diff --git a/src/components/Index.vue b/src/components/Index.vue index 9a50685..f1bebb1 100644 --- a/src/components/Index.vue +++ b/src/components/Index.vue @@ -95,7 +95,7 @@ const isDone = ref(false) const isShowDone = ref(false) const xflIconRef = ref(null) const currentProgress = ref(0) // 当前进度百分比 -const debounce = ref(false) +const debounce = ref(true) let animation = null // 视频库 @@ -219,12 +219,21 @@ const convertCoordinates = (point) => { const svg = document.querySelector('.path-svg') const pt = svg.createSVGPoint() - pt.x = point.x - pt.y = point.y - return pt.matrixTransform(svg.getScreenCTM().inverse()) + // 添加1px偏移修复iOS精度问题 + pt.x = point.x + 1 + pt.y = point.y + 1 + + // 考虑设备像素比 + const dpr = window.devicePixelRatio || 1 + const screenPoint = pt.matrixTransform(svg.getScreenCTM().inverse()) + + return { + x: Math.round(screenPoint.x * dpr), + y: Math.round(screenPoint.y * dpr) + } } -const initSvgAnimation = () => { +const initSvgAnimation = async () => { // 获取SVG元素 const svg = document.querySelector('.path-svg') const path = document.querySelector('#motionPath') @@ -254,10 +263,19 @@ const initSvgAnimation = () => { force3D: true // 启用GPU加速 }) + // 等待2帧确保渲染完成 + await new Promise(resolve => requestAnimationFrame(resolve)) + await new Promise(resolve => requestAnimationFrame(resolve)) + + // 强制重排 + + void path.offsetHeight + // 初始定位优化 gsap.set(xflIconRef.value, { x: convertCoordinates(path.getPointAtLength(0)).x, - y: convertCoordinates(path.getPointAtLength(0)).y + y: convertCoordinates(path.getPointAtLength(0)).y, + force3D: true }) @@ -368,6 +386,7 @@ const animationFn = () => { repeat: -1, yoyo: true, ease: "bounce.out()", + }) } }); @@ -426,8 +445,11 @@ const animationFn = () => { x: 20, duration: 1, ease: "back.inOut(3)", - }) + onComplete: () => { + debounce.value = false + } + }) @@ -650,22 +672,24 @@ const animationFn = () => { .line-box { @include pos(348px, 1048px, 185px, 583px); - overflow: visible; + // overflow: visible; pointer-events: none; /* 确保元素可超出容器 */ .path-svg { width: 100%; height: 100%; - transform: translateZ(0); + // transform: translateZ(0); opacity: 0; /* 修复渲染层级 */ + backface-visibility: hidden; + /* 修复iOS偏移 */ } .xfl-icon { pointer-events: none; - // position: absolute; + position: absolute; width: 163px; height: 153px; // 以中心放大1.5倍 @@ -686,16 +710,5 @@ const animationFn = () => { } } - // .box { - // width: 30px; - // height: 30px; - // background-color: #42b983; - // position: absolute; - // left: 0; - // top: 0; - // transform: translate(-50%, -50%); - // will-change: transform; - // /* 优化动画性能 */ - // } }