鼠标点击时对象的动画(旋转、移动)

Posted

技术标签:

【中文标题】鼠标点击时对象的动画(旋转、移动)【英文标题】:Animation (rotation, movement) of an object on mouse click 【发布时间】:2019-07-10 21:50:20 【问题描述】:

考虑这个 three.js 示例

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

我正在尝试在鼠标单击事件中实现对象的动画(从对象当前所在的位置旋转/移动),我得到了这些但没有动画。

这是我添加的代码。我是否过度使用渲染?

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

如果我添加函数rotation(); requestAnimationFrame( 旋转 );

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

gltfModel 一直循环旋转,每次点击速度都会翻倍

完整代码如下:

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

可以用EventDispatcher来完成吗?如果是这样,怎么做? https://threejs.org/docs/#api/en/core/EventDispatcher

但我更喜欢第一种方法?

【问题讨论】:

【参考方案1】:

是的,您只需拨打一次render,这样您就可以从rotation()clickMe() 以及document.addEventListener( 'mousedown', clickMe, false ); 之后拨打这三个电话。

但是,每次点击您只会旋转一次对象。我假设您想要实现的是在按住鼠标时旋转对象。

如果你想这样做,你可以在鼠标按下时设置一个布尔值。

所以在 clickMe 里面你可以做这样的事情:

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

然后在你的渲染函数中你可以这样做:

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

在所有这些之后,请确保添加一个mouseup 侦听器以在您松开鼠标时停止旋转。

function handleMouseUp() 
  rotating = false;


document.addEventListener('mouseup', handleMouseUp);

【讨论】:

【参考方案2】:

一个简单的盒子代码示例,它可以在鼠标向下旋转时帮助您入门。您可以轻松地将其应用于您的 gltf 模型。至于渲染方法,是的,您无缘无故地在函数中使用它。你应该看看基本的场景示例。

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>

【讨论】:

以上是关于鼠标点击时对象的动画(旋转、移动)的主要内容,如果未能解决你的问题,请参考以下文章

unity中鼠标点击触发物体运动

Unity3d C# 鼠标点击下物体,物体匀速旋转180°,要看到旋转过程,这个代码怎么写?

使用 jQuery 制作动画时失去悬停(不移动鼠标)

在three.js中获取鼠标点击点的3D坐标

在鼠标拖动时旋转和移动 2D 对象

点击或移动出现爱心或文字