* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial', sans-serif;
}
.imgtip-container {
position: relative;
width: 100%;
aspect-ratio: 16 / 9;
background: url("https://coposports.com/wp-content/uploads/2026/08/ScreenShot_2026-08-13_104625_906.jpg") center / cover no-repeat;
overflow: hidden;
margin: 0 auto;
}
.imgtip-group {
position: absolute;
transform: translate(-50%, -50%);
z-index: 5;
}
.imgtip-group[data-pos="1"] {
top: 22%;
left: 83%;
}
.imgtip-group[data-pos="2"] {
top: 44%;
left: 70%;
}
.imgtip-group[data-pos="3"] {
top: 63%;
left: 30%;
}
.imgtip-group[data-pos="4"] {
top: 68.5%;
left: 79%
}
.imgtip-group:hover {
z-index: 99 !important;
}
.imgtip-point {
width: 18px;
height: 18px;
border-radius: 50%;
background: #f5a41c;
cursor: pointer;
transition: box-shadow 0.2s;
position: relative;
z-index: 6;
}
.imgtip-point::before,
.imgtip-point::after {
content: "";
position: absolute;
inset: -2px;
border-radius: 50%;
background: #f5a41c;
opacity: 0;
transform: scale(1);
pointer-events: none;
box-shadow: 0 0 0 0 rgba(245, 164, 28, 0.35);
}
.imgtip-point::before {
animation: ripple-1 1.8s ease-out infinite;
animation-delay: 0s;
}
.imgtip-point::after {
animation: ripple-1 1.8s ease-out infinite;
animation-delay: 0.9s;
}
@keyframes ripple-1 {
0% {
transform: scale(1);
opacity: 0.55;
box-shadow: 0 0 0 0 rgba(245, 164, 28, 0.35);
}
40% {
opacity: 0.25;
}
100% {
transform: scale(2.8);
opacity: 0;
box-shadow: 0 0 0 12px rgba(245, 164, 28, 0);
}
}
.imgtip-circle-preview {
position: absolute;
width: 130px;
height: 130px;
border-radius: 50%;
overflow: hidden;
pointer-events: none;
opacity: 0;
transform: scale(0.85);
transition: opacity 0.25s ease, transform 0.25s ease;
background: #eaeef3;
z-index: 10;
border: 3px solid #ffffff;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
}
.imgtip-circle-preview img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.imgtip-text-desc {
position: absolute;
min-width: 220px;
max-width: 360px;
padding: 12px 18px;
background: rgba(255, 255, 255, 0.75);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
color: #1f2a3a;
border-radius: 10px;
font-size: 14px;
line-height: 1.6;
pointer-events: none;
opacity: 0;
transform: translateY(6px);
transition: opacity 0.25s ease, transform 0.25s ease;
z-index: 11;
border: 1px solid rgba(255, 255, 255, 0.8);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
font-weight: 400;
letter-spacing: 0.01em;
width: 360px;
}
.imgtip-text-desc strong {
font-weight: 700;
display: block;
margin-bottom: 4px;
color: #0b1a2b;
font-size: 15px;
}
.imgtip-group:hover .imgtip-circle-preview {
opacity: 1;
transform: scale(1);
}
.imgtip-group:hover .imgtip-text-desc {
opacity: 1;
transform: translateY(0);
}
@media (max-width: 768px) {
.imgtip-circle-preview,
.imgtip-text-desc {
display: none;
}
.imgtip-point {
width: 24px;
height: 24px;
border-width: 2px;
}
}
@media (max-width: 600px) {
.imgtip-text-desc {
min-width: 140px;
max-width: 180px;
width: 180px;
font-size: 12px;
padding: 8px 14px;
}
.imgtip-circle-preview {
width: 100px;
height: 100px;
}
}
.imgtip-text-desc br {
display: none;
}
.imgtip-text-desc strong + br {
display: none;
}
Bio-based Panel
Waterproof and UV-resistant, stable performance, durable for all scenarios.
Bio-based Parallel Double-layer Keel
This system provides robust support and enhances structural stability and flexibility.
Absorbing Pad
Consistent hardness with excellent damping performance.
Patented Leveling Pad
convenient, corrosion resistant, prevents floor sinking from shim corrosion.
(function() {
const container = document.getElementById('imgtipContainer');
if (!container) return;
const groups = document.querySelectorAll('.imgtip-group');
const PADDING = 14;
const GAP = 10;
const TEXT_GAP = 16;
const DESC_HEIGHT = 0;
function getDescWidth(desc) {
const clone = desc.cloneNode(true);
clone.style.visibility = 'hidden';
clone.style.position = 'absolute';
clone.style.width = 'auto';
clone.style.maxWidth = '360px';
clone.style.minWidth = '220px';
clone.style.padding = '12px 18px';
clone.style.fontSize = '14px';
document.body.appendChild(clone);
let w = clone.offsetWidth;
document.body.removeChild(clone);
return Math.min(Math.max(w, 220), 360);
}
function overlaps(a, b) {
return !(
a.right = b.right ||
a.bottom = b.bottom
);
}
function positionFloaters(group) {
const containerRect = container.getBoundingClientRect();
const groupRect = group.getBoundingClientRect();
const preview = group.querySelector('.imgtip-circle-preview');
const desc = group.querySelector('.imgtip-text-desc');
if (!preview || !desc) return;
const previewSize = preview.offsetWidth || 130;
const descWidth = getDescWidth(desc);
desc.style.width = descWidth + 'px';
const descHeight = desc.offsetHeight || 80;
const pointX =
groupRect.left -
containerRect.left +
groupRect.width / 2;
const pointY =
groupRect.top -
containerRect.top +
groupRect.height / 2;
const cW = containerRect.width;
const cH = containerRect.height;
const candidates = [];
// 右侧
if (
pointX +
GAP +
previewSize +
TEXT_GAP +
descWidth =
PADDING
&&
pointY +
previewSize / 2 =
PADDING
&&
pointY -
previewSize / 2 >=
PADDING
&&
pointY +
previewSize / 2 =
PADDING
&&
pointX -
previewSize / 2 >=
PADDING
&&
pointX +
previewSize / 2 <=
cW - PADDING
) {
candidates.push('up');
}
// 下侧
if (
pointY +
GAP +
previewSize +
TEXT_GAP +
descHeight =
PADDING
&&
pointX +
previewSize / 2 0
? candidates[0]
: 'right';
let preTop = 0;
let preLeft = 0;
let descTop = 0;
let descLeft = 0;
switch (direction) {
case 'right':
preTop =
-previewSize / 2;
preLeft =
GAP;
descTop =
preTop + 8;
descLeft =
preLeft +
previewSize +
TEXT_GAP;
break;
case 'left':
preTop =
-previewSize / 2;
preLeft =
-previewSize -
GAP;
descTop =
preTop + 8;
descLeft =
preLeft -
descWidth -
TEXT_GAP;
break;
case 'up':
preTop =
-previewSize -
GAP;
preLeft =
-previewSize / 2;
descTop =
preTop -
descHeight -
TEXT_GAP;
descLeft =
preLeft +
previewSize / 2 -
descWidth / 2;
break;
case 'down':
preTop =
GAP;
preLeft =
-previewSize / 2;
descTop =
preTop +
previewSize +
TEXT_GAP;
descLeft =
preLeft +
previewSize / 2 -
descWidth / 2;
break;
}
function clamp(value, min, max) {
return Math.min(
Math.max(value, min),
max
);
}
const preMinX =
PADDING -
pointX;
const preMaxX =
cW -
PADDING -
previewSize -
pointX;
const preMinY =
PADDING -
pointY;
const preMaxY =
cH -
PADDING -
previewSize -
pointY;
preLeft =
clamp(
preLeft,
preMinX,
preMaxX
);
preTop =
clamp(
preTop,
preMinY,
preMaxY
);
const descMinX =
PADDING -
pointX;
const descMaxX =
cW -
PADDING -
descWidth -
pointX;
const descMinY =
PADDING -
pointY;
const descMaxY =
cH -
PADDING -
descHeight -
pointY;
descLeft =
clamp(
descLeft,
descMinX,
descMaxX
);
descTop =
clamp(
descTop,
descMinY,
descMaxY
);
const preRect = {
left:
pointX +
preLeft,
right:
pointX +
preLeft +
previewSize,
top:
pointY +
preTop,
bottom:
pointY +
preTop +
previewSize
};
const descRect = {
left:
pointX +
descLeft,
right:
pointX +
descLeft +
descWidth,
top:
pointY +
descTop,
bottom:
pointY +
descTop +
descHeight
};
if (overlaps(preRect, descRect)) {
// 右侧
if (
preRect.right +
TEXT_GAP +
descWidth =
PADDING
) {
descLeft =
preRect.left -
TEXT_GAP -
descWidth -
pointX;
// 下侧
} else if (
preRect.bottom +
TEXT_GAP +
descHeight =
PADDING
) {
descTop =
preRect.top -
TEXT_GAP -
descHeight -
pointY;
}
descLeft =
clamp(
descLeft,
descMinX,
descMaxX
);
descTop =
clamp(
descTop,
descMinY,
descMaxY
);
}
preview.style.top =
preTop + 'px';
preview.style.left =
preLeft + 'px';
desc.style.top =
descTop + 'px';
desc.style.left =
descLeft + 'px';
}
function refreshAllTips() {
groups.forEach(function(group) {
positionFloaters(group);
});
}
setTimeout(
refreshAllTips,
80
);
setTimeout(
refreshAllTips,
300
);
let resizeTimer;
window.addEventListener(
'resize',
function() {
clearTimeout(resizeTimer);
resizeTimer =
setTimeout(
refreshAllTips,
150
);
}
);
window.addEventListener(
'load',
function() {
setTimeout(
refreshAllTips,
200
);
setTimeout(
refreshAllTips,
600
);
}
);
window.repositionImgTips =
refreshAllTips;
})();