【问题标题】:ThreeJS Raycaster doesn't find intersected objects if canvas isn't full screen如果画布不是全屏,ThreeJS Raycaster 不会找到相交的对象
【发布时间】:2018-07-01 02:21:09
【问题描述】:

我使用 ThreeJS 在 canvas 元素中创建了一个包含多个对象的场景。如果用户单击它,我现在想更改对象的材质颜色。

我的 Angular 5 组件的摘录,它包含所有 ThreeJS 内容:

public onMouseDown(event: MouseEvent) {
    console.log("onMouseDown");
    event.preventDefault();

    var rayCaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    mouse.x = (event.clientX / this.renderer.domElement.clientWidth) * 2 - 1;
    mouse.y = -(event.clientY / this.renderer.domElement.clientHeight) * 2 + 1;

    rayCaster.setFromCamera(mouse, this.camera);

    var intersects = rayCaster.intersectObjects(this.scene.children);

    console.log("Scene has " + obj.length + " objects");
    console.log(intersects.length + " intersected objects found");

    intersects.forEach((i) => {
      i.object.material =
        new THREE.MeshBasicMaterial({color: 0xf1f11f});
    });
    this.render();
}

问题是鼠标坐标不正确,由于canvas 元素和文档外边缘之间的距离。每当我在场景中单击时,鼠标右侧的对象都会获得新的材质颜色。

一些信息: this.renderer.domElement.clientWidth 保存画布元素的宽度

如果canvas元素不是全屏,如何计算正确的鼠标坐标?

【问题讨论】:

  • 这不是一个 three.js 问题,而是一个 JavaScript/布局问题。
  • 相关:见stackoverflow.com/questions/13542175/… 另外,不要不必要地实例化新的Raycater、Vector2、Material。
  • @WestLangley 如何在不实例化的情况下使用 Raycaster?您的意思是在函数内部使用全局 Raycaster 对象而不是本地对象?
  • 是的,或者使用闭包,这样单个 Raycaster 实例就可以重复使用。更改现有材质的颜色;不要分配新材料。

标签: three.js


【解决方案1】:

如果您的流程中断(您的容器浮动或手动定位),那么clientX/clientY 将报告“错误”值(相对于页面,而不是您可能期望的容器)。 offsetX/offsetY 属性通过报告与触发事件的容器相关的值来解决此问题。

根据 MDN,support is limited,但我刚刚(01/22/2018)的测试显示最新版本的 Chrome、Firefox、Edge 和 IE 都报告了正确的值*。请注意,有些浏览器会报告整数值,而其他浏览器可能会报告双精度值。

*这可能不适用于 Safari 或移动浏览器。 YMMV。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-02
    • 2016-08-21
    • 2014-03-03
    • 2018-08-29
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多