PointerLock API 实现全景漫游的核心是隐藏光标并监听 movementX/Y 增量驱动 yaw/pitch 旋转,需用户点击触发锁定、配合 WebGL 渲染全景图、限制 pitch 范围、处理退出逻辑,并注意移动端适配与数值溢出。

使用 PointerLock API 实现沉浸式全景漫游,核心不是“锁住鼠标”,而是通过隐藏光标 + 持续监听鼠标移动增量,驱动视角水平(yaw)和垂直(pitch)旋转,从而模拟第一人称自由环视。它必须配合 WebGL(如 Three.js)或 CSS 3D(较简单但能力有限)渲染球面/立方体全景图,且需用户主动触发锁定(点击/按键),不能自动启用。
1. 基础准备:获取容器、请求指针锁定
选一个全屏 `
- HTML 中设置一个可点击的全景容器:<div id="pano-container"></div>
- JS 中监听点击并请求锁定:
document.getElementById('pano-container').addEventListener('click', () => {
document.body.requestPointerLock();
}); - 监听锁定成功/失败事件:
document.addEventListener('pointerlockchange', () => {
if (document.pointerLockElement === document.body) {
// 已锁定,开始监听 mousemove
}
});
document.addEventListener('pointerlockerror', () => console.error('锁定失败'));
2. 捕获鼠标移动并计算视角偏移
锁定后,`mousemove` 事件的 `movementX` / `movementY` 属性给出相对于上一帧的像素偏移量(不受系统鼠标加速度影响),直接用于更新 yaw 和 pitch。
- 定义两个变量存储角度:let yaw = 0, pitch = 0;
- 在 `mousemove` 中累加偏移(建议乘以灵敏度系数,如 0.002):
document.addEventListener('mousemove', (e) => {
yaw += e.movementX * 0.002;
pitch -= e.movementY * 0.002; // 注意取负,让鼠标下移时视角下俯
}); - 限制 pitch 范围(避免翻转),例如:
pitch = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, pitch));
3. 渲染全景场景(以 Three.js 为例)
有了 yaw/pitch,即可构建相机旋转矩阵,应用到全景球体或立方体贴图上。Three.js 提供了简洁方式:
立即学习“前端免费学习笔记(深入)”;
- 创建球面几何体(或使用 THREE.CubeCamera)加载全景图;
- 将相机的旋转设为:
camera.rotation.y = yaw;
camera.rotation.x = pitch; - 关键:确保相机始终位于原点(position.set(0,0,0)),且无父级变换干扰;
- 每帧调用 renderer.render(scene, camera) 更新画面。
4. 退出与恢复控制
用户按 ESC 键会自动退出锁定,此时应重置交互状态,并提示重新点击进入。也可主动调用 document.exitPointerLock()。
- 监听 `pointerlockchange` 判断是否已退出;
- 监听 `keydown` 检测 Escape:
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && document.pointerLockElement) {
document.exitPointerLock();
}
}); - 退出后暂停视角更新逻辑,避免空转;可显示“点击画面继续漫游”提示。
不复杂但容易忽略:PointerLock 不提供惯性滑动或触摸支持,移动端需另配 touchmove + requestFullscreen;全景图分辨率要足够高,否则旋转时边缘拉伸明显;yaw 应对 2π 取模防止数值溢出。



















