Skip to content
Skillv1.0.0

threejs-animation

Implement and debug Three.js motion with AnimationMixer, clips and actions, GLTF animation playback, skeletal rigs, morph targets, cross-fades, and frame-rate-independent procedural animation. Use whe

by akillness(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from akillness/jeo-skills (.agent-skills/threejs-animation/SKILL.md). Install upstream with npx skills add akillness/jeo-skills --skill threejs-animation. Copyright stays with the author (MIT).

Three.js Animation

Use this skill for the animation implementation itself: clip selection, mixer ownership, blending, skeleton/morph driving, and time-step correctness. Use threejs-loaders to load the model and web-game-development when game-state or combat design—not the animation API—is the primary problem.

When to use this skill

  • Play, pause, seek, loop, or blend AnimationClip data through AnimationMixer
  • Attach GLTF clips to a loaded scene and clean mixers up with the model lifecycle
  • Animate skeletal bones, morph target influences, or lightweight procedural movement
  • Fix actions that do not play, snap during transitions, speed up with frame rate, or leak

Instructions

Step 1: Identify the animation owner and clock

  1. Inspect the model's gltf.animations, root object, and current render-loop owner.
  2. Create one mixer per animated root and advance it once per frame with elapsed delta time, not a fixed per-frame amount.
  3. Preserve action references by semantic name; do not index an exported clip array blindly because asset revisions can reorder clips.
const mixer = new THREE.AnimationMixer(gltf.scene);
const clips = new Map(gltf.animations.map((clip) => [clip.name, clip]));
const idle = mixer.clipAction(clips.get("Idle"));
idle.reset().fadeIn(0.2).play();

const clock = new THREE.Clock();
function update() {
  mixer.update(clock.getDelta());
  renderer.render(scene, camera);
  requestAnimationFrame(update);
}
update();

Step 2: Transition actions without visual discontinuities

Set loop and clamp behavior deliberately, reset an incoming action before playing it, and use cross-fades only when clips share a compatible pose/rig.

function transition(from, to, duration = 0.2) {
  to.reset().setEffectiveWeight(1).setEffectiveTimeScale(1).play();
  from.crossFadeTo(to, duration, false);
}

For one-shot actions, listen for the mixer's finished event and transition back to a known idle action. Remove listeners during feature teardown.

Step 3: Choose the narrowest animation mechanism

Need Default mechanism
Authored transform/property keys AnimationClip + keyframe tracks
Imported character animation AnimationMixer + clipAction
Per-frame idle motion or UI response Delta-time procedural update
Facial expressions or mesh deformation morphTargetInfluences
Runtime bone adjustment Bone transform after mixer update
Layered additive pose Additive clip only after validating reference pose

Apply procedural bone offsets after mixer.update(delta) so the authored clip does not overwrite them. Keep expensive IK, physics, or retargeting behind a measured budget.

Step 4: Dispose animation state with the feature

Call mixer.stopAllAction() and mixer.uncacheRoot(root) when the animated root is permanently removed. Do not uncache a root shared by another scene or instance.

Step 5: Verify animation behavior

  • Test at a low and high frame rate; duration and travel must remain consistent.
  • Test transition interruption, one-shot completion, and rapid action changes.
  • Confirm named clips exist and report a useful error when an expected asset export changes.
  • Verify cleanup by mounting/unmounting the scene repeatedly without growing listeners or retained mixer actions.

Examples

Animate a morph target

const face = gltf.scene.getObjectByName("Face");
face.morphTargetInfluences[0] = 0.75;

Validate that the mesh has morph targets and use a named index map from the asset rather than a magic number when the export includes multiple expressions.

Drive a simple procedural bob

const elapsed = clock.getElapsedTime();
mesh.position.y = baseY + Math.sin(elapsed * 2) * 0.1;

Store baseY separately. Incremental position changes accumulate drift and make mixing with authored animation difficult.

Best practices

  1. Update mixers exactly once per frame with delta seconds.
  2. Prefer exported clips for authored movement; procedural offsets should be additive and localized.
  3. Name clips at export time and validate names at load time.
  4. Avoid cloning a rig or mixer without checking shared skeleton and material ownership.
  5. Profile skinned meshes and morph targets on target hardware before multiplying them.

References

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/akillness-jeo-skills-threejs-animation/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

akillness-jeo-skills-threejs-animation.ocm.jsonjson
{
  "ocm": "1",
  "id": "akillness-jeo-skills-threejs-animation",
  "kind": "skill",
  "name": "threejs-animation",
  "description": "Implement and debug Three.js motion with AnimationMixer, clips and actions, GLTF animation playback, skeletal rigs, morph targets, cross-fades, and frame-rate-independent procedural animation. Use when playing or blending model animations, driving bones or morphs, creating timeline motion, or fixing animation lifecycle and performance issues. Triggers on: Three.js animation, AnimationMixer, AnimationAction, AnimationClip, GLTF animation, skeletal animation, bones, morph targets, crossfade, procedural motion.",
  "publisher": "akillness",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "three-js",
      "animation",
      "animation-mixer",
      "gltf",
      "skeleton",
      "morph-targets",
      "webgl",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Implement and debug Three.js motion with AnimationMixer, clips and actions, GLTF animation playback, skeletal rigs, morph targets, cross-fades, and frame-rate-independent procedural animation. Use when playing or blending model animations, driving bones or morphs, creating timeline motion, or fixing animation lifecycle and performance issues. Triggers on: Three.js animation, AnimationMixer, AnimationAction, AnimationClip, GLTF animation, skeletal animation, bones, morph targets, crossfade, procedural motion."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/akillness/jeo-skills",
      "path": ".agent-skills/threejs-animation/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/akillness/jeo-skills/blob/HEAD/.agent-skills/threejs-animation/SKILL.md",
      "key": "akillness/jeo-skills/.agent-skills/threejs-animation/SKILL.md"
    },
    "allowed_tools": [
      "Bash",
      "Read",
      "Write",
      "Edit",
      "Glob",
      "Grep"
    ],
    "license": "MIT"
  },
  "instructions": "# Three.js Animation\n\nUse this skill for the animation implementation itself: clip selection, mixer ownership,\nblending, skeleton/morph driving, and time-step correctness. Use `threejs-loaders` to\nload the model and `web-game-development` when game-state or combat design—not the\nanimation API—is the primary problem.\n\n## When to use this skill\n\n- Play, pause, seek, loop, or blend `AnimationClip` data through `AnimationMixer`\n- Attach GLTF clips to a loaded scene and clean mixers up with the model lifecycle\n- Animate skeletal bones, morph target influences, or lightweight procedural movement\n- F",
  "cost": {
    "context_tokens": 1163
  }
}

Fetch it by URL: GET /api/v1/registry/akillness-jeo-skills-threejs-animation/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.