【问题标题】:ThreeJS Rotation AnimationThreeJS 旋转动画
【发布时间】:2012-02-01 11:25:41
【问题描述】:

我在 ThreeJS 中有一个立方体,每次按下按钮时我都想将它顺时针旋转 90 度。我想我有它的基本要点:创建一个 Three.Animation 实例,将它绑定到立方体,然后每次按下正确的按钮时都开始动画。但是,我很难理解 ThreeJS 的 API,因为它似乎没有包含任何关于其方法的示例。

这是 THREE.js 的 Animation 构造函数:(root、data、interpolationType、JITCompile)我不明白字段中的内容。我猜根是我放置立方体的地方,但其余的呢?

我也可以随时调用animation.play() 来触发动画吗?以及animationHandler是如何工作的?

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    我认为对于将对象顺时针旋转 90 度,使用 TWEEN 类就可以了。我认为 Animation 类对于较重的东西(如骨骼/皮肤变形/等)很方便。

    要使用补间类有 3 个基本步骤:

    1. 在您的文件中包含该类 (<script src="js/Tween.js"></script>)
    2. 为您需要的事件添加补间 (new TWEEN.Tween( cube.rotation ).to( { y:Math.random()}, 1000 ).easing( TWEEN.Easing.Quadratic.EaseOut).start();)
    3. 更新渲染循环中的补间 (TWEEN.update();)

    您可以先查看cubes tween example

    我已经修改了默认的多维数据集示例以添加补间:

    <!doctype html>
    <html lang="en">
        <head>
            <title>three.js canvas - geometry - cube</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
            <style>
                body {
                    font-family: Monospace;
                    background-color: #f0f0f0;
                    margin: 0px;
                    overflow: hidden;
                }
            </style>
        </head>
        <body>
    
            <script src="../build/Three.js"></script>
            <script src="js/Tween.js"></script>
            <script src="js/RequestAnimationFrame.js"></script>
            <script src="js/Stats.js"></script>
    
            <script>
    
                var container, stats;
    
                var camera, scene, renderer;
    
                var cube, plane;
    
                var windowHalfX = window.innerWidth / 2;
                var windowHalfY = window.innerHeight / 2;
    
                var rad90 = Math.PI * .5;
    
                init();
                animate();
    
                function init() {
    
                    container = document.createElement( 'div' );
                    document.body.appendChild( container );
    
                    var info = document.createElement( 'div' );
                    info.style.position = 'absolute';
                    info.style.top = '10px';
                    info.style.width = '100%';
                    info.style.textAlign = 'center';
                    info.innerHTML = 'click to tween';
                    container.appendChild( info );
    
                    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
                    camera.position.y = 150;
                    camera.position.z = 500;
    
                    scene = new THREE.Scene();
    
                    // Cube
    
                    var materials = [];
    
                    for ( var i = 0; i < 6; i ++ ) {
    
                        materials.push( [ new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) ] );
    
                    }
    
                    cube = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200, 1, 1, 1, materials ), new THREE.MeshFaceMaterial() );
                    cube.position.y = 150;
                    cube.overdraw = true;
                    scene.add( cube );
    
                    // Plane
    
                    plane = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200 ), new THREE.MeshBasicMaterial( { color: 0xe0e0e0 } ) );
                    plane.rotation.x = - 90 * ( Math.PI / 180 );
                    plane.overdraw = true;
                    scene.add( plane );
    
                    renderer = new THREE.CanvasRenderer();
                    renderer.setSize( window.innerWidth, window.innerHeight );
    
                    container.appendChild( renderer.domElement );
    
                    stats = new Stats();
                    stats.domElement.style.position = 'absolute';
                    stats.domElement.style.top = '0px';
                    container.appendChild( stats.domElement );
    
                    document.addEventListener( 'mousedown', onDocumentMouseDown, false );
                }
    
                //
    
                function onDocumentMouseDown( event ) {
    
                    event.preventDefault();
                    new TWEEN.Tween( cube.rotation ).to( {  y:  cube.rotation.y + rad90}, 1000 ).easing( TWEEN.Easing.Quadratic.EaseOut).start();
                    new TWEEN.Tween( plane.rotation ).to( { z:  plane.rotation.z + rad90}, 1000 ).easing( TWEEN.Easing.Quadratic.EaseOut).start();
    
                    console.log("click");
                }
    
                //
    
                function animate() {
    
                    requestAnimationFrame( animate );
    
                    render();
                    stats.update();
    
                }
    
                function render() {
                    TWEEN.update();
                    renderer.render( scene, camera );
    
                }
    
            </script>
    
        </body>
    </html>
    

    【讨论】:

    • 感谢您的帮助!我们最终使用了 Tween.js,一切都很顺利。
    • 我是不是弄错了,或者这会插入欧拉角(这是您通常不想想要做的事情)?如果你想插入四元数怎么办?特别是您通常希望在四元数之间进行 球形 插值。有没有一种简单的方法来调整这段代码来实现这一点?或者我们是否停留在检索自补间开始以来经过的时间(如果可能)并在正确的时间手动调用 quaternion.slerp
    • @Bakuriu 我没有在原始问题中发现有关欧拉旋转的问题。我知道问题是使用正确的类来使用three.js 库为属性(在这种情况下为旋转)设置动画:主要是语法/api 问题,而不是线性代数问题。你是对的,一般来说,在 3D 空间中的旋转应该避免欧拉角,但在这个简单的示例场景中,它并没有真正的区别。您应该可以使用 Tween 类为 Object3Dquaternion 属性设置动画,只需确保在开始补间之前将 useQuaternion 设置为 true
    • 感谢分享!挣扎了一段时间,因为我使用了TWEEN.Easing.Sinusoidal.EaseInOut 而不是TWEEN.Easing.Sinusoidal.InOut。得到一个错误“TypeError: this._easingFunction is not a function”。也许在最近的版本中缓动名称已经改变。
    • @FrostyZ 我明白你的意思。最好仔细检查您正在使用的库版本的参考(值得注意的是这个答案现在已经 6 岁了)。根据您所追求的运动,您可能能够像 Quadratic 这样简单地摆脱困境,如果是这样,它的效率也会稍高一些,因为它没有在幕后使用 Math.sin()/Math.cos()
    猜你喜欢
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 2011-05-20
    相关资源
    最近更新 更多