Three.js将鼠标移动限制为仅限场景

时间:2015-04-11 10:40:33

标签: three.js

我正在研究来自three.js的多维数据集示例(webgl_interactive_cubes_gpu.html)。我意识到事件会进入整个html页面。我的意思是我可以旋转,放大或缩小,即使鼠标指针不在场景内..

我稍微谷歌并找到了一些答案(Allow mouse control of three.js scene only when mouse is over canvas),但它们对我不起作用。下面是我的代码......

        var container, stats;
        var camera, controls, scene, renderer;
        var pickingData = [], pickingTexture, pickingScene;
        var objects = [];
        var highlightBox;

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

        init();
        animate();

        function init() {

            container = document.getElementById( "container" );

            camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000 );
            camera.position.z = 1000;
            //camera.translateZ( -500 );

            controls = new THREE.TrackballControls(camera);
            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 4;
            controls.panSpeed = 0.8;
            controls.noZoom = false;
            controls.noPan = false;
            controls.staticMoving = true;
            controls.dynamicDampingFactor = 0.3;


            scene = new THREE.Scene();

            pickingScene = new THREE.Scene();
            pickingTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
            pickingTexture.minFilter = THREE.LinearFilter;
            pickingTexture.generateMipmaps = false;

            scene.add( new THREE.AmbientLight( 0x555555 ));

            var light = new THREE.SpotLight( 0xffffff, 1.5 );
            light.position.set( 0, 500, 2000 );
            scene.add( light );

            var geometry = new THREE.Geometry(),
            pickingGeometry = new THREE.Geometry(),
            pickingMaterial = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors } ),
            defaultMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.FlatShading,      vertexColors: THREE.VertexColors} );

            function applyVertexColors( g, c ) {

                g.faces.forEach( function( f ) {

                    var n = ( f instanceof THREE.Face3 ) ? 3 : 4;

                    for( var j = 0; j < n; j ++ ) {

                        f.vertexColors[ j ] = c;

                    }

                } );

            }

            var geom = new THREE.BoxGeometry(0.005, 0.005, 0.005 );
            var color = new THREE.Color();

            var matrix = new THREE.Matrix4();
            var quaternion = new THREE.Quaternion();

            var coord="219_163_189;130_173_179;161_113_231;
            var splitCoord=coord.split(";");

            var coordColr="0_255_255;255_255_0;0_0_255;0_255_0;255_255_0;
            var splitCoordColor=coordColr.split(";");

            for ( var i = 0; i < splitCoord.length; i++ ) {

                var position = new THREE.Vector3();
                var xyz=splitCoord[i].split("_");
                var col=splitCoordColor[i].split("_");

                position.x = xyz[0];
                position.y = xyz[1];
                position.z = xyz[2];

                var rotation = new THREE.Euler();
                rotation.x = 0
                rotation.y = 0;
                rotation.z = 0;

                var scale = new THREE.Vector3();
                scale.x = 200 + 100;
                scale.y = 200 + 100;
                scale.z = 200 + 100;

                quaternion.setFromEuler(rotation, false );
                matrix.compose( position, quaternion, scale);

                col[0]=col[0]/255;
                col[1]=col[1]/255;                  
                col[2]=col[2]/255;

                applyVertexColors(geom, color.setRGB(col[0], col[1], col[2]));
                geometry.merge(geom, matrix);

                // give the geom's vertices a color corresponding to the "id"
                applyVertexColors( geom, color.setHex( i ) );

                pickingGeometry.merge( geom, matrix );

                pickingData[ i ] = {

                    position: position,
                    rotation: rotation,
                    scale: scale

                };

            }

            var drawnObject = new THREE.Mesh( geometry, defaultMaterial );
            scene.add(drawnObject);

            pickingScene.add( new THREE.Mesh( pickingGeometry, pickingMaterial ) );

            highlightBox = new THREE.Mesh(
                new THREE.BoxGeometry( 0.01, 0.01, 0.01 ),
                new THREE.MeshLambertMaterial( { color: 0xffff00 }
            ) );
            scene.add( highlightBox );

            renderer = new THREE.WebGLRenderer( );
            //renderer.setClearColor( 0xffffff );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize(800, 800);
            renderer.sortObjects = false;
            container.appendChild(renderer.domElement);

            stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.top = '0px';
            container.appendChild( stats.domElement );

            //renderer.domElement.addEventListener('mousemove', onMouseMove );

        }


        function onMouseMove( e ) {
            mouse.x = e.clientX;
            mouse.y = e.clientY;
        }

        function animate() {

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

        function pick() {


            //render the picking scene off-screen
            renderer.render( pickingScene, camera, pickingTexture );

            //create buffer for reading single pixel
            var pixelBuffer = new Uint8Array( 4 );

            //read the pixel under the mouse from the texture
            renderer.readRenderTargetPixels(pickingTexture, mouse.x, pickingTexture.height - mouse.y, 1, 1, pixelBuffer);

            //interpret the pixel as an ID

            var id = ( pixelBuffer[0] << 16 ) | ( pixelBuffer[1] << 8 ) | ( pixelBuffer[2] );
            var data = pickingData[ id ];

            if (data) {

                //move our highlightBox so that it surrounds the picked object
                if ( data.position && data.rotation && data.scale ){

                    highlightBox.position.copy( data.position );
                    highlightBox.rotation.copy( data.rotation );
                    highlightBox.scale.copy( data.scale ).add( offset );
                    highlightBox.visible = true;
                }

            } else {

                highlightBox.visible = false;
            }

        }

        function render() {

            controls.update();
            pick();
            renderer.render( scene, camera );

        }

任何帮助都非常感谢.. 感谢

1 个答案:

答案 0 :(得分:1)

您可以将画布作为参数传递给TrackballsControls构造函数。

var controls = new THREE.TrackballControls(camera, renderer.domElement);

那应该可以解决问题。

编辑:包含一个工作示例,

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, 400 / 300, 1, 1000);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(400, 300);
document.body.appendChild(renderer.domElement);

var controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 4;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;


var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
  color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 5;

var render = function() {
  requestAnimationFrame(render);
  controls.update();
  cube.rotation.x += 0.1;
  cube.rotation.y += 0.1;

  renderer.render(scene, camera);
};

render();

无法让你的代码完全运行..