threejs-模型点击以及添加CSS2DObject
模型点击事件网上教程挺多的,官网好像也有demo,这里我就只记录我碰到的问题以及解决方案:
首先要清楚一件事,就是模型的展示需要一个容器,当这个容器是body|window 和 非全屏的容器时,是有区别的,全屏的坐标拾取方法:
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
非全屏:
let getBoundingClientRect = container.getBoundingClientRect() mouse.x = ((event.clientX - getBoundingClientRect .left) / container.offsetWidth) * 2 - 1; mouse.y = -((event.clientY - getBoundingClientRect .top) / container.offsetHeight) * 2 + 1;
非全屏,且有存在缩放问题:【我这里用的一个框架, 会根据屏幕的比例和浏览器的缩放比例去自动适应。达到布局不变。容器位置看起来也不变】当存在缩放且不是全局容器时:
let div3DLeft = (window.innerWidth - renderer.domElement.clientWidth * zoom) / 2; // 由于容器位置看起来不变,所以直接用window来计算。 let div3DTop = window.innerHeight - renderer.domElement.clientHeight * zoom; // 这里获取容器距离 window的 left 和top, // renderer.domElement.clientWidth * zoom, 容器的实际大小会被缩放, 所以需要乘以 缩放比例zoom mouse.x = ((event.clientX - div3DLeft) / (renderer.domElement.clientWidth * zoom)) * 2 -1; mouse.y = -((event.clientY - div3DTop) /(renderer.domElement.clientHeight * zoom)) *2 +1;
后续来了:之前这个公式可能是不对的, 我测试过了, 存在缩放,位置会存在很大偏差。
上面可以看出,存在缩放的时候,鼠标点击的位置和和通过光线投射获取到的实际位置偏差很大。
至于上面的错误公式,是我在有一个项目中测试过的,那个项目可以,虽然会有一点点的偏差,但是基本上我觉得还能用。到了目前这项目就不行了。
至于如何解决这个问题。看这里
添加CSS2DObject
分为三个步骤:
1:创建css2dobject 【const divLabel = new CSS2DObject(div);】
labelRenderer.setSize(dom.clientWidth, dom.clientHeight);【设置大小和属性】
labelRenderer.domElement.style.position = "absolute";
labelRenderer.domElement.style.top = "0px";
labelRenderer.domElement.style.outline = "none";
labelRenderer.domElement.style.zIndex = "-999";
2. 创建 渲染器 render 【labelRenderer = new CSS2DRenderer();】,添加到容器下:【dom.appendChild(labelRenderer.domElement);】
3.控制器:【controls = new OrbitControls(
camera,
labelRenderer.domElement
);】
4.渲染 【labelRenderer.render(scene, camera);】
5. 更新 【function animate() {
//更新控制器
render();
//更新性能插件
controls.update();
requestAnimationFrame(animate); //告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
}
】