Three.js鼠标悬停在3D元素上

时间:2013-02-21 15:14:37

标签: three.js mousehover

我的问题如下:即使鼠标没有直接在立方体上方,鼠标悬停操作也适用于立方体,如果它位于场景之外的立方体上方或下方的Y轴上,则它可以工作。有人可以解释我为什么以及如何解决它?

 <!DOCTYPE html>
    <html lang="fr" xml:lang="fr" xmlns="http://www.w3.org/1999/xhtml">
    <head>



     <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>        

    <script src="lib/Three.js" type="text/javascript"></script>

    <script src="lib/Detector.js"></script>
    <script src="lib/stats.min.js" type="text/javascript"></script>
    <script src="lib/THREEx/THREEx.WindowResize.js"></script>
    <script src="lib/THREEx/THREEx.FUllScreen.js"></script>
    <script src="lib/TrackballControls.js"></script>

      <style type="text/css">
      body
    {
        color: #ffffff;
        text-align:center;
        background-color:  gray;
        margin: 0px;
    }
    #center
    {
        color: #fff;
        position: absolute;
        top: 50px; width: 100%;
        padding: 5px;
        z-index:100;
    }

    #center h1
    {

        font-size:60px;
    }

    #container
    {
        position:absolute;
        bottom:0;
    }

      </style>

    </head>

    <body>

    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
    <div id="container"></div>


     </body>

     <script>
    // MAIN

    console.log("Main.js");
    if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

    // global variables

    var container, scene, camera, renderer, stats, controls;

    // custom variables 

    var t = THREE;
    var cube;

    // to keep track of the mouse position
    var projector, INTERSECTED, mouse = { x: 0, y: 0 },

    // an array to store our particles in
    particles = [];

    init();
    animate();

    function init()
    {


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

        // camera
        var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
        var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
        camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
        scene.add(camera);
        camera.position.set(0,0,800);
        camera.lookAt(scene.position);

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

        // container
        container = document.getElementById('container');
        container.appendChild( renderer.domElement );

        // stats
        stats = new Stats();
        stats.domElement.style.position = 'absolute';
        stats.domElement.style.bottom = '0px';
        stats.domElement.style.zIndex = 100;
        container.appendChild( stats.domElement );

        // events 
        THREEx.WindowResize(renderer, camera);
        THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });

        // initialize object to perform world/screen calculations
        projector = new THREE.Projector();

        // CUSTOM

        // Cubes

        x = window.innerWidth / 5;
        y =  window.innerHeight / 10;
        console.log(window.innerWidth);
        console.log(window.innerHeight);
        var geometry = new t.CubeGeometry(125,125,125);
        var material = new t.MeshBasicMaterial({color:0xCCCCCC});
        cube = new t.Mesh(geometry, material);
        cube.name = "cube";

        scene.add(cube);
        cube.position.set(-x,-y,0);

        x = window.innerWidth;
        y =  window.innerHeight / 10;

        var geometry2 = new t.CubeGeometry(125,125,125);
        var material2 = new t.MeshBasicMaterial({color:0xCCCCCC});
        cube2 = new t.Mesh(geometry2, material2);
        scene.add(cube2);

        cube2.name = "cube2";
        cube2.position.set(0,-y,0);


        x = window.innerWidth / 5;
        y =  window.innerHeight / 10;

        var geometry3 = new t.CubeGeometry(125,125,125);
        var material3 = new t.MeshBasicMaterial({color:0xCCCCCC});
        cube3 = new t.Mesh(geometry3, material3);
        cube3.name = "cube3";

        scene.add(cube3);
        cube3.position.set(x,-y,0);

        // particles

        makeParticles(); 


    // Mouse events
    document.addEventListener( 'mousemove', onMouseMove, false ); 
    document.addEventListener( 'mousedown', onMouseDown, false ); 


    }


    // called when the mouse moves
    function onMouseMove( event ) 
    {
    // store the mouseX and mouseY position 
    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    }

    function onMouseDown( event ) 
    {
        event.preventDefault();

        var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
        projector.unprojectVector( vector, camera );
        var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );

        var intersects = ray.intersectObjects( scene.children );

        if ( intersects.length > 0 )
        {
            console.log(INTERSECTED.name);
            if(INTERSECTED.name == "cube")
            {
                page("real");
            }
        }
    }

    function animate() 
    {
        cube.rotation.y +=0.005;
        cube.rotation.x -=0.005;
        cube2.rotation.y +=0.005;
        cube2.rotation.x -=0.005;
        cube3.rotation.y +=0.005;
        cube3.rotation.x -=0.005;
        //textMesh.rotation.y +=0.005;

        requestAnimationFrame( animate );
        render();   
        update();   
    }

                    // creates a random field of Particle objects

    function makeParticles() 
    { 

    var particle, material; 

        // we're gonna move from z position -1000 (far away) 
        // to 1000 (where the camera is) and add a random particle at every pos. 
        for ( var zpos= -1000; zpos < 1000; zpos+=20 ) 
        {

        // we make a particle material and pass through the 
        // colour and custom particle render function we defined. 
        material = new THREE.ParticleCanvasMaterial( {  program: particleRender } );
        // make the particle
        particle = new THREE.Particle(material);

        // give it a random x and y position between -500 and 500
        particle.position.x = Math.random() * 1000 - 500;
        particle.position.y = Math.random() * 1000 - 500;

        // set its z position
        particle.position.z = zpos;

        // scale it up a bit
        particle.scale.x = particle.scale.y = 10;

        // add it to the scene
        scene.add( particle );

        // and to the array of particles. 
        particles.push(particle); 
        }
    }

    // there isn't a built in circle particle renderer 
    // so we have to define our own. 

    function particleRender( context ) 
    {

    // we get passed a reference to the canvas context
    context.beginPath();
    // and we just have to draw our shape at 0,0 - in this
    // case an arc from 0 to 2Pi radians or 360º - a full circle!
    context.arc( 0, 0, 0.2, 2,  Math.PI * 4, true );
    context.fillStyle = "white";
    context.fill();
    };

        // moves all the particles dependent on mouse position

    function updateParticles() 
    { 

        // iterate through every particle
        for(var i=0; i<particles.length; i++) 
        {

        particle = particles[i]; 

        // and move it forward dependent on the mouseY position. 
        particle.position.z +=  250 * 0.02;

        // if the particle is too close move it to the back
        if(particle.position.z>1000) particle.position.z-=2000; 

        }

    }

    function render()
    {
    renderer.render( scene, camera );
    }

    function update()
    {
    updateParticles();
    stats.update();


        // find intersections

        // create a Ray with origin at the mouse position
        //   and direction into the scene (camera direction)
        var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
        projector.unprojectVector( vector, camera );
        var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );

        // create an array containing all objects in the scene with which the ray intersects
        var intersects = ray.intersectObjects( scene.children );

        // INTERSECTED = the object in the scene currently closest to the camera 
        //      and intersected by the Ray projected from the mouse position    

        // if there is one (or more) intersections
        if ( intersects.length > 0 )
        {
            // if the closest object intersected is not the currently stored intersection object
            if ( intersects[ 0 ].object != INTERSECTED) 
            {
                // restore previous intersection object (if it exists) to its original scale
                if ( INTERSECTED )  
                {
                    INTERSECTED.scale.x = INTERSECTED.currentscale.x;
                    INTERSECTED.scale.y = INTERSECTED.currentscale.y;
                    INTERSECTED.scale.z = INTERSECTED.currentscale.z;
                }
                // store reference to closest object as current intersection object
                INTERSECTED = intersects[ 0 ].object;
                // store scale of closest object (for later restoration)
                scalex = INTERSECTED.scale.x;
                scaley = INTERSECTED.scale.y;
                scalez = INTERSECTED.scale.z;

                INTERSECTED.currentscale = { x : scalex , y : scaley, z : scalez };
                // set a new scale for closest object
                INTERSECTED.scale.x = INTERSECTED.scale.y = INTERSECTED.scale.z = 1.5;


            }
        } 

        else // there are no intersections
        {
            // restore previous intersection object (if it exists) to its original scale
            if ( INTERSECTED ) 
            {
                INTERSECTED.scale.x = INTERSECTED.currentscale.x;
                INTERSECTED.scale.y = INTERSECTED.currentscale.y;
                INTERSECTED.scale.z = INTERSECTED.currentscale.z;
            }

            // remove previous intersection object reference
            //     by setting current intersection object to "nothing"
            INTERSECTED = null;
        }

    }



    // Pour charger une page dynamiquement
        function page(page){
        $("body").animate({opacity:0},1000, function(){
        $("body").empty();
        $("body").load(page +'.html');
        $("body").animate({opacity:1},1000, function(){

                });
            });
    }


     </script>






    </html>

1 个答案:

答案 0 :(得分:1)

窗口左上角和画布左上角之间是否有偏移? 如果是这样,您必须计算偏移量(顶部和左侧)并从event.client值中减去值。

试试这个:

// now get the space between top left browser window corner
var absoluteOffsetLeft = 0;
var absoluteOffsetTop = 0;
var obj = <your HTML object containing the canvas>;

// taken from http://www.quirksmode.org/js/findpos.html
if (obj.offsetParent) {
    do {
        absoluteOffsetLeft += obj.offsetLeft;
        absoluteOffsetTop += obj.offsetTop;
    } while (obj = obj.offsetParent);
} else {
    console.log("Method offsetParent not supported");
}

// YOUR mouse move event handler - also take the innerWidth and Height from the canvas
function onMouseMove( event ) {
    // store the mouseX and mouseY position 
    mouse.x = ( (event.clientX - absoluteOffsetLeft) / canvas.innerWidth ) * 2 - 1;
    mouse.y = - ( (event.clientY - absoluteOffsetTop) / canvas.innerHeight ) * 2 + 1;
}
相关问题