Files
lsky-pro-docker/patches
mole404 4085642695 fix(viewer): 切图动画起点固定为屏幕中心(强制回流),并删掉上一版无效的摘类补丁
老师反馈上一版没修好(附真机截图)。按 Claude 的静态分析复核后确认,根因是 view() 的时序竞态:
  · view() 每次都新建一个 <img>:先写成"屏幕中心的点"(宽高 0 + margin 居中),读自然尺寸后
    再加 viewer-transition 写最终尺寸,靠 CSS 过渡补间。
  · CSS 过渡的起点 = 浏览器"上一次真正渲染过的样式"。第 1 步默认样式是"满宽贴顶",第 2 步是
    "中心点",第 3 步是最终值。哪一帧被渲染过决定动画从哪开始:第 2、3 步之间有帧 ⇒ 从中心
    长出来;只渲染到第 1 步 ⇒ 从屏幕上方飞入;一帧都没渲染 ⇒ 无动画直接出现。取决于图片是否
    缓存、网络快慢、主线程是否空闲 —— 这就是"没规律"的来源。
  · 上一版在 pointerup 里 viewer.image.classList.remove('viewer-transition') 无效:view() 新建
    的是另一个 <img>,且 load() 会按 options.transition 给新图重新加类。已删除该段及错误注释
    (原注释"从上一张图 margin 滑过来"也不成立)。

修法(Claude 方案 A):包一层 viewer.initImage,在它读自然尺寸之前强制回流一次
(void viewer.image.offsetWidth),把"中心点"提交为已渲染样式 ⇒ 起点恒为屏幕中心。
覆盖手指滑动、缩略图条、键盘、底部按钮等所有切图路径(都在 view() 内)。

本机实测(延迟图片响应 + 限速,模拟"未缓存的大图",即 Claude 给的复现法):
  切换瞬间 top 与稳定后 top 的差值:A 组 0px / 0px,C 组重跑 0px / 0px ✓
  对照组(剥掉补丁)未取得有效数据(生成对照版本时脚本把页面切坏),"无补丁会飞"留待真机确认。
本机 9 套 jsdom 测试全绿。
2026-10-03 14:49:22 +08:00
..