当带有渲染器的 DOM 元素不在屏幕顶部时移动场景坐标

Moved coordinates of the scene when DOM element with renderer is not at the top of the screen

我遇到了一个问题,我在视图中的 angular 自定义指令中有一个 three.js 场景。在顶部,我有一个导航栏,它总是在那里提供导航和 wiews 之间的切换(还没有异常)。比方说我设置了一个简单的场景(和以前一样多次,但不是 angular),我在场景中放了一个简单的立方体,设置了相机旋转和其他基本的东西。当我尝试按下鼠标击中该对象时,问题就开始了(光线投射器工作得很好),但似乎我的坐标系是从页面顶部开始的(或者我对此没有任何其他解释)。为了更好地理解,我在这里有一个屏幕 ( http://prntscr.com/6r6pnu )。看起来好像对象的真实网格向上移动了一点,并且它的图像呈现为图片所示。我必须是的,我在谷歌上搜索了很多,但关于 angularjs+three.js

的内容并不多

渲染器设置:

 renderer.setSize(window.innerWidth, window.innerHeight);
    element[0].appendChild(renderer.domElement);

其中 element[0] 是我的自定义指令

<input-dir> <canvas> </input-dir>

raycaster 设置:

          var vector = new THREE.Vector3();
      vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
      vector.unproject( camera );

      raycaster.ray.set( camera.position, vector.sub( camera.position ).normalize());

谢谢

我认为问题在于鼠标坐标是相对于浏览器显示的视口而言的。坐标 (0, 0) 位于浏览器视口的左上角,您希望它位于渲染 THREE.js 场景的 canvas 的左上角。由于您有导航栏,因此在获取鼠标坐标时必须考虑到屏幕顶部的偏移量。

要获得从 canvas 到视口边缘的偏移量,您可以使用 canvas.getBoundingClientRect() 函数。这将 return 一个大小为 canvas 的对象,其相对于视口的位置。

要获取由 THREE.js 渲染器创建的 canvas,您可以使用 renderer.domElement。或者您可以在程序开始时通过将 canvas.

传递给渲染器,将您自己的 canvas 分配给渲染器
var canvas = document.getElementById("canvasID");
renderer = new THREE.WebGLRenderer({ canvas: canvas });

然后使用它来获取偏移量。

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left, // left offset
      y: evt.clientY - rect.top //top offset
    };
}

您可以使用此函数获取鼠标位置相对于canvas的坐标。

希望这能解决问题。

ps。我会要求您 post 您现在使用的代码来获取鼠标位置,但我无法对您的问题发表评论。在询问有关堆栈溢出的问题时,最好提供您遇到问题的代码

编辑: 您想在使用它们之前获得鼠标坐标,换句话说:

var vector = new THREE.Vector3();
var mousePos = getMousePos(canvas, event);
vector.set( ( mousePos.x / window.innerWidth ) * 2 - 1,
 - ( mousePos.y / window.innerHeight ) * 2 + 1, 0.5 );
vector.unproject( camera );

下一个问题是,如何将 canvas 作为该函数的参数? 要尝试这是否可行,请尝试将您的渲染器设置为全局(如果尚未设置)。然后调用

var mousePos = getMousePos(renderer.domElement, event);

相反。如果可行,您可能希望将渲染器设为私有并以其他方式获取 canvas (因为拥有不必要的全局变量通常是不好的做法)。

你可以通过 DOM 方法获取 canvas,通过 id 或其他方式获取它。

希望这有效!