Three.js Animations
3D animation with Three.js — scene setup, AnimationMixer, keyframe tracks, morph targets, skeletal animation, clock-based loops, and integration with requestAnimationFrame.
You are an expert in Three.js for creating 3D animations in the browser using WebGL.
## Key Points
- Always use `clock.getDelta()` for `mixer.update()` to keep animations frame-rate-independent.
- Dispose of geometries, materials, and textures when removing objects to prevent GPU memory leaks.
- Use `renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))` to cap resolution on high-DPI screens for performance.
- Forgetting to call `mixer.update(delta)` inside the render loop causes animations to appear frozen.
- Calling `clock.getDelta()` more than once per frame returns near-zero on the second call, breaking animation timing for multiple mixers. Call it once and pass the value to all mixers.
## Quick Example
```bash
npm install three
npm install -D @types/three # TypeScript support
```
```js
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
```skilldb get animation-services-skills/Three.js AnimationsFull skill: 136 linesThree.js Animations — Web Animation
You are an expert in Three.js for creating 3D animations in the browser using WebGL.
Core Philosophy
Overview
Three.js is the dominant JavaScript library for 3D graphics on the web. Its animation system revolves around AnimationMixer, AnimationClip, and KeyframeTrack objects that drive property changes over time. Animations can target position, rotation, scale, morph targets, and skeletal bones. The render loop is driven by requestAnimationFrame with a THREE.Clock providing delta-time for frame-rate-independent playback.
Setup & Configuration
npm install three
npm install -D @types/three # TypeScript support
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
Minimal scene with an animation loop:
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({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
// update animations here
renderer.render(scene, camera);
}
animate();
Core Patterns
Keyframe Animation
const times = [0, 1, 2];
const values = [0, 0, 0, 5, 0, 0, 0, 0, 0]; // x,y,z at each keyframe
const positionTrack = new THREE.VectorKeyframeTrack(".position", times, values);
const clip = new THREE.AnimationClip("move", 2, [positionTrack]);
const mixer = new THREE.AnimationMixer(mesh);
const action = mixer.clipAction(clip);
action.play();
// In render loop:
mixer.update(delta);
Loading Animated glTF Models
const loader = new GLTFLoader();
loader.load("/model.glb", (gltf) => {
scene.add(gltf.scene);
const mixer = new THREE.AnimationMixer(gltf.scene);
gltf.animations.forEach((clip) => {
mixer.clipAction(clip).play();
});
// Store mixer for update loop
mixers.push(mixer);
});
Morph Target Animation
const morphTrack = new THREE.NumberKeyframeTrack(
".morphTargetInfluences[0]",
[0, 0.5, 1],
[0, 1, 0]
);
const clip = new THREE.AnimationClip("morph", 1, [morphTrack]);
mixer.clipAction(clip).play();
Controlling Playback
const action = mixer.clipAction(clip);
action.setLoop(THREE.LoopRepeat, Infinity);
action.timeScale = 1.5; // speed up
action.clampWhenFinished = true; // hold last frame
action.fadeIn(0.3); // blend in over 0.3s
// Cross-fade between two actions
previousAction.fadeOut(0.5);
nextAction.reset().fadeIn(0.5).play();
Best Practices
- Always use
clock.getDelta()formixer.update()to keep animations frame-rate-independent. - Dispose of geometries, materials, and textures when removing objects to prevent GPU memory leaks.
- Use
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))to cap resolution on high-DPI screens for performance.
Common Pitfalls
- Forgetting to call
mixer.update(delta)inside the render loop causes animations to appear frozen. - Calling
clock.getDelta()more than once per frame returns near-zero on the second call, breaking animation timing for multiple mixers. Call it once and pass the value to all mixers.
Anti-Patterns
Using the service without understanding its pricing model. Cloud services bill differently — per request, per GB, per seat. Deploying without modeling expected costs leads to surprise invoices.
Hardcoding configuration instead of using environment variables. API keys, endpoints, and feature flags change between environments. Hardcoded values break deployments and leak secrets.
Ignoring the service's rate limits and quotas. Every external API has throughput limits. Failing to implement backoff, queuing, or caching results in dropped requests under load.
Treating the service as always available. External services go down. Without circuit breakers, fallbacks, or graceful degradation, a third-party outage becomes your outage.
Coupling your architecture to a single provider's API. Building directly against provider-specific interfaces makes migration painful. Wrap external services in thin adapter layers.
Install this skill directly: skilldb add animation-services-skills
Related Skills
Anime.js
Lightweight JavaScript animation engine — DOM, CSS, SVG, and object property animations with timeline sequencing, staggering, and spring-based easing.
Auto Animate
Zero-config animation library by FormKit — automatic transitions for DOM additions, removals, and reordering with a single function call or directive.
Framer Motion (Motion)
Production-grade animation library for React — animate, variants, AnimatePresence, layout animations, gestures, scroll-triggered effects, useMotionValue, and stagger orchestration.
GSAP
GreenSock Animation Platform — timeline orchestration, ScrollTrigger, tweens, stagger, React integration with useGSAP, SplitText, morphSVG, and from/to/fromTo patterns.
Lottie
Render After Effects animations on the web with lottie-react and lottie-web — player controls, interactivity, lazy loading, and the light player for optimized bundles.
Motion One
Lightweight Web Animations API wrapper — animate, timeline, spring physics, scroll-linked animations, stagger, and minimal bundle size for modern browsers.