Skip to main content الرئيسية المنشئون beko2210 firstbrain threejs-animation
threejs-animation Three.js animation - keyframe animation, skeletal animation, morph targets, animation mixing. Use when animating objects, playing GLTF animations, creating procedural motion, or blending animations.
الانتقال إلى التثبيت سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/BEKO2210/Firstbrain --skill threejs-animationيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... المهن ذات الصلة SOC
استنادا إلى تصنيف SOC المهني
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. type skill created 2026-02-27T00:00:00.000Z domain design-creative category 3d-animation risk unknown source community tags ["skill","design-creative","3d-animation","threejs","animation"]
Three.js Animation
When to Use
You need to animate objects, rigs, morph targets, or imported GLTF animations in Three.js.
The task involves mixers, clips, keyframes, procedural motion, or animation blending.
You are building motion behavior in a Three.js scene rather than just static rendering.
Quick Start
import * as THREE from "three" ;
const timer = new THREE .Timer ();
renderer.setAnimationLoop (() => {
timer.update ();
const delta = timer.getDelta ();
const elapsed = timer.getElapsed ();
mesh.rotation .y += delta;
mesh.position .y = Math .sin (elapsed) * 0.5 ;
renderer.render (scene, camera);
});
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.
Animation System Overview
Three.js animation system has three main components:
AnimationClip - Container for keyframe data
AnimationMixer - Plays animations on a root object
AnimationAction - Controls playback of a clip
AnimationClip
Stores keyframe animation data.
const times = [ , , ];
values = [ , , ];
track = . (
,
times,
values,
);
clip = . ( , , [track]);
0
1
2
const
0
1
0
const
new
THREE
NumberKeyframeTrack
".position[y]"
const
new
THREE
AnimationClip
"bounce"
2
KeyframeTrack Types
new THREE .NumberKeyframeTrack (".opacity" , times, [1 , 0 ]);
new THREE .NumberKeyframeTrack (".material.opacity" , times, [1 , 0 ]);
new THREE .VectorKeyframeTrack (".position" , times, [
0 ,
0 ,
0 ,
1 ,
2 ,
0 ,
0 ,
0 ,
0 ,
]);
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 ],
);
new THREE .ColorKeyframeTrack (".material.color" , times, [
1 ,
0 ,
0 ,
0 ,
1 ,
0 ,
0 ,
0 ,
1 ,
]);
new THREE .BooleanKeyframeTrack (".visible" , [0 , 0.5 , 1 ], [true , false , true ]);
new THREE .StringKeyframeTrack (
".morphTargetInfluences[smile]" ,
[0 , 1 ],
["0" , "1" ],
);
Interpolation Modes const track = new THREE .VectorKeyframeTrack (".position" , times, values);
track.setInterpolation (THREE .InterpolateLinear );
track.setInterpolation (THREE .InterpolateSmooth );
track.setInterpolation (THREE .InterpolateDiscrete );
BezierInterpolant (r183) Three.js r183 adds THREE.BezierInterpolant for bezier curve interpolation in keyframe tracks, enabling smoother animation curves with tangent control.
AnimationMixer Plays animations on an object and its descendants.
const mixer = new THREE .AnimationMixer (model);
const action = mixer.clipAction (clip);
action.play ();
function animate ( ) {
const delta = clock.getDelta ();
mixer.update (delta);
requestAnimationFrame (animate);
renderer.render (scene, camera);
}
Mixer Events mixer.addEventListener ("finished" , (e ) => {
console .log ("Animation finished:" , e.action .getClip ().name );
});
mixer.addEventListener ("loop" , (e ) => {
console .log ("Animation looped:" , e.action .getClip ().name );
});
AnimationAction Controls playback of an animation clip.
const action = mixer.clipAction (clip);
action.play ();
action.stop ();
action.reset ();
action.halt (fadeOutDuration);
action.isRunning ();
action.isScheduled ();
action.time = 0.5 ;
action.timeScale = 1 ;
action.paused = false ;
action.weight = 1 ;
action.setEffectiveWeight (1 );
action.loop = THREE .LoopRepeat ;
action.loop = THREE .LoopOnce ;
action.loop = THREE .LoopPingPong ;
action.repetitions = 3 ;
action.clampWhenFinished = true ;
action.blendMode = THREE .NormalAnimationBlendMode ;
action.blendMode = THREE .AdditiveAnimationBlendMode ;
Fade In/Out
action.reset ().fadeIn (0.5 ).play ();
action.fadeOut (0.5 );
const action1 = mixer.clipAction (clip1);
const action2 = mixer.clipAction (clip2);
action1.play ();
action1.crossFadeTo (action2, 0.5 , true );
action2.play ();
Loading GLTF Animations 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);
const mixer = new THREE .AnimationMixer (model);
const clips = gltf.animations ;
console .log (
"Available animations:" ,
clips.map ((c ) => c.name ),
);
if (clips.length > 0 ) {
const action = mixer.clipAction (clips[0 ]);
action.play ();
}
const walkClip = THREE .AnimationClip .findByName (clips, "Walk" );
if (walkClip) {
mixer.clipAction (walkClip).play ();
}
window .mixer = mixer;
});
function animate ( ) {
const delta = clock.getDelta ();
if (window .mixer ) window .mixer .update (delta);
requestAnimationFrame (animate);
renderer.render (scene, camera);
}
Skeletal Animation
Skeleton and Bones
const skinnedMesh = model.getObjectByProperty ("type" , "SkinnedMesh" );
const skeleton = skinnedMesh.skeleton ;
skeleton.bones .forEach ((bone ) => {
console .log (bone.name , bone.position , bone.rotation );
});
const headBone = skeleton.bones .find ((b ) => b.name === "Head" );
if (headBone) headBone.rotation .y = Math .PI / 4 ;
const helper = new THREE .SkeletonHelper (model);
scene.add (helper);
Programmatic Bone Animation function animate ( ) {
const time = clock.getElapsedTime ();
const headBone = skeleton.bones .find ((b ) => b.name === "Head" );
if (headBone) {
headBone.rotation .y = Math .sin (time) * 0.3 ;
}
mixer.update (clock.getDelta ());
}
Bone Attachments
const weapon = new THREE .Mesh (weaponGeometry, weaponMaterial);
const handBone = skeleton.bones .find ((b ) => b.name === "RightHand" );
if (handBone) handBone.add (weapon);
weapon.position .set (0 , 0 , 0.5 );
weapon.rotation .set (0 , Math .PI / 2 , 0 );
Morph Targets Blend between different mesh shapes.
const geometry = mesh.geometry ;
console .log ("Morph attributes:" , Object .keys (geometry.morphAttributes ));
mesh.morphTargetInfluences ;
mesh.morphTargetDictionary ;
mesh.morphTargetInfluences [0 ] = 0.5 ;
const smileIndex = mesh.morphTargetDictionary ["smile" ];
mesh.morphTargetInfluences [smileIndex] = 1 ;
Animating Morph Targets
function animate ( ) {
const t = clock.getElapsedTime ();
mesh.morphTargetInfluences [0 ] = (Math .sin (t) + 1 ) / 2 ;
}
const track = new THREE .NumberKeyframeTrack (
".morphTargetInfluences[smile]" ,
[0 , 0.5 , 1 ],
[0 , 1 , 0 ],
);
const clip = new THREE .AnimationClip ("smile" , 1 , [track]);
mixer.clipAction (clip).play ();
Animation Blending Mix multiple animations together.
const idleAction = mixer.clipAction (idleClip);
const walkAction = mixer.clipAction (walkClip);
const runAction = mixer.clipAction (runClip);
idleAction.play ();
walkAction.play ();
runAction.play ();
idleAction.setEffectiveWeight (1 );
walkAction.setEffectiveWeight (0 );
runAction.setEffectiveWeight (0 );
function updateAnimations (speed ) {
if (speed < 0.1 ) {
idleAction.setEffectiveWeight (1 );
walkAction.setEffectiveWeight (0 );
runAction.setEffectiveWeight (0 );
} else if (speed < 5 ) {
const t = speed / 5 ;
idleAction.setEffectiveWeight (1 - t);
walkAction.setEffectiveWeight (t);
runAction.setEffectiveWeight (0 );
} else {
const t = Math .min ((speed - 5 ) / 5 , 1 );
idleAction.setEffectiveWeight (0 );
walkAction.setEffectiveWeight (1 - t);
runAction.setEffectiveWeight (t);
}
}
Additive Blending
const baseAction = mixer.clipAction (baseClip);
baseAction.play ();
const additiveAction = mixer.clipAction (additiveClip);
additiveAction.blendMode = THREE .AdditiveAnimationBlendMode ;
additiveAction.play ();
THREE .AnimationUtils .makeClipAdditive (additiveClip);
Animation Utilities import * as THREE from "three" ;
const clip = THREE .AnimationClip .findByName (clips, "Walk" );
const subclip = THREE .AnimationUtils .subclip (clip, "subclip" , 0 , 30 , 30 );
THREE .AnimationUtils .makeClipAdditive (clip);
THREE .AnimationUtils .makeClipAdditive (clip, 0 , referenceClip);
const clone = clip.clone ();
clip.duration ;
clip.optimize ();
clip.resetDuration ();
Procedural Animation Patterns
Smooth Damping
const target = new THREE .Vector3 ();
const current = new THREE .Vector3 ();
const velocity = new THREE .Vector3 ();
function smoothDamp (current, target, velocity, smoothTime, deltaTime ) {
const omega = 2 / smoothTime;
const x = omega * deltaTime;
const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);
const change = current.clone ().sub (target);
const temp = velocity
.clone ()
.add (change.clone ().multiplyScalar (omega))
.multiplyScalar (deltaTime);
velocity.sub (temp.clone ().multiplyScalar (omega)).multiplyScalar (exp);
return target.clone ().add (change.add (temp).multiplyScalar (exp));
}
function animate ( ) {
current.copy (smoothDamp (current, target, velocity, 0.3 , delta));
mesh.position .copy (current);
}
Spring Physics class Spring {
constructor (stiffness = 100 , damping = 10 ) {
this .stiffness = stiffness;
this .damping = damping;
this .position = 0 ;
this .velocity = 0 ;
this .target = 0 ;
}
update (dt ) {
const force = -this .stiffness * (this .position - this .target );
const dampingForce = -this .damping * this .velocity ;
this .velocity += (force + dampingForce) * dt;
this .position += this .velocity * dt;
return this .position ;
}
}
const spring = new Spring (100 , 10 );
spring.target = 1 ;
function animate ( ) {
mesh.position .y = spring.update (delta);
}
Oscillation function animate ( ) {
const t = clock.getElapsedTime ();
mesh.position .y = Math .sin (t * 2 ) * 0.5 ;
mesh.position .y = Math .abs (Math .sin (t * 3 )) * 2 ;
mesh.position .x = Math .cos (t) * 2 ;
mesh.position .z = Math .sin (t) * 2 ;
mesh.position .x = Math .sin (t) * 2 ;
mesh.position .z = Math .sin (t * 2 ) * 1 ;
}
Performance Tips
Share clips : Same AnimationClip can be used on multiple mixers
Optimize clips : Call clip.optimize() to remove redundant keyframes
Disable when off-screen : Stop mixer updates for invisible objects
Use LOD for animations : Simpler rigs for distant characters
Limit active mixers : Each mixer.update() has a cost
mesh.onBeforeRender = () => {
action.paused = false ;
};
mesh.onAfterRender = () => {
if (!isInFrustum (mesh)) {
action.paused = true ;
}
};
const clipCache = new Map ();
function getClip (name ) {
if (!clipCache.has (name)) {
clipCache.set (name, loadClip (name));
}
return clipCache.get (name);
}
See Also
threejs-loaders - Loading animated GLTF models
threejs-fundamentals - Clock and animation loop
threejs-shaders - Vertex animation in shaders
Connections
Domain: [[Design & Kreativitaet]]
Kategorie: [[3D & Animation]]
Navigation: [[Skills Uebersicht]], [[Home]]