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

时间:2019-01-28 21:28:15

标签: three.js

希望我有一个简单的问题,无法解决。

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

我想从移动球体到页面上的div或img元素画一条线。为此,我假设我必须将css坐标转换为三个js坐标。 I found something I thought did something like this (Note: Over use of somethings to signify I am probably mistaken)

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

基本上我想知道:

  • 如果需要,应如何更改div保留宽高比的大小?
    • 本质上,我希望div或元素在某个摄像机深度填充屏幕。
  • 默认情况下如何将div放置在场景的中心?
    • 矿井似乎在z方向上移动了1000,但这可能就是我必须考虑的div(img)的大小。
  • 如何在webgl球形和html div / img之间划一条线?

提前谢谢!

1 个答案:

答案 0 :(得分:2)

不幸的是,您问了3个问题,很难一次全部解决。

我将解释如何将DIV元素放置在某些3D对象的顶部。我的示例是一个用鼠标悬停该对象时出现的工具提示:http://jsfiddle.net/mmalex/ycnh0wze/

HTML tooltip on three.js objects

让我们开始吧,

首先,您需要订阅鼠标事件,并将鼠标的2D坐标转换为视口上的相对坐标。很好解释,您将在这里找到它:Get mouse clicked point's 3D coordinate in three.js

具有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);

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

计算顺序如下:

  1. 获取2D鼠标坐标,
  2. 射线广播对象并记住相交的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
        });
    }
}