使用 Three.js 动画系统(Animation System)

person 少陵野老    watch_later 2024-10-11 22:59:13
visibility 34    class Animation System    bookmark 专栏

Three.js 提供了强大的动画系统,使得在 3D 场景中为对象添加动画变得简单而高效。本文将详细介绍 Three.js 动画系统的基本概念、常用方法,以及如何在 Three.js 中实现动画效果,包括关键帧动画、混合动画和使用动画控制器。

1. 动画系统的基本概念

Three.js 的动画系统主要由以下几个部分组成:

  • AnimationMixer:用于控制和混合不同的动画。
  • AnimationClip:定义一段动画,包括关键帧和属性变化。
  • KeyframeTrack:表示动画的关键帧和相应的属性变化。

2. 准备工作

确保在 HTML 文件中引入 Three.js:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js 动画系统示例</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>

3. 创建基本的 Three.js 场景

3.1 初始化场景、摄像机和渲染器

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

3.2 添加 3D 对象

我们将在场景中添加一个立方体,以便演示动画效果:

const geometryCube = new THREE.BoxGeometry(1, 1, 1);
const materialCube = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometryCube, materialCube);
scene.add(cube);

camera.position.z = 5;

4. 创建动画

4.1 定义关键帧动画(Keyframe Animation)

创建一个关键帧动画以使立方体在 Y 轴上上下移动:

const mixer = new THREE.AnimationMixer(cube);

const positionKF = new THREE.VectorKeyframeTrack(
    '.position',
    [0, 1, 2], // 时间点
    [0, 2, 0,  // 在这些时间点的 Y 坐标
     0, -2, 0]
);

const clip = new THREE.AnimationClip('moveCube', 2, [positionKF]);
const action = mixer.clipAction(clip);
action.play(); // 播放动画

4.2 更新动画

在渲染循环中更新动画混合器:

function animate() {
    requestAnimationFrame(animate);

    const delta = clock.getDelta(); // 获取时间间隔
    mixer.update(delta); // 更新动画混合器

    renderer.render(scene, camera);
}

const clock = new THREE.Clock(); // 创建时钟
animate();

5. 使用动画控制器

Three.js 还提供了动画控制器,使得控制动画更加灵活。

5.1 创建控制器

创建一个控制器并将其与动画混合器关联:

const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用阻尼
controls.dampingFactor = 0.25;

5.2 在渲染循环中更新控制器

在渲染循环中更新控制器:

function animate() {
    requestAnimationFrame(animate);

    const delta = clock.getDelta();
    mixer.update(delta);
    controls.update(); // 更新控制器

    renderer.render(scene, camera);
}

6. 使用模型和混合动画

Three.js 的动画系统还支持从模型文件中加载动画,下面将展示如何使用 GLTF 模型及其动画。

6.1 加载 GLTF 模型

使用 GLTFLoader 加载模型及其动画:

const loader = new THREE.GLTFLoader();
loader.load('path/to/your/model.glb', (gltf) => {
    const model = gltf.scene;
    scene.add(model);

    const mixer = new THREE.AnimationMixer(model);
    gltf.animations.forEach((clip) => {
        mixer.clipAction(clip).play();
    });
});

6.2 更新混合器

在渲染循环中继续更新混合器,以确保动画的流畅播放:

function animate() {
    requestAnimationFrame(animate);

    const delta = clock.getDelta();
    mixer.update(delta); // 更新混合器

    controls.update();
    renderer.render(scene, camera);
}

7. 完整示例代码

以下是一个完整的示例,展示了如何在 Three.js 中使用动画系统:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js 动画系统示例</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/examples/jsm/loaders/GLTFLoader.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/examples/jsm/controls/OrbitControls.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <script>
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        const geometryCube = new THREE.BoxGeometry(1, 1, 1);
        const materialCube = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        const cube = new THREE.Mesh(geometryCube, materialCube);
        scene.add(cube);

        camera.position.z = 5;

        // 动画
        const mixer = new THREE.AnimationMixer(cube);
        const positionKF = new THREE.VectorKeyframeTrack(
            '.position',
            [0, 1, 2],
            [0, 2, 0, 0, -2, 0]
        );

        const clip = new THREE.AnimationClip('moveCube', 2, [positionKF]);
        const action = mixer.clipAction(clip);
        action.play();

        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;

        const clock = new THREE.Clock();

        function animate() {
            requestAnimationFrame(animate);

            const delta = clock.getDelta();
            mixer.update(delta);
            controls.update();

            renderer.render(scene, camera);
        }

        animate();
    </script>
</body>
</html>

8. 处理窗口调整

确保在窗口调整大小时更新渲染器和摄像机:

window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

9. 结论

在本文中,我们详细探讨了如何在 Three.js 中使用动画系统,包括关键帧动画、混合动画、模型动画的加载及控制。通过这些示例,希望你能够掌握 Three.js 动画系统的使用,创造出更加生动的 3D 场景。若有任何问题或建议,欢迎在评论区留言讨论!

评论区
评论列表
menu