From 8c47a88c790d98fd04ed2b5c3045d041d9dad54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Tue, 29 Sep 2026 15:00:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(viewer):=20=E7=8E=AF=E5=9B=9E=E7=9E=AC?= =?UTF-8?q?=E6=97=B6=E5=9B=9E=E4=BD=8D=E5=BC=BA=E5=88=B6=E9=87=8D=E6=8E=92?= =?UTF-8?q?=E2=80=94=E2=80=94=E5=90=8C=E5=B8=A7=E6=81=A2=E5=A4=8D=E8=BF=87?= =?UTF-8?q?=E6=B8=A1=E5=AF=BC=E8=87=B4=E5=8F=AF=E8=A7=81=E5=8F=8D=E5=90=91?= =?UTF-8?q?=E9=95=BF=E6=BB=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 真浏览器样式计算时过渡仍在,回跳变成动画;强制 offsetWidth 重排 + 双 rAF 确保无过渡状态先绘制一帧(测试假时钟下掩盖的根因)。 Co-Authored-By: Claude Code --- apps/viewer/src/components/ads/AdCarousel.vue | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/viewer/src/components/ads/AdCarousel.vue b/apps/viewer/src/components/ads/AdCarousel.vue index d1cb670..22746db 100644 --- a/apps/viewer/src/components/ads/AdCarousel.vue +++ b/apps/viewer/src/components/ads/AdCarousel.vue @@ -34,6 +34,8 @@ const SLIDE_MS = 450; const trackPos = ref(1); /** 瞬时回位期间关闭过渡(transform 跳转不产生动画)。 */ const noTransition = ref(false); +/** 轨道元素(snapBack 强制重排用)。 */ +const trackEl = ref(null); let snapTimer: ReturnType | undefined; /** 轨道帧序列:{ ad, real }——real 为真实 index,克隆帧为 null。 */ @@ -57,9 +59,16 @@ function clearSnapTimer(): void { async function snapBack(): Promise { noTransition.value = true; trackPos.value = current.value + 1; - // 同帧应用「关过渡 + 新 transform」,下一拍恢复过渡(transform 已就位不触发)。 await nextTick(); - noTransition.value = false; + // 强制重排 + 双 rAF:确保「无过渡 + 新 transform」先完成一次绘制,再恢复 + // 过渡。若在同一帧内直接恢复(浏览器样式计算时过渡仍在),回跳会变成可见 + // 的反向长滚(2026-09-29 线上反馈根因;测试假时钟下恰好掩盖)。 + void trackEl.value?.offsetWidth; + requestAnimationFrame(() => { + requestAnimationFrame(() => { + noTransition.value = false; + }); + }); } /** 移动到真实 index(圆点/滑动/自动轮播共用):环回走克隆位 + 到位后回跳。 */ @@ -170,6 +179,7 @@ function openAd(ad: PublicAd): void { 令环回也是单帧宽自然滑入(到位后关过渡瞬时回位,见 script);仅活跃 真实帧可聚焦;错误上报只看活跃帧。 -->