问题描述
Mask QC 绘图时,画笔拖动与侧边滚动条发生冲突,滚动位置会跳回或漂移;此前叠加 touch-action:none、overflow-anchor:none 等 CSS 限制后仍未解决。
根因(已从当前 index(9).html 确认)
pointerdown调用lockCanvasScroll(),记录右侧.detail.scrollTop和window.scrollX/Y。- 每次画笔拖动触发
pointermove时,都调用restoreCanvasScroll(),强制把滚动位置恢复到按下鼠标时的快照;其中还会反复执行window.scrollTo()。 - 画布指针捕获、绘图状态和滚动快照耦合,导致绘图期间滚动位置被强行回滚。
- 原布局使用
height/min-height: calc(100vh - 67px),假设顶部工具栏始终为 67px;工具栏换行或展开目录设置后,页面高度计算可能产生额外溢出。
修复方案(本地修复版已完成)
- 完全移除
canvasScrollSnapshot、lockCanvasScroll()、restoreCanvasScroll(),绘图事件不再写入或回滚任何滚动容器的位置。 - 引入
activePointerId,只允许当前主指针驱动笔画;其他指针不会结束或污染当前笔画。 - 将活动指针的移动、抬起、取消监听放在 window 层,配合 canvas pointer capture,指针移出画布后笔画仍能连续处理;捕获不可用时仍可由 window 事件维持操作。
- 窗口失焦或页面隐藏时清理活动指针状态,避免拖动状态卡住。
- 页面改为基于实际视口高度的 flex 布局;桌面端由左右面板独立滚动,平板/手机由应用容器滚动,不再依赖固定的 67px 顶栏高度。
server(6).py不需要修改:本次故障在前端指针/滚动控制层,服务端接口不参与滚动事件。
回归测试
使用 Chromium + Playwright,以 800×600 测试图片和本地 API 模拟响应,对真实页面 DOM、Pointer Events 和滚动容器执行交互测试:
- 复现旧版问题:右侧滚动位置先设为 80,拖动画笔期间改为 150,旧版 pointermove 会将其重置为 80。
- 修复版同一操作保持在 150,画笔像素写入成功(目标像素 alpha=255)。
- 画笔结束后活动指针释放,绘图状态归零。
- 空格 + 拖动只平移画布,画笔计数不增加。
- 右侧面板滚轮正常滚动,画布缩放值不变。
- 手机布局可在应用容器内滚动(scrollHeight 2840 / clientHeight 777)。
- 平板布局可在应用容器内滚动(scrollHeight 2418 / clientHeight 733)。
- 展开目录设置后,应用区域自动收缩;页面 body 未产生额外滚动(clientHeight 与 scrollHeight 均为 700)。
- JavaScript
node --check通过;Python 服务端py_compile通过;自动化页面无 JavaScript 异常。
测试限制:无头 Chromium 使用覆盖式滚动条,因此未能模拟 Windows 系统可见滚动条滑块的物理拖动;需要在 Windows Chrome/Edge 上做最后的人工验收。
验收标准
- 按住左键连续涂白、擦黑,笔迹不丢失、不跳点。
- 绘图时不再自动修改右侧面板或页面滚动位置。
- 直接拖动侧边滚动条时不得误触发画笔。
- 空格拖动画布与画笔绘制互不串扰。
- 桌面、平板、手机布局均无整页意外漂移。
本次本地修复文件:index(9)_画笔滚动冲突彻底修复.html。该文件已完成上述自动化交互测试;尚未提交到仓库实际页面文件。