# 拼图运行时拖动跟手延迟修复 日期:`2026-04-27` ## 1. 背景 拼图玩法运行时已经支持单块拖动、合并块整体拖动与拆分,但实测拖动时拼块会明显慢于手指或鼠标,表现为“拖着走但始终落后半拍”,尤其在移动端更明显。 本次目标只修复前端拖动跟手延迟,不改变拼图交换、合并、拆分、通关等玩法规则。 ## 2. 根因 本轮定位到拖动延迟主要来自两个前端渲染问题: 1. `pointermove` 每一帧都调用 `setDragState`,导致整个 `PuzzleRuntimeShell` 和整盘拼图格子持续重渲染。 2. 拼块节点默认挂了 `transition`,拖动过程中的 `transform` 会被浏览器当成缓动动画处理,视觉上进一步放大“慢半拍”。 这两个问题叠加后,即使后端或本地运行态裁决没有延迟,前端拖动视觉仍然会滞后。 ## 3. 修复口径 ### 3.1 拖动视觉更新改为直写 DOM 拖动中的位移不再依赖 React state 持续驱动,而是改成: 1. `pointerdown` 只记录起点和 pointer 信息。 2. 超过拖动阈值后,只做一次 `setDraggingPieceId` 用于切换拖动态样式。 3. 后续 `pointermove` 通过 `requestAnimationFrame` 合帧,把位移直接写入目标拼块或合并块容器的 `style.transform`。 这样可以避免每一帧都触发整盘 React 重渲染。 ### 3.2 收紧过渡属性 拼块节点不再使用包含 `transform` 的通用 `transition`,只保留颜色、边框、阴影、透明度等非位移动画属性,避免拖动中的 transform 被浏览器插值缓动。 ### 3.3 裁决边界保持不变 本次只优化拖动阶段的视觉反馈: 1. `pointerup` 后仍然走现有 `onDragPiece`。 2. 单块交换、拖到合并块后拆分、合并块整体重排,继续沿用当前本地运行态规则。 3. 不新增前端本地裁决,不把玩法真相从既有运行态实现中分叉出去。 ### 3.4 点击触觉反馈 移动端用户每次按下可交互拼图片时,需要触发一次短促手机震动: 1. 震动触发点放在 `pointerdown`,让点击选中、按住准备拖动与拖起都有一致手感。 2. 同一次按下会话只触发一次震动,后续连续移动不重复震动。 3. 使用浏览器标准 `navigator.vibrate([12])`,不支持震动能力的设备静默跳过。 4. 该反馈只属于前端表现层,不影响拖拽落点、交换、合并、拆分与通关判定。 ## 4. 验收标准 1. 单块拖动时拼块视觉位置应紧跟手指或鼠标,不再出现明显缓动拖尾。 2. 合并块整体拖动时,组容器应同步跟手移动。 3. 点击选中与拖动阈值判定仍保持原语义,不因为优化误触发交换。 4. 运行时现有结算弹窗、排行榜和下一关入口不受影响。 5. 定向测试覆盖拖动提交坐标的行为,并运行编码检查确保中文文档未被写坏。 6. 移动端点击拼图片时立即触发一次短震,同一次按下后的连续移动不重复触发。