如何在ThreeJS中仅将选区内的球体设置为红色?
问题根源
你的代码中球体屏幕坐标的转换逻辑错误,导致坐标偏移计算反向,同时未处理重复选区的颜色重置,这两个问题共同造成了非选区内球体被误设为红色的情况。
解决方案
1. 修正坐标转换逻辑
替换mouseup函数中的坐标计算部分,确保球体的3D位置正确转换为与鼠标坐标统一的文档坐标系:
function mouseup(e) { if (!isOrbitControlEnabled) { var box = document.getElementById("sel_box"); var mxy = getCursorPosition(e); box.style.display = "none"; box.style.width = "0"; box.style.height = "0"; document.onmousemove = function () {}; document.onmouseup = function () {}; mouseUpCoords.x = mxy[0]; mouseUpCoords.y = mxy[1]; console.log("up x y: " + mouseUpCoords.x + " " + mouseUpCoords.y); // 获取容器的文档位置与尺寸 const container = document.getElementById("scene-container1"); const containerRect = container.getBoundingClientRect(); const containerWidth = container.clientWidth; const containerHeight = container.clientHeight; // 重置之前选中球体的颜色(可选,按需启用) selectedMeshes.forEach(sphere => { sphere.material.color.set(defaultMaterial.color); }); selectedMeshes = []; // 遍历球体判断是否在选区内 spheres.forEach((sphere) => { const spherePosition = sphere.position.clone(); const screenPosition = spherePosition.clone().project(camera); // 将标准化设备坐标转换为容器内相对坐标 const containerX = (screenPosition.x + 1) / 2 * containerWidth; const containerY = (-screenPosition.y + 1) / 2 * containerHeight; // 转换为文档坐标(与鼠标坐标坐标系统一) const domX = containerRect.left + containerX + window.scrollX; const domY = containerRect.top + containerY + window.scrollY; // 定义选区边界 const minX = Math.min(mouseDownCoords.x, mouseUpCoords.x); const maxX = Math.max(mouseDownCoords.x, mouseUpCoords.x); const minY = Math.min(mouseDownCoords.y, mouseUpCoords.y); const maxY = Math.max(mouseDownCoords.y, mouseUpCoords.y); // 判断是否在选区内 if ( domX >= minX && domX <= maxX && domY >= minY && domY <= maxY ) { console.log("sphere x y: " + domX + " " + domY); sphere.material.color.set(0xff0000); selectedMeshes.push(sphere); } }); } }
2. 简化鼠标坐标获取函数
getCursorPosition可以直接使用原生pageX/pageY属性,避免手动计算的误差:
function getCursorPosition(e) { e = e || window.event; return [e.pageX, e.pageY]; }
关键说明
- 坐标统一:鼠标事件获取的是文档坐标,球体坐标必须转换为同一坐标系才能准确对比;
- 容器适配:使用容器自身的宽高代替窗口尺寸,确保容器非全屏时坐标计算依然准确;
- 颜色重置:每次选区操作前恢复之前选中球体的默认颜色,避免重复选区导致的颜色残留。
内容的提问来源于stack exchange,提问作者sunShine
相关产品推荐
相关产品推荐

