threejs-fundamentals
Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers,…
Three.js animation - keyframe animation, skeletal animation, morph targets, animation mixing. Use when animating objects, playing GLTF animations, creating procedural motion, or blending animations.
$ npx -y skills add cloudai-x/threejs-skills --skill threejs-animation --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/threejs-animationContext preview
The summary Claude sees to decide when to auto-load this skill.
Three.js animation - keyframe animation, skeletal animation, morph targets, animation mixing. Use when animating objects, playing GLTF animations, creating procedural motion, or blending animations.
name: threejs-animation description: Three.js animation - keyframe animation, skeletal animation, morph targets, animation mixing. Use when animating objects, playing GLTF animations, creating procedural motion, or blending animations.
import * as THREE from "three";
// Simple procedural animation
const clock = new THREE.Clock();
function animate() {
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
mesh.rotation.y += delta;
mesh.position.y = Math.sin(elapsed) * 0.5;
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();Three.js animation system has three main components:
1. **AnimationClip** - Container for keyframe data 2. **AnimationMixer** - Plays animations on a root object 3. **AnimationAction** - Controls playback of a clip
Stores keyframe animation data.
// Create animation clip
const times = [0, 1, 2]; // Keyframe times (seconds)
const values = [0, 1, 0]; // Values at each keyframe
const track = new THREE.NumberKeyframeTrack(
".position[y]", // Property path
times,
values,
);
const clip = new THREE.AnimationClip("bounce", 2, [track]);// Number track (single value)
new THREE.NumberKeyframeTrack(".opacity", times, [1, 0]);
new THREE.NumberKeyframeTrack(".material.opacity", times, [1, 0]);
// Vector track (position, scale)
new THREE.VectorKeyframeTrack(".position", times, [
0,
0,
0, // t=0
1,
2,
0, // t=1
0,
0,
0, // t=2
]);
// Quaternion track (rotation)
const q1 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));
const q2 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0));
new THREE.QuaternionKeyframeTrack(
".quaternion",
[0, 1],
[q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w],
);
// Color track
new THREE.ColorKeyframeTrack(".material.color", times, [
1,
0,
0, // red
0,
1,
0, // green
0,
0,
1, // blue
]);
// Boolean track
new THREE.BooleanKeyframeTrack(".visible", [0, 0.5, 1], [true, false, true]);
// String track (for morph targets)
new THREE.StringKeyframeTrack(
".morphTargetInfluences[smile]",
[0, 1],
["0", "1"],
);const track = new THREE.VectorKeyframeTrack(".position", times, values);
// Interpolation
track.setInterpolation(THREE.InterpolateLinear); // Default
track.setInterpolation(THREE.InterpolateSmooth); // Cubic spline
track.setInterpolation(THREE.InterpolateDiscrete); // Step functionPlays animations on an object and its descendants.
const mixer = new THREE.AnimationMixer(model);
// Create action from clip
const action = mixer.clipAction(clip);
action.play();
// Update in animation loop
function animate() {
const delta = clock.getDelta();
mixer.update(delta); // Required!
requestAnimationFrame(animate);
renderer.render(scene, camera);
}mixer.addEventListener("finished", (e) => {
console.log("Animation finished:", e.action.getClip().name);
});
mixer.addEventListener("loop", (e) => {
console.log("Animation looped:", e.action.getClip().name);
});Controls playback of an animation clip.
const action = mixer.clipAction(clip); // Playback control action.play(); action.stop(); action.reset(); action.halt(fadeOutDuration); // Playback state action.isRunning(); action.isScheduled(); // Time control action.time = 0.5; // Current time action.timeScale = 1; // Playback speed (negative = reverse) action.paused = false; // Weight (for blending) action.weight = 1; // 0-1, contribution to final pose action.setEffectiveWeight(1); // Loop modes action.loop = THREE.LoopRepeat; // Default: loop forever action.loop = THREE.LoopOnce; // Play once and stop action.loop = THREE.LoopPingPong; // Alternate forward/backward action.repetitions = 3; // Number of loops (Infinity default) // Clamping action.clampWhenFinished = true; // Hold last frame when done // Blending action.blendMode = THREE.NormalAnimationBlendMode; action.blendMode = THREE.AdditiveAnimationBlendMode;
// Fade in action.reset().fadeIn(0.5).play(); // Fade out action.fadeOut(0.5); // Crossfade between animations const action1 = mixer.clipAction(clip1); const action2 = mixer.clipAction(clip2); action1.play(); // Later, crossfade to action2 action1.crossFadeTo(action2, 0.5, true); action2.play();
Most common source of skeletal animations.
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
const loader = new GLTFLoader();
loader.load("model.glb", (gltf) => {
const model = gltf.scene;
scene.add(model);
// Create mixer
const mixer = new THREE.AnimationMixer(model);
// Get all clips
const clips = gltf.animations;
console.log(
"Available animations:",
clips.map((c) => c.name),
);
// Play first animation
if (clips.length > 0) {
const action = mixer.clipAction(clips[0]);
action.play();
}
// Play specific animation by name
const walkClip = THREE.AnimationClip.findByName(clips, "Walk");
if (walkClip) {
mixer.clipAction(walkClip).play();
}
// Store mixer for update loop
window.mixer = mixer;
});
// Animation loop
function animate() {
const delta = clock.getDelta();
if (window.mixer) window.mixer.update(delta);
requestAnimationFrame(animate);
renderer.render(scene, camera);
}// Access skeleton from skinned mesh
const skinnedMesh = model.getObjectByProperty("type", "SkinnedMesh");
const skeleton = skinnedMesh.skeleton;
// Access bones
skeleton.bones.forEach((bone) => {
console.log(bone.name, bone.position, bone.rotation);
});
// Find specific bone by name
const headBone = skeleton.bones.finA curated collection of Three.js skill files that provide Claude Code with foundational knowledge for creating 3D elements and interactive experiences.
Repo: cloudai-x/threejs-skills
Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers,…
Three.js geometry creation - built-in shapes, BufferGeometry, custom geometry, instancing. Use when creating 3D shapes, working with vertices, building custom…
Three.js interaction - raycasting, controls, mouse/touch input, object selection. Use when handling user input, implementing click detection, adding camera…
Three.js lighting - light types, shadows, environment lighting. Use when adding lights, configuring shadows, setting up IBL, or optimizing lighting performance.
Three.js asset loading - GLTF, textures, images, models, async patterns. Use when loading 3D models, textures, HDR environments, or managing loading progress.
Three.js materials - PBR, basic, phong, shader materials, material properties. Use when styling meshes, working with textures, creating custom shaders, or…