THREE.js SphereGeometry全景图热点使用DOM元素

9
我使用SphereGeometryPerspectiveCameraCanvasTexture创建了一个简单的WebGL 3D全景应用程序。现在,我想通过在SphereGeometry的某些部分添加“热点”来让场景更加生动。我遇到的问题是如何更新各种DOMElements,使它们的位置反映出更新后的Camera位置。
基本上,当Camera旋转时,各种DOMElements会相对于相机旋转的方向移入或移出视野。我尝试将<div>绝对定位到<canvas>上,并使用返回的PerspectiveCamera camera.rotation来平移XY位置,但并没有真正起作用。这是我的JS和CSS实现:

CSS

#TestHotSpot {
    /* not sure if using margins is the best method to position hotspot */
    margin-top: 50px;
    margin-left: 50px;
    width: 50px;
    height: 50px;
    background: red;
    position: absolute;
}

JavaScript

/** 
   CONFIG is my stored object variable; it contains the PerspectiveCamera instance 
   code is being called inside of my RequestAnimationFrame
**/

config.camera.updateProjectionMatrix();
config.controls.update(delta);

document.getElementById("TestHotSpot").style.transform = "translate("+ config.camera.rotation.x +"px, "+ config.camera.rotation.y +"px)";

这里也有所需效果的实时示例。

什么是解决此问题的最佳方案?当我运行它时,我注意到DOMElements只会轻微移动;我还注意到它们不会真正考虑它们在SphereGeometry上放置的位置(例如,被定位在Camera“后面”;非常复杂!

我很乐意使用任何THREE.js引擎的插件,并遵循任何教程。非常感谢您提前回复!

2个回答

3
  1. 尝试将平面网格/网格设置到所需点。
  2. 复制css元素的位置(使用three.js cssObject创建的domElements[如果您已经知道]),以及planemesh/mesh的位置。

这样就完成了!!


嗨@serious_s,非常感谢您的回复!我尝试查找有关如何使用cssObject的文档,但没有找到。您是否有一个代码片段示例,可以解释如何使用它?我仍然有点困惑-抱歉! - lindsay
你好!经过进一步的研究,我现在理解了你的答案 - 感谢你的帮助!已点赞。 - lindsay
如果您不介意的话,请分享一下您的研究,您参考了哪些教程或读物,还有什么其他发现,您是否有一些好的链接可以帮助我理解整个过程。非常感谢您愿意分享任何相关信息。 - lowtechsun
嗨@lindsay,感谢您的点赞。由于我在stackoverflow上仍然是新手,所以没有注意到您的评论。 - serious_luffy

2

好的,我来回答我的问题!我遇到了一些问题,但是我已经弄清楚了如何将CSS3d与THREE.js WebGL场景混合。

首先,我需要更新我的THREE.js库;我之前使用的是从早期下载中获取的版本71,但我需要将其更新为Mr.Doob在示例中使用的库。我还更新了我的CSS3d库,使用了该示例中包含的文件。

然后,我使用了这个方法(与链接中指定的相同)创建了一个演示场景。

var camera, scene, renderer;

var scene2, renderer2;

var controls;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.set( 200, 200, 200 );

    controls = new THREE.TrackballControls( camera );

    scene = new THREE.Scene();
    scene2 = new THREE.Scene();

    var material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1, side: THREE.DoubleSide } );

            //

    for ( var i = 0; i < 10; i ++ ) {

        var element = document.createElement( 'div' );
            element.style.width = '100px';
            element.style.height = '100px';
            element.style.opacity = 0.5;
            element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle();

        var object = new THREE.CSS3DObject( element );
            object.position.x = Math.random() * 200 - 100;
            object.position.y = Math.random() * 200 - 100;
            object.position.z = Math.random() * 200 - 100;
            object.rotation.x = Math.random();
            object.rotation.y = Math.random();
            object.rotation.z = Math.random();
            object.scale.x = Math.random() + 0.5;
            object.scale.y = Math.random() + 0.5;
        scene2.add( object );

        var geometry = new THREE.PlaneGeometry( 100, 100 );
        var mesh = new THREE.Mesh( geometry, material );
            mesh.position.copy( object.position );
            mesh.rotation.copy( object.rotation );
            mesh.scale.copy( object.scale );
        scene.add( mesh );

    }

            //

    renderer = new THREE.WebGLRenderer();
    renderer.setClearColor( 0xf0f0f0 );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    renderer2 = new THREE.CSS3DRenderer();
    renderer2.setSize( window.innerWidth, window.innerHeight );
    renderer2.domElement.style.position = 'absolute';
    renderer2.domElement.style.top = 0;
    document.body.appendChild( renderer2.domElement );

}

function animate() {

    requestAnimationFrame( animate );

    controls.update();

    renderer.render( scene, camera );
    renderer2.render( scene2, camera );

}

在我完成这个工作之后,我重新利用了 CSS3d场景CSS3d对象CSS3d渲染器,将它们包含在我的场景中。

祝其他人好运,希望这对你有所帮助!


我也在尝试添加带有指向其他全景图的热点。您能否分享一下您是如何实现这一点的?也许您可以制作一个jsfiddle吗?我是ThreeJS的新手,发布了这个问题https://dev59.com/bpPfa4cB1Zd3GeqPF6a_,仍在寻找好的示例或教程来帮助我更好地理解整个问题。如果能够快速制作一个jsfiddle,我将非常感激! - lowtechsun
2021年 - 这仍然有助于使可点击元素覆盖我的 SphereGeometry,以便该元素随全景图的其余部分一起移动。只需要进行一些微调:import { CSS3DRenderer, CSS3DObject } from './assets/js/CSS3DRenderer.js';renderer2 = new CSS3DRenderer(); - William Isted

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接