React中Three.js平面Raycaster鼠标追踪滚动偏移问题咨询
问题:Three.js Raycaster 鼠标交互位置在页面滚动后错位
在React的useEffect中创建Three.js平面,通过Raycaster实现鼠标交互效果:全屏状态下功能正常,但页面滚动至半屏位置后,鼠标置于屏幕中间时,交互效果出现在平面半上方区域;鼠标位于平面底部、屏幕中间时,高亮的仍是屏幕中间对应的平面区域。
当前鼠标位置计算代码:
window.addEventListener('mousemove', (event) => { mouse.x = (event.clientX / window.innerWidth) * 2 - 1 mouse.y = -(event.clientY / window.innerHeight) * 2 + 1 })
Raycaster调用代码:
requestAnimationFrame(animate) renderer.render(scene, camera) raycaster.setFromCamera(mouse, camera)
解决方案
问题根源:原代码使用window.innerHeight和event.clientY计算鼠标坐标,是基于整个浏览器视口的,但页面滚动后,Three.js渲染的Canvas元素顶部与视口顶部产生偏移,导致Y轴坐标映射错误。
修改鼠标坐标计算逻辑,基于Canvas元素的实时视口位置计算相对坐标:
window.addEventListener('mousemove', (event) => { const canvas = renderer.domElement; const rect = canvas.getBoundingClientRect(); // 计算鼠标在Canvas内部的相对位置,再转换为Three.js需要的标准化设备坐标 mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; });
关键说明
getBoundingClientRect()会返回Canvas元素在当前视口中的位置和尺寸(包含滚动偏移后的实时数据)- 通过
event.clientX - rect.left得到鼠标在Canvas左侧的偏移距离,除以Canvas宽度后转换为0-1范围,再转为Three.js的标准化设备坐标(-1到1) - Y轴计算同理,注意Three.js的Y轴向上为正,所以需要取反
如果Canvas元素的尺寸会随窗口变化,还需监听resize事件,更新相机的aspect比例并重新计算投影矩阵:
window.addEventListener('resize', () => { const canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(canvas.clientWidth, canvas.clientHeight); });
内容的提问来源于stack exchange,提问作者Jack Duffy
相关产品推荐
相关产品推荐

