如何在三个js坐标系中正确定位html元素?

mor*_*rod 3 three.js

我希望有一个我无法回答的简单问题。

我有三个 js 几何球体,它们在一个盒子里移动。我把这个盒子放在场景的中心。球体如何留在盒子中的机制无关紧要。重要的是球体围绕原点 (0,0) 移动,并且画布始终充满页面。

我想从移动球体到页面上的 div 或 img 元素绘制一条线。为此,我假设我必须将 css 坐标转换为三个 js 坐标。我发现了一些我认为做了这样的事情(注意:过度使用某些东西来表示我可能弄错了)

我可以将 html 元素添加到与 webgl 渲染器相同的场景/相机,但显然使用不同的渲染器,但我不确定如何从那里继续?

基本上我想知道:

  • 如果需要,我应该如何更改 div 保留纵横比的大小?
    • 本质上,我希望 div 或元素在某个相机深度填充屏幕。
  • 默认情况下如何将div放置在场景的中心?
    • 地雷似乎在 z 方向上移动了 1000,但这可能是我必须看到的 div(img) 的大小。
  • 如何在 webgl 球体和 html div/img 之间画一条线?

提前致谢!

Ale*_*lov 5

不幸的是,您问了 3 个问题,一次解决它们很棘手。

我将解释如何将 DIV 元素定位在某些 3D 对象的顶部。我的例子是当你用鼠标悬停对象时出​​现的工具提示:http : //jsfiddle.net/mmalex/ycnh0wze/

Three.js 对象上的 HTML 工具提示

那么让我们开始吧,

首先,您需要订阅鼠标事件并将鼠标的二维坐标转换为视口上的相对坐标。很好的解释你会在这里找到它:在three.js中获取鼠标点击点的3D坐标

具有 2D 坐标,对对象进行光线投射。这些步骤非常简单,但为了完整起见,我提供了代码块。

var raycaster = new THREE.Raycaster();

function handleManipulationUpdate() {
    // cleanup previous results, mouse moved and they're obsolete now
    latestMouseIntersection = undefined;
    hoveredObj = undefined;

    raycaster.setFromCamera(mouse, camera);
    {
        var intersects = raycaster.intersectObjects(tooltipEnabledObjects);
        if (intersects.length > 0) {
            // keep point in 3D for next steps
            latestMouseIntersection = intersects[0].point;
            // remember what object was hovered, as we will need to extract tooltip text from it
            hoveredObj = intersects[0].object;
        }
    }
    ... // do anything else

    //with some conditions it may show or hide tooltip
    showTooltip();
}

// Following two functions will convert mouse coordinates
// from screen to three.js system (where [0,0] is in the middle of the screen)
function updateMouseCoords(event, coordsObj) {
    coordsObj.x = ((event.clientX - renderer.domElement.offsetLeft + 0.5) / window.innerWidth) * 2 - 1;
    coordsObj.y = -((event.clientY - renderer.domElement.offsetTop + 0.5) / window.innerHeight) * 2 + 1;
}

function onMouseMove(event) {
    updateMouseCoords(event, mouse);
    handleManipulationUpdate();
}

 window.addEventListener('mousemove', onMouseMove, false);
Run Code Online (Sandbox Code Playgroud)

最后看到最重要的部分,DIV 元素放置。要理解代码,必须使用Vector3.project方便方法。

计算顺序如下:

  1. 获取二维鼠标坐标,
  2. Raycast 对象并记住相交的 3D 坐标(如果有),
  3. 将 3D 坐标投影回 2D(这一步在这里似乎是多余的,但是如果您想以编程方式触发对象工具提示怎么办?您将没有鼠标坐标)
  4. 乱七八糟地将 DIV 放在 2D 点上方居中,并有很好的边距。
// This will move tooltip to the current mouse position and show it by timer.
function showTooltip() {
    var divElement = $("#tooltip");

    //element found and mouse hovers some object?
    if (divElement && latestMouseIntersection) {
        //hide until tooltip is ready (prevents some visual artifacts)
        divElement.css({
            display: "block",
            opacity: 0.0
        });

        //!!! === IMPORTANT === 
        // DIV element is positioned here
        var canvasHalfWidth = renderer.domElement.offsetWidth / 2;
        var canvasHalfHeight = renderer.domElement.offsetHeight / 2;

        var tooltipPosition = latestMouseProjection.clone().project(camera);
        tooltipPosition.x = (tooltipPosition.x * canvasHalfWidth) + canvasHalfWidth + renderer.domElement.offsetLeft;
        tooltipPosition.y = -(tooltipPosition.y * canvasHalfHeight) + canvasHalfHeight + renderer.domElement.offsetTop;

        var tootipWidth = divElement[0].offsetWidth;
        var tootipHeight = divElement[0].offsetHeight;

        divElement.css({
            left: `${tooltipPosition.x - tootipWidth/2}px`,
            top: `${tooltipPosition.y - tootipHeight - 5}px`
        });

        //get text from hovered object (we store it in .userData)
        divElement.text(hoveredObj.userData.tooltipText);

        divElement.css({
            opacity: 1.0
        });
    }
}
Run Code Online (Sandbox Code Playgroud)