使用PointerLockControls时如何启用鼠标点击与光标显示?
解决PointerLockControls下Three.js艺术品点击无响应的问题
问题原因
Three.js的Mesh并非DOM元素,无法直接通过addEventListener('click')绑定点击事件;加上PointerLockControls锁定鼠标后,原生鼠标事件不会关联到3D对象,必须通过**射线检测(Raycaster)**判断点击是否命中目标模型。
解决方案
通过射线检测实现3D对象的点击交互,具体步骤如下:
- 初始化射线检测工具与鼠标坐标向量
- 监听鼠标点击事件,点击时计算射线与场景对象的交点
- 命中艺术品时触发弹窗逻辑
修改后的完整代码
// 初始化射线检测工具和鼠标向量 const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); let art2Texture = new THREE.TextureLoader().load('img/art/2.png'); const art2Geometry = new THREE.PlaneBufferGeometry(8, 8); const art2Material = new THREE.MeshBasicMaterial({ map: art2Texture }); const art2 = new THREE.Mesh(art2Geometry, art2Material); art2.position.z = -49.9; art2.position.y = 3.5; art2.userData = { name: 'Artwork 2', description: 'This is the description of Artwork 2', link: 'https://here-goes-the-link', }; // 监听鼠标点击事件(绑定到document,适配PointerLockControls的鼠标锁定状态) document.addEventListener('click', (event) => { // 将屏幕鼠标坐标转换为Three.js标准化设备坐标 mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; // 更新射线的起点与方向(基于相机视角) raycaster.setFromCamera(mouse, camera); // 检测射线与场景中所有对象的交点 const intersects = raycaster.intersectObjects(scene.children); // 遍历交点,判断是否命中目标艺术品 for (let i = 0; i < intersects.length; i++) { const hitObject = intersects[i].object; if (hitObject.userData.name === 'Artwork 2') { console.log('Artwork 2 clicked!'); const popup = document.createElement('div'); popup.className = 'popup'; const title = document.createElement('h2'); title.textContent = hitObject.userData.name; const description = document.createElement('p'); description.textContent = hitObject.userData.description; const link = document.createElement('a'); link.href = hitObject.userData.link; link.target = '_blank'; link.textContent = 'View on OpenSea'; popup.appendChild(title); popup.appendChild(description); popup.appendChild(link); document.body.appendChild(popup); break; // 找到第一个命中对象后停止遍历 } } }); // CSS for the pop-up const popupCSS = ` .popup { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; border: 2px solid black; padding: 16px; width: 300px; text-align: center; z-index: 1; } .popup h2 { margin-top: 0; } .popup a { display: block; margin-top: 16px; } `; const popupStyle = document.createElement('style'); popupStyle.textContent = popupCSS; document.head.appendChild(popupStyle); scene.add(art2);
关键说明
Raycaster通过相机视角与鼠标坐标生成射线,精准检测场景中与射线相交的3D对象- 鼠标坐标需转换为标准化设备坐标(范围[-1,1]),才能匹配Three.js的坐标系逻辑
- 点击事件绑定到
document,适配PointerLockControls锁定鼠标后的事件触发规则 - 可通过
userData自定义属性批量标识艺术品,方便后续扩展多个艺术品的点击交互
内容的提问来源于stack exchange,提问作者Stray Stray
相关产品推荐
相关产品推荐

