Create Three.js AnimationClip with KeyframeTracks
This article explains how to structure a Three.js
AnimationClip using multiple KeyframeTracks.
You will learn how to define individual tracks for properties like
position, rotation, and scale, combine them into a single cohesive
animation clip, and play the resulting animation on a 3D object using
the AnimationMixer.
Understanding the Components
To build an animation in Three.js from scratch, you need three core
components: 1. KeyframeTrack: Defines the values of a
specific property (like position or scale) at specific points in time.
2. AnimationClip: A container that holds one or more
KeyframeTrack objects, representing a complete animation
sequence. 3. AnimationMixer: The player engine that
updates the object’s properties in the render loop based on the
AnimationClip.
Step 1: Create the KeyframeTracks
Each KeyframeTrack requires a target property name, an
array of times (in seconds), and an array of corresponding values.
Three.js provides specialized track classes depending on the data
type: * VectorKeyframeTrack (for position and scale) *
QuaternionKeyframeTrack (for rotation) *
NumberKeyframeTrack (for opacity or morph target
influences)
Here is how to define position and scale tracks:
import * as THREE from 'three';
// Define the time keyframes (in seconds)
const times = [0, 1, 2]; // Start, middle, and end of the animation
// Define position values for each keyframe (X, Y, Z coordinates)
const positionValues = [
0, 0, 0, // Time 0: Origin
0, 5, 0, // Time 1: Moved up 5 units
0, 0, 0 // Time 2: Returned to origin
];
// Define scale values for each keyframe (X, Y, Z scale factors)
const scaleValues = [
1, 1, 1, // Time 0: Normal scale
2, 2, 2, // Time 1: Double scale
1, 1, 1 // Time 2: Normal scale
];
// Create the tracks
// The first argument is the property binding path relative to the target object
const positionTrack = new THREE.VectorKeyframeTrack('.position', times, positionValues);
const scaleTrack = new THREE.VectorKeyframeTrack('.scale', times, scaleValues);Step 2: Combine Tracks into an AnimationClip
Once your tracks are defined, instantiate a
THREE.AnimationClip. The constructor accepts a name for the
animation, the overall duration (set to -1 to automatically
calculate it from the tracks), and an array containing your
KeyframeTrack objects.
// Combine the position and scale tracks into a single clip
const animationDuration = -1; // Auto-calculate duration from keyframes
const moveAndScaleClip = new THREE.AnimationClip('MoveAndScale', animationDuration, [
positionTrack,
scaleTrack
]);Step 3: Play the Animation with the AnimationMixer
To apply the animation to a 3D object (such as a Mesh),
you must associate the object with an AnimationMixer,
create an action from the clip, and update the mixer inside your
animation render loop.
// 1. Create your mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 2. Initialize the AnimationMixer for the mesh
const mixer = new THREE.AnimationMixer(mesh);
// 3. Create an AnimationAction and play it
const action = mixer.clipAction(moveAndScaleClip);
action.play();
// 4. Update the mixer in the render loop
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta(); // Get seconds passed since last frame
mixer.update(delta); // Update the animation evaluation
renderer.render(scene, camera);
}
animate();