Three.js Restrict the mouse movement to Scene only

我们两清 提交于 2019-12-11 10:38:18

问题


I am working on the cube example from three.js (webgl_interactive_cubes_gpu.html). I realized that events goes to the entire html page. I mean i can rotate, zoom in or zoom out, even if the mouse pointer is not inside the scene..

I google a little bit and found some answers (Allow mouse control of three.js scene only when mouse is over canvas) but they do not work for me..Below is my code...

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

        }

any help is greatly appreciated.. Thanks


回答1:


You can pass in the canvas as an argument to the TrackballsControls constructor.

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

That should solve the problem.

EDIT: included a working example,

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();

could not get your code to run at all so..



来源:https://stackoverflow.com/questions/29576928/three-js-restrict-the-mouse-movement-to-scene-only

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!