Three.js 框架中的 KeyframeTrack 使用详解

person 少陵野老    watch_later 2024-10-12 21:57:08
visibility 42    class KeyframeTrack    bookmark 专栏

简介

KeyframeTrack 是 Three.js 动画系统中的核心组件之一。通过 KeyframeTrack,我们可以定义物体在不同时间点的属性值,从而实现平滑过渡的动画效果。它通常与 AnimationClipAnimationMixerAnimationAction 等其他动画组件配合使用,来创建复杂的动画。

在本博客中,我们将详细讲解 KeyframeTrack 的使用,涵盖它的所有属性和方法,并结合其他组件,通过多个示例代码展示如何使用它来创建动画效果。

基础概念

KeyframeTrack 用于定义某个对象属性(如位置、旋转、缩放等)在一段时间内的变化。它本质上是一条包含时间和属性值的“关键帧轨道”,通过插值这些关键帧来产生动画。

基本结构

KeyframeTrack( name, times, values, interpolation )
  • name:字符串,表示轨道的名称,通常以 '.' 分隔,用于指定对象的具体属性。例如:'mesh.position'
  • times:数组,表示动画关键帧发生的时间点。
  • values:数组,表示在每个时间点上属性的值。
  • interpolation:插值方式,默认是 THREE.InterpolateLinear,也可以使用其他插值方法。

KeyframeTrack 的类型

Three.js 提供了多种具体的 KeyframeTrack 类型来处理不同类型的属性:

  • VectorKeyframeTrack:用于矢量属性(如位置、缩放)的动画。
  • QuaternionKeyframeTrack:用于旋转(四元数)的动画。
  • ColorKeyframeTrack:用于颜色属性的动画。
  • NumberKeyframeTrack:用于数值属性的动画。
  • BooleanKeyframeTrack:用于布尔值属性的动画。
  • StringKeyframeTrack:用于字符串属性的动画。

VectorKeyframeTrack 示例

创建一个简单的物体位置变化动画:

import * as THREE from 'three';

// 场景和相机
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;

// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建一个简单的几何体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 创建位置关键帧动画
const times = [0, 1, 2]; // 关键帧时间点
const values = [0, 0, 0, 5, 5, 0, -5, 0, 0]; // 对应时间点的坐标

const positionTrack = new THREE.VectorKeyframeTrack('.position', times, values);

// 创建 AnimationClip
const clip = new THREE.AnimationClip('move', -1, [positionTrack]);

// 动画混合器
const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();

// 渲染循环
const clock = new THREE.Clock();
function animate() {
  requestAnimationFrame(animate);

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

  renderer.render(scene, camera);
}
animate();

QuaternionKeyframeTrack 示例

通过四元数旋转物体:

const times = [0, 1, 2]; // 时间
const values = [
  0, 0, 0, 1,   // 初始旋转(四元数)
  0.707, 0, 0, 0.707,  // 旋转90度
  0, 0, 0, 1   // 恢复原状
];

const rotationTrack = new THREE.QuaternionKeyframeTrack('.quaternion', times, values);

const clip = new THREE.AnimationClip('rotate', -1, [rotationTrack]);

const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();

ColorKeyframeTrack 示例

改变物体颜色的动画:

const times = [0, 1, 2];
const values = [1, 0, 0,  0, 1, 0,  0, 0, 1];  // RGB颜色变化

const colorTrack = new THREE.ColorKeyframeTrack('.material.color', times, values);

const clip = new THREE.AnimationClip('colorChange', -1, [colorTrack]);

const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();

NumberKeyframeTrack 示例

修改物体的不透明度(opacity)动画:

const times = [0, 1, 2];
const values = [1, 0.5, 0]; // 透明度变化

const opacityTrack = new THREE.NumberKeyframeTrack('.material.opacity', times, values);

cube.material.transparent = true; // 使材质透明以支持透明度
const clip = new THREE.AnimationClip('fade', -1, [opacityTrack]);

const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();

BooleanKeyframeTrack 示例

控制物体可见性:

const times = [0, 1, 2];
const values = [true, false, true];  // 可见性变化

const visibilityTrack = new THREE.BooleanKeyframeTrack('.visible', times, values);

const clip = new THREE.AnimationClip('visibilityChange', -1, [visibilityTrack]);

const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();

StringKeyframeTrack 示例

虽然比较少见,但可以通过 StringKeyframeTrack 改变对象的某些字符串属性:

const times = [0, 1, 2];
const values = ['first', 'second', 'third'];

const stringTrack = new THREE.StringKeyframeTrack('.name', times, values);

const clip = new THREE.AnimationClip('nameChange', -1, [stringTrack]);

const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();

KeyframeTrack 属性与方法

KeyframeTrack 本身提供了一些用于控制和获取轨道信息的方法和属性:

属性

  • name:轨道的名称。
  • times:包含关键帧时间点的数组。
  • values:包含关键帧值的数组。
  • ValueTypeName:轨道值的类型。
  • TimeBufferType:时间缓冲区的类型,通常为 Float32Array
  • ValueBufferType:值缓冲区的类型。

方法

  • getValueSize():返回每个关键帧的值的大小。对于位置、颜色等,通常是 3;对于四元数,则是 4。
  • validate():验证时间和值数组是否匹配。
  • optimize():删除冗余关键帧,优化轨道。
const isValid = positionTrack.validate(); // 验证轨道是否有效
positionTrack.optimize(); // 优化轨道

与 AnimationClip、AnimationMixer 的结合使用

KeyframeTrack 通常不会单独使用,而是与 AnimationClipAnimationMixer 配合使用:

  • AnimationClip:包含一个或多个 KeyframeTrack 的动画片段。
  • AnimationMixer:管理和控制动画片段的播放。

我们通过这些组件将 KeyframeTrack 转化为可以播放的动画。

// 定义关键帧轨道
const positionTrack = new THREE.VectorKeyframeTrack('.position', times, values);

// 创建动画剪辑
const clip = new THREE.AnimationClip('move', -1, [positionTrack]);

// 创建混合器和动作
const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);

// 播放动画
action.play();

完整示例:结合多种 KeyframeTrack 实现复杂动画

import * as THREE from 'three';

// 初始化场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建几何体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 创建位置、旋转、颜色和透明度的关键帧轨道
const positionTrack = new THREE.VectorKeyframeTrack('.position', [0, 2, 4], [0, 0, 0, 2, 2, 0, 0, 0, 0]);
const rotationTrack = new THREE.QuaternionKeyframeTrack('.quaternion', [0, 2, 4], [0, 0, 0, 1, 0.707, 0, 0.707, 0, 0, 0, 1]);
const colorTrack = new THREE.ColorKeyframeTrack('.material.color', [0, 2, 4], [1, 0, 0, 0, 1, 0, 0, 0, 1]);
const opacityTrack = new THREE.NumberKeyframeTrack('.material.opacity', [0, 2, 4], [1, 0.5, 0]);

// 创建动画剪辑
const clip = new THREE.AnimationClip('complexAnimation', -1, [positionTrack, rotationTrack, colorTrack, opacityTrack]);

// 创建动画混合器并播放
const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();

// 渲染循环
const clock = new THREE.Clock();
function animate() {
  requestAnimationFrame(animate);
  const delta = clock.getDelta();
  mixer.update(delta); // 更新混合器
  renderer.render(scene, camera); // 渲染场景
}
animate();

总结

KeyframeTrack 是 Three.js 动画系统的重要组成部分,通过它我们可以实现丰富多彩的动画效果。在本篇博客中,我们详细介绍了 KeyframeTrack 的使用,涵盖了多种类型的关键帧轨道及其结合使用的示例。掌握 KeyframeTrack 的用法将使您在 Three.js 中实现复杂动画变得轻松而高效。希望这些示例和代码能够帮助您更好地理解 Three.js 动画系统的强大功能。

评论区
评论列表
menu