s

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); //告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
}

posted @ 2022-09-30 16:48  努力不搬砖的iori  阅读(4901)  评论(4编辑  收藏  举报