Files
Genarrative/docs/technical/PUZZLE_RUNTIME_DRAG_RESPONSE_FIX_2026-04-27.md
2026-05-01 00:33:39 +08:00

3.0 KiB

拼图运行时拖动跟手延迟修复

日期: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. 移动端点击拼图片时立即触发一次短震,同一次按下后的连续移动不重复触发。