在Three.js中制作几何可点击的超链接(WebGl渲染器)

时间:2022-06-25 06:01:41

So I've been trying to make a spherical 360 panorama using three.js which implements clickable objects, which at the moment I would like to make hyperlinks.I've read many of the previous examples of raycasting and such, but have had no luck in getting the object to actually redirect me to the site. If someone could tell me where I'm going wrong in the code I'd greatly appreciate it.

所以我一直在尝试使用three.js制作一个球形360全景,它实现了可点击的对象,目前我想制作超链接。我已经阅读过许多以前的光线投射示例,但是没有好运,让对象实际上将我重定向到网站。如果有人能告诉我我在代码中出错的地方,我会非常感激。

I have a feeling the orbiting/panning function under "onDocumentMouseDown" is interfering with the raycasting? I'm still new to this and figuring it out.

我有一种感觉“onDocumentMouseDown”下的轨道/平移功能是否干扰了光线投射?我仍然是新手并想出来。

<div id="container"></div>
    <script src="three.min.js"></script>
    <script>
        var container, stats;
        var camera, controls, scene, renderer;
        var objects = [], plane;

        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2(),
        offset = new THREE.Vector3();

        var fov = 70,
        texture_placeholder,
        isUserInteracting = false,
        onMouseDownMouseX = 0, onMouseDownMouseY = 0,
        lon = 0, onMouseDownLon = 0,
        lat = 0, onMouseDownLat = 0,
        phi = 0, theta = 0;

        init();
        animate();

        function init() {
            var container, mesh1, sphere1, cube1;

            container = document.getElementById( 'container' );

            camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1100 );
            camera.target = new THREE.Vector3( 0, 0, 0 );

            scene = new THREE.Scene();

            mesh1 = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'spherical_map_small.jpg' ), transparent: true} ) );
            mesh1.scale.x = -1;
            scene.add( mesh1 );

            meshMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff});

            var sphere1 = new THREE.Mesh( new THREE.SphereGeometry( 2.5,20,20 ), meshMaterial );
            sphere1.position.set( 50, 10, 0 );
            scene.add( sphere1 );

            sphere1.userData = { URL:"http://www.google.com"};

            renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );

            container.appendChild( renderer.domElement );

            document.addEventListener( 'mousedown', onDocumentMouseDown, false );
            document.addEventListener( 'mousemove', onDocumentMouseMove, false );
            document.addEventListener( 'mouseup', onDocumentMouseUp, false );
            document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
            document.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false);

            window.addEventListener( 'resize', onWindowResize, false );
        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );
        }

        function onDocumentMouseDown( event ) {
            event.preventDefault();
            isUserInteracting = true;

            onPointerDownPointerX = event.clientX;
            onPointerDownPointerY = event.clientY;

            onPointerDownLon = lon;
            onPointerDownLat = lat;

            raycaster.setFromCamera( mouse, camera );

            var intersects = raycaster.intersectObjects( sphere1 );

            if ( intersects.length > 0 ) {
                controls.enabled = true;

                SELECTED = intersects[ 0 ].sphere1;

                var intersects = raycaster.intersectObject( sphere1 );
                if ( intersects.length > 0 ) {
                    window.open(intersects[0].object.userData.URL);
                }
            }   
        }

        function onDocumentMouseMove( event ) {
            if ( isUserInteracting ) {
                lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
                lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;
            }
        }

        function onDocumentMouseUp( event ) {
            isUserInteracting = false;
        }

        function onDocumentMouseWheel( event ) {
            isUserInteracting = false;
        }

        function animate() {
            requestAnimationFrame( animate );
            render();
        }

        function render() {
            lat = Math.max( - 85, Math.min( 85, lat ) );
            phi = THREE.Math.degToRad( 90 - lat );
            theta = THREE.Math.degToRad( lon );

            camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
            camera.target.y = 500 * Math.cos( phi );
            camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );

            camera.lookAt( camera.target );

            renderer.render( scene, camera );
        }
    </script>

1 个解决方案

#1


0  

Looking at your code I notice that you create var mouse = new THREE.Vector2(), then you don't set its values at any point in the supplied code. Then in onDocumentMouseDown() you cast a ray into the scene with undefined mouse coordinates raycaster.setFromCamera( mouse, camera ); As var mouse has not been set it is very likely that that is the reason you are not getting the navigation to start.

看一下你的代码,我注意到你创建了var mouse = new THREE.Vector2(),然后你就不会在提供的代码中的任何一点设置它的值。然后在onDocumentMouseDown()中使用未定义的鼠标坐标raycaster.setFromCamera(鼠标,相机)将光线投射到场景中;由于没有设置var鼠标,很可能这就是你没有启动导航的原因。

What you need to do is get the normalised screen coordiantes of the mouse and pass that into the raycaster.setFromCamera I can not quite remenber if the screen is one or two units but something like

您需要做的是获取鼠标的标准化屏幕坐标并将其传递到raycaster.setFromCamera如果屏幕是一个或两个单位但我不能完全避免

mouse.x = (event.clientX / window.innerWidth);  // normalise the mouse screen pos
mouse.y = (event.clientY / window.innerHeight); // same

mouse.x *= 2; // 0 is the center. -1 is left and 1 is right
mouse.y -= 1;  // center 

mouse.y *= -2; // Think this is upside down If it does not work try positive 2
mouse.y += 1;  // center

if it does not work try switching mouse.y the otherway around;

如果它不起作用尝试切换鼠标。反过来;

mouse.y *= 2; //  remove the -2 and put in 2
mouse.y -= 1;  // remove the += and put in -=

What I find very handy when messing about in 3D is to have a spare debug object in the scene. Something simple like a box or sphere. Use it to show a point on the raycaster's ray.

当我在3D中搞乱时,我发现非常方便的是在场景中有一个备用的调试对象。像盒子或球体一样简单的东西。用它来显示raycaster射线上的一个点。

Something like

// creat a box
var box... blah blah box creation code/
boxP = new vector3(); // position of debug object
// position it halfway in the raycasters range
boxP.x = camera.x + rayCaster.ray.x* ((rayCaster.near+rayCaster.far)/2);
boxP.y = camera.y + rayCaster.ray.y* ((rayCaster.near+rayCaster.far)/2);
boxP.z = camera.z + rayCaster.ray.z* ((rayCaster.near+rayCaster.far)/2);
box.position.set(boxP.x,boxP.y,boxP.z);

Now with luck you should see where you clicks are going.

现在运气好的话,你应该看看你点击的去向。

Also, I am not sure but if you are looking at the sphere from the inside you may have to set the material to doubleSided (I can't see it in your code) as the raycaster ignores faces with normals pointing away. Or try reversing the direction of each polygon.

此外,我不确定,但如果你从内部看球体,你可能必须将材料设置为doubleSided(我在你的代码中看不到它),因为raycaster忽略了法线指向的面孔。或者尝试反转每个多边形的方向。

That's about all I can suggest at the moment. Hope you find the problem.

这就是我现在所能提出的所有建议。希望你找到问题。

#1


0  

Looking at your code I notice that you create var mouse = new THREE.Vector2(), then you don't set its values at any point in the supplied code. Then in onDocumentMouseDown() you cast a ray into the scene with undefined mouse coordinates raycaster.setFromCamera( mouse, camera ); As var mouse has not been set it is very likely that that is the reason you are not getting the navigation to start.

看一下你的代码,我注意到你创建了var mouse = new THREE.Vector2(),然后你就不会在提供的代码中的任何一点设置它的值。然后在onDocumentMouseDown()中使用未定义的鼠标坐标raycaster.setFromCamera(鼠标,相机)将光线投射到场景中;由于没有设置var鼠标,很可能这就是你没有启动导航的原因。

What you need to do is get the normalised screen coordiantes of the mouse and pass that into the raycaster.setFromCamera I can not quite remenber if the screen is one or two units but something like

您需要做的是获取鼠标的标准化屏幕坐标并将其传递到raycaster.setFromCamera如果屏幕是一个或两个单位但我不能完全避免

mouse.x = (event.clientX / window.innerWidth);  // normalise the mouse screen pos
mouse.y = (event.clientY / window.innerHeight); // same

mouse.x *= 2; // 0 is the center. -1 is left and 1 is right
mouse.y -= 1;  // center 

mouse.y *= -2; // Think this is upside down If it does not work try positive 2
mouse.y += 1;  // center

if it does not work try switching mouse.y the otherway around;

如果它不起作用尝试切换鼠标。反过来;

mouse.y *= 2; //  remove the -2 and put in 2
mouse.y -= 1;  // remove the += and put in -=

What I find very handy when messing about in 3D is to have a spare debug object in the scene. Something simple like a box or sphere. Use it to show a point on the raycaster's ray.

当我在3D中搞乱时,我发现非常方便的是在场景中有一个备用的调试对象。像盒子或球体一样简单的东西。用它来显示raycaster射线上的一个点。

Something like

// creat a box
var box... blah blah box creation code/
boxP = new vector3(); // position of debug object
// position it halfway in the raycasters range
boxP.x = camera.x + rayCaster.ray.x* ((rayCaster.near+rayCaster.far)/2);
boxP.y = camera.y + rayCaster.ray.y* ((rayCaster.near+rayCaster.far)/2);
boxP.z = camera.z + rayCaster.ray.z* ((rayCaster.near+rayCaster.far)/2);
box.position.set(boxP.x,boxP.y,boxP.z);

Now with luck you should see where you clicks are going.

现在运气好的话,你应该看看你点击的去向。

Also, I am not sure but if you are looking at the sphere from the inside you may have to set the material to doubleSided (I can't see it in your code) as the raycaster ignores faces with normals pointing away. Or try reversing the direction of each polygon.

此外,我不确定,但如果你从内部看球体,你可能必须将材料设置为doubleSided(我在你的代码中看不到它),因为raycaster忽略了法线指向的面孔。或者尝试反转每个多边形的方向。

That's about all I can suggest at the moment. Hope you find the problem.

这就是我现在所能提出的所有建议。希望你找到问题。