Element.setPointerCapture 可确保拖拽时指针移出元素边界后事件仍持续派发,需在 pointerdown 中校验 button 和 pointerType 后调用,并在 pointerup/pointercancel 中释放,避免泄漏。
在拖拽交互中,使用 Element.setPointerCapture 可以确保即使鼠标/手指移出目标元素边界,事件仍持续派发给该元素——这是解决“拖拽中途丢失指针”问题的核心机制。
默认情况下,pointermove 和 pointerup 事件只在指针位于触发 element(如拖拽手柄)上时才触发。一旦快速拖动导致指针移出元素区域(比如划出窗口、经过滚动条、被其他元素遮挡),浏览器会立即触发 pointercancel 或直接停止派发 pointermove,拖拽逻辑中断。调用 setPointerCapture 后,该指针的后续事件将强制路由到当前元素,直到显式释放或指针抬起。
必须在 pointerdown 事件中调用,且仅对有效指针触发:
event.button === 0(仅左键,避免右键/中键干扰)event.pointerType !== 'pen' || event.buttons === 1
element.addEventListener('pointerdown', (e) => { if (e.button !== 0) return; e.target.setPointerCapture(e.pointerId); // 启动拖拽状态机}); capture 不会自动清理,必须主动释放,否则造成内存泄漏或后续事件错乱:
pointerup 和 pointercancel 中调用 e.target.releasePointerCapture(e.pointerId)
pointerleave 时**不释放**——这正是 capture 要覆盖的行为;但可在此记录“指针已离开可视区”,用于 UI 反馈Chrome/Firefox/Edge 支持良好;Safari 15.4+ 开始支持,旧版需降级为 mouse capture(setCapture())或监听全局 mousemove;移动端注意:
pointerId 在一次触摸过程中保持唯一,可安全用于状态映射touchstart 中混用 setPointerCapture——应统一使用 pointer 事件流pointercancel 触发较迟,建议加 50ms 超时兜底释放