简体   繁体   中英

Animation (rotation, movement) of an object on mouse click

Considering this three.js example

https://threejs.org/examples/?q=glt#webgl_loader_gltf

I'm trying to achieve animation (rotation/movement from where the object currently is) of an object on mouse click event, I get these but without animation.

Here is the code that I have added. Do I overuse render?

        document.addEventListener( 'mousedown', clickMe, false );
        render();

        function clickMe() {
            rotation();
            render();   
        }


        var gltfModel;


        function rotation() {
            var rotationAnimation = 5 * (Math.PI / 180);
            gltfModel.rotation.x += rotationAnimation;
            render();       
        }

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

if I add in function rotation(); requestAnimationFrame( rotation );

            function rotation() {
            requestAnimationFrame( rotation );
            var rotationAnimation = 5 * (Math.PI / 180);
            gltfModel.rotation.x += rotationAnimation;
            render();       
        }

gltfModel keeps loop spinning, and every time I click the speed doubles

Here is the complete code:

        <script>

        if ( WEBGL.isWebGLAvailable() === false ) {

            document.body.appendChild( WEBGL.getWebGLErrorMessage() );

        }

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




        init();
        animate();

        function init() {

            container = document.createElement( 'div' );
            document.body.appendChild( container );

            camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
            camera.position.set( - 1.8, 0.9, 2.7 );

            controls = new THREE.OrbitControls( camera );
            controls.target.set( 0, - 0.2, - 0.2 );
            controls.update();

            var urls = [ 'posx.jpg', 'negx.jpg', 'posy.jpg', 'negy.jpg', 'posz.jpg', 'negz.jpg' ];
            var loader = new THREE.CubeTextureLoader().setPath( 'textures/cube/Bridge2/' );
            var background = loader.load( urls );

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

            light = new THREE.HemisphereLight( 0xbbbbff, 0x444422 );
            light.position.set( 0, 1, 0 );
            scene.add( light );

            // model
            var loader = new THREE.GLTFLoader().setPath( 'models/gltf/DamagedHelmet/glTF/' );
            loader.load( 'DamagedHelmet.gltf', function ( gltf ) {

                gltf.scene.traverse( function ( child ) {

                    if ( child.isMesh ) {

                        child.material.envMap = background;

                        gltfModel = child;

                    }

                } );

                scene.add( gltf.scene );

            }, undefined, function ( e ) {

                console.error( e );

            } );

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            renderer.gammaOutput = true;
            container.appendChild( renderer.domElement );

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

            //MY LINE OF CODE
            document.addEventListener( 'mousedown', clickMe, false );
            render();


            // stats
            stats = new Stats();
            container.appendChild( stats.dom );

        }

        function onWindowResize() {

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

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

        }

        //MY LINE OF CODE
        ///////////////////////////////////////

        function clickMe() {

            rotation();

            render();



        }


        var gltfModel;


        function rotation() {

            var rotationAnimation = 5 * (Math.PI / 180);

            gltfModel.rotation.x += rotationAnimation;

            render();

        }




        ///////////////////////////////////////



        function animate() {

            requestAnimationFrame( animate );


            render();

            stats.update();


        }


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

    </script>

Can it be accomplished with EventDispatcher? If so, how? https://threejs.org/docs/#api/en/core/EventDispatcher

But I rather prefer maybe the first method?

Yes you only need to call render once so you can take those three calls out from rotation() and clickMe() and after document.addEventListener( 'mousedown', clickMe, false ); .

However with this, you will only rotate the object once with every click. I'm assuming what you want to achieve is to rotate the object as you hold your mouse down.

If you want to do this you can just set a boolean on mousedown.

So inside clickMe you can do something like:

function clickMe() {
  rotating = true; // declare this as a global variable
}

and then in your render function you can do:

function render() {
  if (rotating) {
    var rotationAnimation = 5 * (Math.PI / 180);
    gltfModel.rotation.x += rotationAnimation;
  }
  renderer.render( scene, camera );
}

After all this, make sure you add a mouseup listener to stop the rotating when you let go of your mouse.

function handleMouseUp() {
  rotating = false;
}

document.addEventListener('mouseup', handleMouseUp);

A simple code sample of a box that spins on mouse down to get you started. You can apply it easily to your gltf model. As for the render method, yes you are using it in your functions for no reason. You should have a look at basic scene examples.

https://threejs.org/docs/#manual/en/introduction/Creating-a-scene

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> </body> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/101/three.min.js"></script> <script> var box; var isMouseDown = false; var rotateSpeed = 0; init(); animate(); function init() { container = document.createElement('div'); document.body.appendChild(container); camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20); camera.position.set(5,5,5); camera.lookAt(new THREE.Vector3(0,0,0)); scene = new THREE.Scene(); light = new THREE.HemisphereLight(0xbbbbff, 0x444422); light.position.set(0, 1, 0); scene.add(light); var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 ); var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); box = new THREE.Mesh( geometry, material ); scene.add( box ); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); container.appendChild(renderer.domElement); window.addEventListener('mousedown', () => isMouseDown = true,false); window.addEventListener('mouseup', () => isMouseDown = false,false); animate(); } function animate() { requestAnimationFrame(animate); if(isMouseDown) rotateSpeed += 0.001; else rotateSpeed /= 1.01; box.rotation.y += rotateSpeed; render(); } function render() { renderer.render(scene, camera); } </script> </html> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM