Element.requestPointerLock 是浏览器用于锁定鼠标指针至指定元素的底层API,隐藏光标、禁用移动限制并提供原始位移delta;需用户手势触发,成功后通过document级mousemove监听movementX/Y,响应pointerlockchange/error事件,并做好兼容性降级。

Element.requestPointerLock 是浏览器提供的一项底层 API,用于将鼠标指针锁定到指定元素内,隐藏光标、禁用默认移动限制,并持续接收未经处理的原始位移 delta(即 mousemove 事件中的 movementX 和 movementY)。它不等于“全屏”或“焦点锁定”,而是专为第一人称视角、3D 控制、绘图工具等需要连续、高精度、无边界指针输入的场景设计。
触发锁定需满足用户手势条件
出于安全与用户体验考虑,requestPointerLock 只能在由用户显式交互(如 click、tap、keydown)触发的事件处理函数中调用。不能在页面加载、定时器、异步回调或非用户驱动的生命周期钩子中直接调用,否则会静默失败。
- ✅ 正确做法:绑定 button 的
click事件,在回调中调用canvas.requestPointerLock() - ❌ 错误做法:在
setTimeout(() => el.requestPointerLock(), 100)或onload中调用 - ⚠️ 注意:若元素不可见、被遮挡、未插入 DOM 或 CSS 设置了
pointer-events: none,也会导致锁定失败
监听并处理原始指针位移
锁定成功后,鼠标不再触发常规坐标变化(clientX/clientY 停止更新),但会持续派发 mousemove 事件,其中 movementX 和 movementY 提供的是本次事件与上一次之间的**相对像素位移量**(绕过系统鼠标加速度和 DPI 缩放,接近硬件级原始数据)。
- 在 document 级别监听
mousemove,避免因目标元素失焦丢失事件 - 检查
event.movementX !== 0 || event.movementY !== 0再执行逻辑,过滤空事件 - 注意:该位移是累加值,无需自行做差分;但需手动积分(如用于视角旋转时,每次 += movementX * sensitivity)
响应锁定状态变更与异常退出
锁定不是永久的。用户按 Esc、切换标签页、收到系统级弹窗、或调用 document.exitPointerLock() 都会导致解锁。应监听 pointerlockchange 和 pointerlockerror 事件以及时响应。
-
pointerlockchange:在 document 上监听,通过document.pointerLockElement === targetEl判断当前是否处于锁定状态 -
pointerlockerror:发生权限拒绝或无效调用时触发,适合提示用户重试或降级交互方式 - 解锁后应重置相关状态(如旋转角度、拖拽标志位),防止下次锁定时继承错误偏移
兼容性与降级策略建议
现代 Chromium、Firefox、Safari(macOS 15.4+ / iOS 17.4+)均已支持,但移动端支持有限(多数 Safari on iOS 仍不支持)。生产环境应做渐进式增强:
- 先检测
'pointerLockElement' in document或el.requestPointerLock是否存在 - 不支持时,可回退为基于
mousedown → mousemove → mouseup的受限拖拽模式,并用getBoundingClientRect()模拟方向感 - 对 WebXR 场景,优先使用
XRSession.inputSources,仅在非 XR 模式下启用 pointer lock 作为补充控制
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











