美文网首页
three.js(32)-AnimationObjectGrou

three.js(32)-AnimationObjectGrou

作者: 姜治宇 | 来源:发表于2023-01-10 16:44 被阅读0次

我们可以给一组对象赋予一套动作,让他们整体划一的动起来。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="http://www.yanhuangxueyuan.com/threejs/build/three.min.js"></script>
    <script src="http://www.yanhuangxueyuan.com/threejs/examples/js/controls/OrbitControls.js"></script>
    <title>Document</title>
    <style>
        .label {
            color: #FFF;
            padding: 2px;
            background-color: rgb(20, 143, 211, 0.68);
            box-shadow: 0 0 12px rgba(0, 128, 255, 0.75);
            border: 1px solid rgba(127, 177, 255, 0.75);
        }
    </style>
</head>

<body>
    <div id="webgl"></div>

</body>

</html>
<script>
    var scene, camera, clock;

    function init() {
        scene = new THREE.Scene();
        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set( 50, 50, 50 );
        camera.lookAt( scene.position );

        scene.add(camera);//添加相机
        //添加坐标轴
        var axes = new THREE.AxesHelper(500);//500表示xyz轴的长度,红:x,绿:y,蓝:z
        scene.add(axes);


        const animationGroup = new THREE.AnimationObjectGroup();//创建动画对象组
        const geometry = new THREE.BoxGeometry( 5, 5, 5 );
        const material = new THREE.MeshBasicMaterial( { transparent: true } );
        //创建一大坨物体对象
        for (let i = 0; i < 5; i++) {

            for (let j = 0; j < 5; j++) {

                const mesh = new THREE.Mesh(geometry, material);

                mesh.position.x = 32 - (16 * i);
                mesh.position.y = 0;
                mesh.position.z = 32 - (16 * j);

                scene.add(mesh);

                animationGroup.add(mesh);//把一坨统统丢进animationGroup,然后给整体定义动作

                //=========================================定义帧==================================================//
                //一共三帧即可,开始,结束,开始
                const xAxis = new THREE.Vector3( 1, 0, 0 );//旋转轴
                const qInitial = new THREE.Quaternion().setFromAxisAngle( xAxis, 0 );//开始旋转,绕x轴0°
                const qFinal = new THREE.Quaternion().setFromAxisAngle( xAxis, Math.PI );//结束旋转,绕x轴旋转180°
                //定义旋转变化,最后一个参数数组,会根据前面的参数,共划分为3组
                const quaternionKF = new THREE.QuaternionKeyframeTrack( '.quaternion', [ 0, 1, 2 ], [ qInitial.x, qInitial.y, qInitial.z, qInitial.w, qFinal.x, qFinal.y, qFinal.z, qFinal.w, qInitial.x, qInitial.y, qInitial.z, qInitial.w ] );
                //定义颜色变化
                const colorKF = new THREE.KeyframeTrack( '.material.color', [ 0, 1, 2 ], [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]);//名称(不可乱起),times,values(必须是展开数组)
                //定义透明度变化
                const opacityKF = new THREE.KeyframeTrack( '.material.opacity', [ 0, 1, 2 ], [ 1, 0, 1 ] );//名称不可乱起

                //===============================================================================================//

                const clip = new THREE.AnimationClip( 'hellojack', 3, [ quaternionKF, colorKF, opacityKF ] );//名称(随便起),延时播放时间,帧

    

                mixer = new THREE.AnimationMixer( animationGroup );

                const clipAction = mixer.clipAction( clip );

                clipAction.play();

                clock = new THREE.Clock();//初始化时钟
            }

        }


    }

    function render() {


        renderer = new THREE.WebGLRenderer({
            antialias: true,
            alpha: true
        });//画布
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);//设置渲染区域尺寸
        renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
        document.getElementById('webgl').appendChild(renderer.domElement);
        var controls = new THREE.OrbitControls(camera, renderer.domElement);

    }
    function animate() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
       
        if ( mixer ) {

            mixer.update( clock.getDelta() );

        }
    }

    init();

    render();

    animate();
</script>

这个例子用到了四元数。四元数跟欧拉角都是描述物体旋转的,因为欧拉角沿着自身坐标轴旋转的话,会有万向节死锁的问题,所以大部分场合下我们都是用四元数。四元数有四个数,分别是x,y,z,w,不过四元数的问题是数值看起来不直观,因此没有什么价值,可以忽略。
关于KeyframeTrack有好多种类型,一般KeyframeTrack即可大部分需求,不过旋转这块得用QuaternionKeyframeTrack,否则会有问题,大家可以试一下。


GIF 2023-1-11 16-38-56.gif

相关文章

网友评论

      本文标题:three.js(32)-AnimationObjectGrou

      本文链接:https://www.haomeiwen.com/subject/ngevcdtx.html