{"id":"a28c8303-b8f3-4888-bfbc-4a8caa324040","shortId":"gYvv7R","kind":"skill","title":"threejs-animation","tagline":"Three.js animation - keyframe animation, skeletal animation, morph targets, animation mixing. Use when animating objects, playing GLTF animations, creating procedural motion, or blending animations.","description":"# Three.js Animation\n\n## When to Use\n- You need to animate objects, rigs, morph targets, or imported GLTF animations in Three.js.\n- The task involves mixers, clips, keyframes, procedural motion, or animation blending.\n- You are building motion behavior in a Three.js scene rather than just static rendering.\n\n## Quick Start\n\n```javascript\nimport * as THREE from \"three\";\n\n// Simple procedural animation with Timer (recommended in r183)\nconst timer = new THREE.Timer();\n\nrenderer.setAnimationLoop(() => {\n  timer.update();\n  const delta = timer.getDelta();\n  const elapsed = timer.getElapsed();\n\n  mesh.rotation.y += delta;\n  mesh.position.y = Math.sin(elapsed) * 0.5;\n\n  renderer.render(scene, camera);\n});\n```\n\n**Note:** `THREE.Timer` is recommended over `THREE.Clock` as of r183. Timer pauses when the page is hidden and has a cleaner API. `THREE.Clock` still works but is considered legacy.\n\n## Animation System Overview\n\nThree.js animation system has three main components:\n\n1. **AnimationClip** - Container for keyframe data\n2. **AnimationMixer** - Plays animations on a root object\n3. **AnimationAction** - Controls playback of a clip\n\n## AnimationClip\n\nStores keyframe animation data.\n\n```javascript\n// Create animation clip\nconst times = [0, 1, 2]; // Keyframe times (seconds)\nconst values = [0, 1, 0]; // Values at each keyframe\n\nconst track = new THREE.NumberKeyframeTrack(\n  \".position[y]\", // Property path\n  times,\n  values,\n);\n\nconst clip = new THREE.AnimationClip(\"bounce\", 2, [track]);\n```\n\n### KeyframeTrack Types\n\n```javascript\n// Number track (single value)\nnew THREE.NumberKeyframeTrack(\".opacity\", times, [1, 0]);\nnew THREE.NumberKeyframeTrack(\".material.opacity\", times, [1, 0]);\n\n// Vector track (position, scale)\nnew THREE.VectorKeyframeTrack(\".position\", times, [\n  0,\n  0,\n  0, // t=0\n  1,\n  2,\n  0, // t=1\n  0,\n  0,\n  0, // t=2\n]);\n\n// Quaternion track (rotation)\nconst q1 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));\nconst q2 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0));\nnew THREE.QuaternionKeyframeTrack(\n  \".quaternion\",\n  [0, 1],\n  [q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w],\n);\n\n// Color track\nnew THREE.ColorKeyframeTrack(\".material.color\", times, [\n  1,\n  0,\n  0, // red\n  0,\n  1,\n  0, // green\n  0,\n  0,\n  1, // blue\n]);\n\n// Boolean track\nnew THREE.BooleanKeyframeTrack(\".visible\", [0, 0.5, 1], [true, false, true]);\n\n// String track (for morph targets)\nnew THREE.StringKeyframeTrack(\n  \".morphTargetInfluences[smile]\",\n  [0, 1],\n  [\"0\", \"1\"],\n);\n```\n\n### Interpolation Modes\n\n```javascript\nconst track = new THREE.VectorKeyframeTrack(\".position\", times, values);\n\n// Interpolation\ntrack.setInterpolation(THREE.InterpolateLinear); // Default\ntrack.setInterpolation(THREE.InterpolateSmooth); // Cubic spline\ntrack.setInterpolation(THREE.InterpolateDiscrete); // Step function\n```\n\n### BezierInterpolant (r183)\n\nThree.js r183 adds `THREE.BezierInterpolant` for bezier curve interpolation in keyframe tracks, enabling smoother animation curves with tangent control.\n\n## AnimationMixer\n\nPlays animations on an object and its descendants.\n\n```javascript\nconst mixer = new THREE.AnimationMixer(model);\n\n// Create action from clip\nconst action = mixer.clipAction(clip);\naction.play();\n\n// Update in animation loop\nfunction animate() {\n  const delta = clock.getDelta();\n  mixer.update(delta); // Required!\n\n  requestAnimationFrame(animate);\n  renderer.render(scene, camera);\n}\n```\n\n### Mixer Events\n\n```javascript\nmixer.addEventListener(\"finished\", (e) => {\n  console.log(\"Animation finished:\", e.action.getClip().name);\n});\n\nmixer.addEventListener(\"loop\", (e) => {\n  console.log(\"Animation looped:\", e.action.getClip().name);\n});\n```\n\n## AnimationAction\n\nControls playback of an animation clip.\n\n```javascript\nconst action = mixer.clipAction(clip);\n\n// Playback control\naction.play();\naction.stop();\naction.reset();\naction.halt(fadeOutDuration);\n\n// Playback state\naction.isRunning();\naction.isScheduled();\n\n// Time control\naction.time = 0.5; // Current time\naction.timeScale = 1; // Playback speed (negative = reverse)\naction.paused = false;\n\n// Weight (for blending)\naction.weight = 1; // 0-1, contribution to final pose\naction.setEffectiveWeight(1);\n\n// Loop modes\naction.loop = THREE.LoopRepeat; // Default: loop forever\naction.loop = THREE.LoopOnce; // Play once and stop\naction.loop = THREE.LoopPingPong; // Alternate forward/backward\naction.repetitions = 3; // Number of loops (Infinity default)\n\n// Clamping\naction.clampWhenFinished = true; // Hold last frame when done\n\n// Blending\naction.blendMode = THREE.NormalAnimationBlendMode;\naction.blendMode = THREE.AdditiveAnimationBlendMode;\n```\n\n### Fade In/Out\n\n```javascript\n// Fade in\naction.reset().fadeIn(0.5).play();\n\n// Fade out\naction.fadeOut(0.5);\n\n// Crossfade between animations\nconst action1 = mixer.clipAction(clip1);\nconst action2 = mixer.clipAction(clip2);\n\naction1.play();\n\n// Later, crossfade to action2\naction1.crossFadeTo(action2, 0.5, true);\naction2.play();\n```\n\n## Loading GLTF Animations\n\nMost common source of skeletal animations.\n\n```javascript\nimport { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\n\nconst loader = new GLTFLoader();\nloader.load(\"model.glb\", (gltf) => {\n  const model = gltf.scene;\n  scene.add(model);\n\n  // Create mixer\n  const mixer = new THREE.AnimationMixer(model);\n\n  // Get all clips\n  const clips = gltf.animations;\n  console.log(\n    \"Available animations:\",\n    clips.map((c) => c.name),\n  );\n\n  // Play first animation\n  if (clips.length > 0) {\n    const action = mixer.clipAction(clips[0]);\n    action.play();\n  }\n\n  // Play specific animation by name\n  const walkClip = THREE.AnimationClip.findByName(clips, \"Walk\");\n  if (walkClip) {\n    mixer.clipAction(walkClip).play();\n  }\n\n  // Store mixer for update loop\n  window.mixer = mixer;\n});\n\n// Animation loop\nfunction animate() {\n  const delta = clock.getDelta();\n  if (window.mixer) window.mixer.update(delta);\n\n  requestAnimationFrame(animate);\n  renderer.render(scene, camera);\n}\n```\n\n## Skeletal Animation\n\n### Skeleton and Bones\n\n```javascript\n// Access skeleton from skinned mesh\nconst skinnedMesh = model.getObjectByProperty(\"type\", \"SkinnedMesh\");\nconst skeleton = skinnedMesh.skeleton;\n\n// Access bones\nskeleton.bones.forEach((bone) => {\n  console.log(bone.name, bone.position, bone.rotation);\n});\n\n// Find specific bone by name\nconst headBone = skeleton.bones.find((b) => b.name === \"Head\");\nif (headBone) headBone.rotation.y = Math.PI / 4; // Turn head\n\n// Skeleton helper\nconst helper = new THREE.SkeletonHelper(model);\nscene.add(helper);\n```\n\n### Programmatic Bone Animation\n\n```javascript\nfunction animate() {\n  const time = clock.getElapsedTime();\n\n  // Animate bone\n  const headBone = skeleton.bones.find((b) => b.name === \"Head\");\n  if (headBone) {\n    headBone.rotation.y = Math.sin(time) * 0.3;\n  }\n\n  // Update mixer if also playing clips\n  mixer.update(clock.getDelta());\n}\n```\n\n### Bone Attachments\n\n```javascript\n// Attach object to bone\nconst weapon = new THREE.Mesh(weaponGeometry, weaponMaterial);\nconst handBone = skeleton.bones.find((b) => b.name === \"RightHand\");\nif (handBone) handBone.add(weapon);\n\n// Offset attachment\nweapon.position.set(0, 0, 0.5);\nweapon.rotation.set(0, Math.PI / 2, 0);\n```\n\n## Morph Targets\n\nBlend between different mesh shapes.\n\n```javascript\n// Morph targets are stored in geometry\nconst geometry = mesh.geometry;\nconsole.log(\"Morph attributes:\", Object.keys(geometry.morphAttributes));\n\n// Access morph target influences\nmesh.morphTargetInfluences; // Array of weights\nmesh.morphTargetDictionary; // Name -> index mapping\n\n// Set morph target by index\nmesh.morphTargetInfluences[0] = 0.5;\n\n// Set by name\nconst smileIndex = mesh.morphTargetDictionary[\"smile\"];\nmesh.morphTargetInfluences[smileIndex] = 1;\n```\n\n### Animating Morph Targets\n\n```javascript\n// Procedural\nfunction animate() {\n  const t = clock.getElapsedTime();\n  mesh.morphTargetInfluences[0] = (Math.sin(t) + 1) / 2;\n}\n\n// With keyframe animation\nconst track = new THREE.NumberKeyframeTrack(\n  \".morphTargetInfluences[smile]\",\n  [0, 0.5, 1],\n  [0, 1, 0],\n);\nconst clip = new THREE.AnimationClip(\"smile\", 1, [track]);\nmixer.clipAction(clip).play();\n```\n\n## Animation Blending\n\nMix multiple animations together.\n\n```javascript\n// Setup actions\nconst idleAction = mixer.clipAction(idleClip);\nconst walkAction = mixer.clipAction(walkClip);\nconst runAction = mixer.clipAction(runClip);\n\n// Play all with different weights\nidleAction.play();\nwalkAction.play();\nrunAction.play();\n\n// Set initial weights\nidleAction.setEffectiveWeight(1);\nwalkAction.setEffectiveWeight(0);\nrunAction.setEffectiveWeight(0);\n\n// Blend based on speed\nfunction updateAnimations(speed) {\n  if (speed < 0.1) {\n    idleAction.setEffectiveWeight(1);\n    walkAction.setEffectiveWeight(0);\n    runAction.setEffectiveWeight(0);\n  } else if (speed < 5) {\n    const t = speed / 5;\n    idleAction.setEffectiveWeight(1 - t);\n    walkAction.setEffectiveWeight(t);\n    runAction.setEffectiveWeight(0);\n  } else {\n    const t = Math.min((speed - 5) / 5, 1);\n    idleAction.setEffectiveWeight(0);\n    walkAction.setEffectiveWeight(1 - t);\n    runAction.setEffectiveWeight(t);\n  }\n}\n```\n\n### Additive Blending\n\n```javascript\n// Base pose\nconst baseAction = mixer.clipAction(baseClip);\nbaseAction.play();\n\n// Additive layer (e.g., breathing)\nconst additiveAction = mixer.clipAction(additiveClip);\nadditiveAction.blendMode = THREE.AdditiveAnimationBlendMode;\nadditiveAction.play();\n\n// Convert clip to additive\nTHREE.AnimationUtils.makeClipAdditive(additiveClip);\n```\n\n## Animation Utilities\n\n```javascript\nimport * as THREE from \"three\";\n\n// Find clip by name\nconst clip = THREE.AnimationClip.findByName(clips, \"Walk\");\n\n// Create subclip\nconst subclip = THREE.AnimationUtils.subclip(clip, \"subclip\", 0, 30, 30);\n\n// Convert to additive\nTHREE.AnimationUtils.makeClipAdditive(clip);\nTHREE.AnimationUtils.makeClipAdditive(clip, 0, referenceClip);\n\n// Clone clip\nconst clone = clip.clone();\n\n// Get clip duration\nclip.duration;\n\n// Optimize clip (remove redundant keyframes)\nclip.optimize();\n\n// Reset clip to first frame\nclip.resetDuration();\n```\n\n## Procedural Animation Patterns\n\n### Smooth Damping\n\n```javascript\n// Smooth follow/lerp\nconst target = new THREE.Vector3();\nconst current = new THREE.Vector3();\nconst velocity = new THREE.Vector3();\n\nfunction smoothDamp(current, target, velocity, smoothTime, deltaTime) {\n  const omega = 2 / smoothTime;\n  const x = omega * deltaTime;\n  const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);\n  const change = current.clone().sub(target);\n  const temp = velocity\n    .clone()\n    .add(change.clone().multiplyScalar(omega))\n    .multiplyScalar(deltaTime);\n  velocity.sub(temp.clone().multiplyScalar(omega)).multiplyScalar(exp);\n  return target.clone().add(change.add(temp).multiplyScalar(exp));\n}\n\nfunction animate() {\n  current.copy(smoothDamp(current, target, velocity, 0.3, delta));\n  mesh.position.copy(current);\n}\n```\n\n### Spring Physics\n\n```javascript\nclass Spring {\n  constructor(stiffness = 100, damping = 10) {\n    this.stiffness = stiffness;\n    this.damping = damping;\n    this.position = 0;\n    this.velocity = 0;\n    this.target = 0;\n  }\n\n  update(dt) {\n    const force = -this.stiffness * (this.position - this.target);\n    const dampingForce = -this.damping * this.velocity;\n    this.velocity += (force + dampingForce) * dt;\n    this.position += this.velocity * dt;\n    return this.position;\n  }\n}\n\nconst spring = new Spring(100, 10);\nspring.target = 1;\n\nfunction animate() {\n  mesh.position.y = spring.update(delta);\n}\n```\n\n### Oscillation\n\n```javascript\nfunction animate() {\n  const t = clock.getElapsedTime();\n\n  // Sine wave\n  mesh.position.y = Math.sin(t * 2) * 0.5;\n\n  // Bouncing\n  mesh.position.y = Math.abs(Math.sin(t * 3)) * 2;\n\n  // Circular motion\n  mesh.position.x = Math.cos(t) * 2;\n  mesh.position.z = Math.sin(t) * 2;\n\n  // Figure 8\n  mesh.position.x = Math.sin(t) * 2;\n  mesh.position.z = Math.sin(t * 2) * 1;\n}\n```\n\n## Performance Tips\n\n1. **Share clips**: Same AnimationClip can be used on multiple mixers\n2. **Optimize clips**: Call `clip.optimize()` to remove redundant keyframes\n3. **Disable when off-screen**: Stop mixer updates for invisible objects\n4. **Use LOD for animations**: Simpler rigs for distant characters\n5. **Limit active mixers**: Each mixer.update() has a cost\n\n```javascript\n// Pause animation when not visible\nmesh.onBeforeRender = () => {\n  action.paused = false;\n};\n\nmesh.onAfterRender = () => {\n  // Check if will be visible next frame\n  if (!isInFrustum(mesh)) {\n    action.paused = true;\n  }\n};\n\n// Cache clips\nconst clipCache = new Map();\nfunction getClip(name) {\n  if (!clipCache.has(name)) {\n    clipCache.set(name, loadClip(name));\n  }\n  return clipCache.get(name);\n}\n```\n\n## See Also\n\n- `threejs-loaders` - Loading animated GLTF models\n- `threejs-fundamentals` - Clock and animation loop\n- `threejs-shaders` - Vertex animation in shaders\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.","tags":["threejs","animation","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows"],"capabilities":["skill","source-sickn33","skill-threejs-animation","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/threejs-animation","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34460 github stars · SKILL.md body (13,301 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T06:52:01.095Z","embedding":null,"createdAt":"2026-04-18T21:46:16.047Z","updatedAt":"2026-04-22T06:52:01.095Z","lastSeenAt":"2026-04-22T06:52:01.095Z","tsv":"'-1':477 '0':180,188,190,224,230,239,240,241,243,246,249,250,251,264,265,266,274,276,280,297,298,300,302,304,305,313,328,330,476,605,610,763,764,767,770,811,834,848,851,853,899,901,915,917,932,942,999,1009,1133,1135,1137 '0.1':911 '0.235':1075 '0.3':728,1114 '0.48':1072 '0.5':106,314,460,528,533,552,765,812,849,1186 '1':148,181,189,223,229,244,248,281,296,301,306,315,329,331,464,475,483,822,837,850,852,859,897,913,927,940,944,1069,1070,1165,1219,1222 '10':1127,1163 '100':1125,1162 '2':154,182,210,245,253,769,838,1061,1185,1194,1201,1206,1213,1218,1233 '3':162,502,1193,1242 '30':1000,1001 '4':693,1254 '5':921,925,938,939,1264 '8':1208 'access':656,669,793 'action':390,394,443,607,872 'action.blendmode':517,519 'action.clampwhenfinished':509 'action.fadeout':532 'action.halt':451 'action.isrunning':455 'action.isscheduled':456 'action.loop':486,491,497 'action.paused':469,1280,1293 'action.play':397,448,611 'action.repetitions':501 'action.reset':450,526 'action.seteffectiveweight':482 'action.stop':449 'action.time':459 'action.timescale':463 'action.weight':474 'action1':538 'action1.crossfadeto':550 'action1.play':545 'action2':542,549,551 'action2.play':554 'activ':1266 'add':358,1088,1102 'addit':948,958,972,1004 'additiveact':963 'additiveaction.blendmode':966 'additiveaction.play':968 'additiveclip':965,974 'also':732,1315 'altern':499 'anim':3,5,7,9,12,16,20,26,28,35,43,55,81,138,142,157,172,176,369,376,400,403,411,422,430,439,536,557,563,596,602,614,634,637,646,651,707,710,714,823,829,841,864,868,975,1033,1108,1167,1175,1258,1275,1320,1328,1334 'animationact':163,434 'animationclip':149,169,1226 'animationmix':155,374 'api':130 'array':798 'ask':1370 'attach':738,740,761 'attribut':790 'avail':595 'b':685,719,753 'b.name':686,720,754 'base':903,951 'baseact':954 'baseaction.play':957 'baseclip':956 'behavior':61 'bezier':361 'bezierinterpol':354 'blend':25,56,473,516,773,865,902,949 'blue':307 'bone':654,670,672,679,706,715,737,743 'bone.name':674 'bone.position':675 'bone.rotation':676 'boolean':308 'bounc':209,1187 'boundari':1378 'breath':961 'build':59 'c':598 'c.name':599 'cach':1295 'call':1236 'camera':109,414,649 'chang':1080 'change.add':1103 'change.clone':1089 'charact':1263 'check':1283 'circular':1195 'clamp':508 'clarif':1372 'class':1121 'cleaner':129 'clear':1345 'clip':50,168,177,206,392,396,440,445,590,592,609,620,734,855,862,970,984,988,990,997,1006,1008,1012,1017,1021,1027,1224,1235,1296 'clip.clone':1015 'clip.duration':1019 'clip.optimize':1025,1237 'clip.resetduration':1031 'clip1':540 'clip2':544 'clipcach':1298 'clipcache.get':1312 'clipcache.has':1305 'clipcache.set':1307 'clips.length':604 'clips.map':597 'clock':1326 'clock.getdelta':406,640,736 'clock.getelapsedtime':713,832,1178 'clone':1011,1014,1087 'color':290 'common':559 'compon':147 'consid':136 'console.log':421,429,594,673,788 'const':87,93,96,178,186,195,205,257,267,335,384,393,404,442,537,541,569,576,583,591,606,617,638,661,666,682,698,711,716,744,750,785,816,830,842,854,873,877,881,922,934,953,962,987,994,1013,1040,1044,1048,1059,1063,1067,1079,1084,1140,1145,1158,1176,1297 'constructor':1123 'contain':150 'contribut':478 'control':164,373,435,447,458 'convert':969,1002 'cost':1272 'creat':21,175,389,581,992 'criteria':1381 'crossfad':534,547 'cubic':348 'current':461,1045,1054,1111,1117 'current.clone':1081 'current.copy':1109 'curv':362,370 'damp':1036,1126,1131 'dampingforc':1146,1151 'data':153,173 'default':345,488,507 'delta':94,101,405,408,639,644,1115,1171 'deltatim':1058,1066,1093 'descend':382 'describ':1349 'differ':775,888 'disabl':1243 'distant':1262 'done':515 'dt':1139,1152,1155 'durat':1018 'e':420,428 'e.action.getclip':424,432 'e.g':960 'elaps':97,105 'els':918,933 'enabl':367 'environ':1361 'environment-specif':1360 'event':416 'exp':1068,1099,1106 'expert':1366 'fade':521,524,530 'fadein':527 'fadeoutdur':452 'fals':317,470,1281 'figur':1207 'final':480 'find':677,983 'finish':419,423 'first':601,1029 'follow/lerp':1039 'forc':1141,1150 'forev':490 'forward/backward':500 'frame':513,1030,1289 'function':353,402,636,709,828,906,1052,1107,1166,1174,1301 'fundament':1325 'geometri':784,786 'geometry.morphattributes':792 'get':588,1016 'getclip':1302 'gltf':19,42,556,575,1321 'gltf.animations':593 'gltf.scene':578 'gltfloader':566,572 'green':303 'handbon':751,757 'handbone.add':758 'head':687,695,721 'headbon':683,689,717,723 'headbone.rotation':690,724 'helper':697,699,704 'hidden':125 'hold':511 'idleact':874 'idleaction.play':890 'idleaction.seteffectiveweight':896,912,926,941 'idleclip':876 'import':41,74,565,978 'in/out':522 'index':803,809 'infin':506 'influenc':796 'initi':894 'input':1375 'interpol':332,342,363 'invis':1252 'involv':48 'isinfrustum':1291 'javascript':73,174,214,334,383,417,441,523,564,655,708,739,778,826,870,950,977,1037,1120,1173,1273 'keyfram':6,51,152,171,183,194,365,840,1024,1241 'keyframetrack':212 'last':512 'later':546 'layer':959 'legaci':137 'limit':1265,1337 'load':555,1319 'loadclip':1309 'loader':570,1318 'loader.load':573 'lod':1256 'loop':401,427,431,484,489,505,631,635,1329 'main':146 'map':804,1300 'match':1346 'material.color':294 'material.opacity':227 'math.abs':1190 'math.cos':1199 'math.min':936 'math.pi':275,692,768 'math.sin':104,726,835,1183,1191,1204,1211,1216 'mesh':660,776,1292 'mesh.geometry':787 'mesh.morphtargetdictionary':801,818 'mesh.morphtargetinfluences':797,810,820,833 'mesh.onafterrender':1282 'mesh.onbeforerender':1279 'mesh.position':102,1168,1181,1188,1197,1202,1209,1214 'mesh.position.copy':1116 'mesh.rotation':99 'miss':1383 'mix':13,866 'mixer':49,385,415,582,584,628,633,730,1232,1249,1267 'mixer.addeventlistener':418,426 'mixer.clipaction':395,444,539,543,608,624,861,875,879,883,955,964 'mixer.update':407,735,1269 'mode':333,485 'model':388,577,580,587,702,1322 'model.getobjectbyproperty':663 'model.glb':574 'morph':10,38,322,771,779,789,794,806,824 'morphtargetinflu':326,846 'motion':23,53,60,1196 'multipl':867,1231 'multiplyscalar':1090,1092,1096,1098,1105 'name':425,433,616,681,802,815,986,1303,1306,1308,1310,1313 'need':33 'negat':467 'new':89,197,207,219,225,235,259,262,269,272,277,292,310,324,337,386,571,585,700,746,844,856,1042,1046,1050,1160,1299 'next':1288 'note':110 'number':215,503 'object':17,36,161,379,741,1253 'object.keys':791 'off-screen':1245 'offset':760 'omega':1060,1065,1091,1097 'opac':221 'optim':1020,1234 'oscil':1172 'output':1355 'overview':140 'page':123 'path':202 'pattern':1034 'paus':120,1274 'perform':1220 'permiss':1376 'physic':1119 'play':18,156,375,493,529,600,612,626,733,863,885 'playback':165,436,446,453,465 'pose':481,952 'posit':199,233,237,339 'procedur':22,52,80,827,1032 'programmat':705 'properti':201 'q1':258 'q1.w':285 'q1.x':282 'q1.y':283 'q1.z':284 'q2':268 'q2.w':289 'q2.x':286 'q2.y':287 'q2.z':288 'quaternion':254,279 'quick':71 'r183':86,118,355,357 'rather':66 'recommend':84,113 'red':299 'redund':1023,1240 'referenceclip':1010 'remov':1022,1239 'render':70 'renderer.render':107,412,647 'renderer.setanimationloop':91 'requestanimationfram':410,645 'requir':409,1374 'reset':1026 'return':1100,1156,1311 'revers':468 'review':1367 'rig':37,1260 'righthand':755 'root':160 'rotat':256 'runact':882 'runaction.play':892 'runaction.seteffectiveweight':900,916,931,946 'runclip':884 'safeti':1377 'scale':234 'scene':65,108,413,648 'scene.add':579,703 'scope':1348 'screen':1247 'second':185 'see':1314 'set':805,813,893 'setfromeul':261,271 'setup':871 'shader':1332,1336 'shape':777 'share':1223 'simpl':79 'simpler':1259 'sine':1179 'singl':217 'skelet':8,562,650 'skeleton':652,657,667,696 'skeleton.bones.find':684,718,752 'skeleton.bones.foreach':671 'skill':1340 'skill-threejs-animation' 'skin':659 'skinnedmesh':662,665 'skinnedmesh.skeleton':668 'smile':327,819,847,858 'smileindex':817,821 'smooth':1035,1038 'smoothdamp':1053,1110 'smoother':368 'smoothtim':1057,1062 'sourc':560 'source-sickn33' 'specif':613,678,1362 'speed':466,905,908,910,920,924,937 'spline':349 'spring':1118,1122,1159,1161 'spring.target':1164 'spring.update':1170 'start':72 'state':454 'static':69 'step':352 'stiff':1124,1129 'still':132 'stop':496,1248,1368 'store':170,627,782 'string':319 'sub':1082 'subclip':993,995,998 'substitut':1358 'success':1380 'system':139,143 'tangent':372 'target':11,39,323,772,780,795,807,825,1041,1055,1083,1112 'target.clone':1101 'task':47,1344 'temp':1085,1104 'temp.clone':1095 'test':1364 'this.damping':1130,1147 'this.position':1132,1143,1153,1157 'this.stiffness':1128,1142 'this.target':1136,1144 'this.velocity':1134,1148,1149,1154 'three':76,78,145,980,982 'three.additiveanimationblendmode':520,967 'three.animationclip':208,857 'three.animationclip.findbyname':619,989 'three.animationmixer':387,586 'three.animationutils.makeclipadditive':973,1005,1007 'three.animationutils.subclip':996 'three.bezierinterpolant':359 'three.booleankeyframetrack':311 'three.clock':115,131 'three.colorkeyframetrack':293 'three.euler':263,273 'three.interpolatediscrete':351 'three.interpolatelinear':344 'three.interpolatesmooth':347 'three.js':4,27,45,64,141,356 'three.looponce':492 'three.looppingpong':498 'three.looprepeat':487 'three.mesh':747 'three.normalanimationblendmode':518 'three.numberkeyframetrack':198,220,226,845 'three.quaternion':260,270 'three.quaternionkeyframetrack':278 'three.skeletonhelper':701 'three.stringkeyframetrack':325 'three.timer':90,111 'three.vector3':1043,1047,1051 'three.vectorkeyframetrack':236,338 'three/examples/jsm/loaders/gltfloader.js':568 'threej':2,1317,1324,1331 'threejs-anim':1 'threejs-fundament':1323 'threejs-load':1316 'threejs-shad':1330 'time':179,184,203,222,228,238,295,340,457,462,712,727 'timer':83,88,119 'timer.getdelta':95 'timer.getelapsed':98 'timer.update':92 'tip':1221 'togeth':869 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'track':196,211,216,232,255,291,309,320,336,366,843,860 'track.setinterpolation':343,346,350 'treat':1353 'true':316,318,510,553,1294 'turn':694 'type':213,664 'updat':398,630,729,1138,1250 'updateanim':907 'use':14,31,1229,1255,1338 'util':976 'valid':1363 'valu':187,191,204,218,341 'vector':231 'veloc':1049,1056,1086,1113 'velocity.sub':1094 'vertex':1333 'visibl':312,1278,1287 'walk':621,991 'walkact':878 'walkaction.play':891 'walkaction.seteffectiveweight':898,914,929,943 'walkclip':618,623,625,880 'wave':1180 'weapon':745,759 'weapon.position.set':762 'weapon.rotation.set':766 'weapongeometri':748 'weaponmateri':749 'weight':471,800,889,895 'window.mixer':632,642 'window.mixer.update':643 'work':133 'x':1064,1071,1073,1074,1076,1077,1078,1198,1210 'y':100,103,200,691,725,1169,1182,1189 'z':1203,1215","prices":[{"id":"01b46197-90f3-499d-8a33-0b486ed26a81","listingId":"a28c8303-b8f3-4888-bfbc-4a8caa324040","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:46:16.047Z"}],"sources":[{"listingId":"a28c8303-b8f3-4888-bfbc-4a8caa324040","source":"github","sourceId":"sickn33/antigravity-awesome-skills/threejs-animation","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/threejs-animation","isPrimary":false,"firstSeenAt":"2026-04-18T21:46:16.047Z","lastSeenAt":"2026-04-22T06:52:01.095Z"}],"details":{"listingId":"a28c8303-b8f3-4888-bfbc-4a8caa324040","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"threejs-animation","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34460,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-22T06:40:00Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"4d1313e4aad1fad2a8e1f7f8a0a17e652f518d8e","skill_md_path":"skills/threejs-animation/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/threejs-animation"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"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."},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/threejs-animation"},"updatedAt":"2026-04-22T06:52:01.095Z"}}