简体   繁体   English

鼠标单击时对象的动画(旋转,移动)

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

Considering this three.js example 考虑这个three.js示例

https://threejs.org/examples/?q=glt#webgl_loader_gltf 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(); 如果我添加功能rotation(); requestAnimationFrame( 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 gltfModel保持循环旋转,每次单击速度都会翻倍

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? 可以用EventDispatcher完成吗? If so, how? 如果是这样,怎么办? https://threejs.org/docs/#api/en/core/EventDispatcher 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 ); 是的,您只需要调用一次render ,这样您就可以从rotation()clickMe()以及在document.addEventListener( 'mousedown', clickMe, false );之后取出这三个调用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. 如果要执行此操作,可以在mousedown上设置一个布尔值。

So inside clickMe you can do something like: 因此,在clickMe内,您可以执行以下操作:

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. 完成所有这些操作后,请确保添加一个mouseup侦听器,以在放开鼠标时停止旋转。

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. 您可以轻松地将其应用于gltf模型。 As for the render method, yes you are using it in your functions for no reason. 至于render方法,是的,您无缘无故地在函数中使用它。 You should have a look at basic scene examples. 您应该看一下基本的场景示例。

https://threejs.org/docs/#manual/en/introduction/Creating-a-scene 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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