非全屏DIV容器中Three.js raycasting射线检测功能失效如何修复
Three.js 多窗口布局下射线检测失效修复方案
1. 替换偏移量计算方式,使用getBoundingClientRect获取准确坐标
原来的offsetLeft/offsetTop只能获取元素相对于直属父级的偏移,当容器存在多层嵌套时会出现计算偏差。使用getBoundingClientRect()可以直接获取canvas元素相对于浏览器视口的绝对位置,不受嵌套层级影响。
2. 开启射线检测的递归遍历参数
raycaster.intersectObjects方法的第二个参数默认为false,仅检测传入对象本身,不会检测子级网格。如果你的GLTF模型网格存在嵌套结构,需要将该参数设为true开启递归检测。
3. 确认渲染器与相机参数匹配
多窗口布局下需要确保:
- 渲染器尺寸与容器实际尺寸一致,已调用
renderer.setSize(containerWidth, containerHeight)设置 - 相机的宽高比参数与渲染器匹配,修改后已调用
camera.updateProjectionMatrix()更新投影矩阵
修改后的核心代码示例
function onMouseDown( event ) { if ( !DRAWLINE ) return; var raycaster = new THREE.Raycaster(); event.preventDefault(); // 替换为getBoundingClientRect计算准确坐标 const canvasRect = renderer.domElement.getBoundingClientRect(); mouse.x = (( event.clientX - canvasRect.left) / canvasRect.width ) * 2 - 1; mouse.y = - (( event.clientY - canvasRect.top) / canvasRect.height ) * 2 + 1; raycaster.setFromCamera(mouse, camera); // 第二个参数设为true,开启递归检测子网格 var intersects = raycaster.intersectObjects( objects, true ); if ( intersects.length > 0 ) { alert("HIT!"); dot.visible = true; mouse.copy( intersects[0].point ); intersects.length = 0; addPoint(); } else { console.log( "<<NO Intersection!!>>" ); } }
额外排查点
如果上述修改后仍未生效,可按以下顺序排查:
- 检查
objects数组中是否正确存入了所有可交互的网格对象 - 确认页面不存在对canvas元素的CSS缩放、transform变换,如有特殊变换需要额外计算坐标缩放比例
- 打印
mouse.x和mouse.y数值,确认点击模型中心位置时数值接近(0,0),如偏差较大则仍为坐标计算问题
内容的提问来源于stack exchange,提问作者Ringo Work
相关产品推荐
相关产品推荐

