AI студия Владимира Ломтева
УСЛУГИПРОЕКТЫСТАТЬИБАЗА ЗНАНИЙМаркетплейсПолезные сервисы

Оставьте заявку,
чтобы обсудить проект

Напишите ваш вопрос, не забудьте указать телефон. Мы перезвоним и все расскажем.

Контакты

Москва

Работаем по всей России
и миру (онлайн)

+7 (999) 760-24-41

Ежедневно с 9:00 до 21:00

lamooof@gmail.com

По вопросам сотрудничества

TelegramWhatsApp

Есть предложение?

Напишите нам в мессенджеры

© 2025 AI студия Владимира Ломтева

Политика конфиденциальностиСогласие на обработку ПДн|ИНН 623412173261

    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.

    Скиллы для операций#GitHub#cloudai-x/threejs-skills#skills.sh
    Скачивания
    0
    В избранном
    0
    Комментарии
    0
    Просмотры
    2

    Установить скилл

    Добавьте инструмент одной командой или скачайте проверенный архив версии.

    npx skills add cloudai-x/threejs-skills --skill threejs-animation
    Скачать ZIP
    Версия
    1.0.0+b1c623076c66
    Автор
    Владимир Ломтев
    Репозиторий
    cloudai-x/threejs-skills
    GitHub: cloudai-x/threejs-skills

    Как установить

    1. 1Скопируйте команду из блока установки.
    2. 2Запустите её в терминале из каталога проекта.

    Документация

    Three.js Animation

    Quick Start

    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();
    

    Animation System Overview

    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

    AnimationClip

    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]);
    

    KeyframeTrack Types

    // 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"],
    );
    

    Interpolation Modes

    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 function
    

    AnimationMixer

    Plays 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 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);
    
    // 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/Out

    // 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();
    

    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);
    
      // 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);
    }
    

    Skeletal Animation

    Skeleton and Bones

    // 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.find((b) => b.name === "Head");
    if (headBone) headBone.rotation.y = Math.PI / 4; // Turn head
    
    // Skeleton helper
    const helper = new THREE.SkeletonHelper(model);
    scene.add(helper);
    

    Programmatic Bone Animation

    function animate() {
      const time = clock.getElapsedTime();
    
      // Animate bone
      const headBone = skeleton.bones.find((b) => b.name === "Head");
      if (headBone) {
        headBone.rotation.y = Math.sin(time) * 0.3;
      }
    
      // Update mixer if also playing clips
      mixer.update(clock.getDelta());
    }
    

    Bone Attachments

    // Attach object to bone
    const weapon = new THREE.Mesh(weaponGeometry, weaponMaterial);
    const handBone = skeleton.bones.find((b) => b.name === "RightHand");
    if (handBone) handBone.add(weapon);
    
    // Offset attachment
    weapon.position.set(0, 0, 0.5);
    weapon.rotation.set(0, Math.PI / 2, 0);
    

    Morph Targets

    Blend between different mesh shapes.

    // Morph targets are stored in geometry
    const geometry = mesh.geometry;
    console.log("Morph attributes:", Object.keys(geometry.morphAttributes));
    
    // Access morph target influences
    mesh.morphTargetInfluences; // Array of weights
    mesh.morphTargetDictionary; // Name -> index mapping
    
    // Set morph target by index
    mesh.morphTargetInfluences[0] = 0.5;
    
    // Set by name
    const smileIndex = mesh.morphTargetDictionary["smile"];
    mesh.morphTargetInfluences[smileIndex] = 1;
    

    Animating Morph Targets

    // Procedural
    function animate() {
      const t = clock.getElapsedTime();
      mesh.morphTargetInfluences[0] = (Math.sin(t) + 1) / 2;
    }
    
    // With keyframe animation
    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.

    // Setup actions
    const idleAction = mixer.clipAction(idleClip);
    const walkAction = mixer.clipAction(walkClip);
    const runAction = mixer.clipAction(runClip);
    
    // Play all with different weights
    idleAction.play();
    walkAction.play();
    runAction.play();
    
    // Set initial weights
    idleAction.setEffectiveWeight(1);
    walkAction.setEffectiveWeight(0);
    runAction.setEffectiveWeight(0);
    
    // Blend based on speed
    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

    // Base pose
    const baseAction = mixer.clipAction(baseClip);
    baseAction.play();
    
    // Additive layer (e.g., breathing)
    const additiveAction = mixer.clipAction(additiveClip);
    additiveAction.blendMode = THREE.AdditiveAnimationBlendMode;
    additiveAction.play();
    
    // Convert clip to additive
    THREE.AnimationUtils.makeClipAdditive(additiveClip);
    

    Animation Utilities

    import * as THREE from "three";
    
    // Find clip by name
    const clip = THREE.AnimationClip.findByName(clips, "Walk");
    
    // Create subclip
    const subclip = THREE.AnimationUtils.subclip(clip, "subclip", 0, 30, 30);
    
    // Convert to additive
    THREE.AnimationUtils.makeClipAdditive(clip);
    THREE.AnimationUtils.makeClipAdditive(clip, 0, referenceClip);
    
    // Clone clip
    const clone = clip.clone();
    
    // Get clip duration
    clip.duration;
    
    // Optimize clip (remove redundant keyframes)
    clip.optimize();
    
    // Reset clip to first frame
    clip.resetDuration();
    

    Procedural Animation Patterns

    Smooth Damping

    // Smooth follow/lerp
    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();
    
      // Sine wave
      mesh.position.y = Math.sin(t * 2) * 0.5;
    
      // Bouncing
      mesh.position.y = Math.abs(Math.sin(t * 3)) * 2;
    
      // Circular motion
      mesh.position.x = Math.cos(t) * 2;
      mesh.position.z = Math.sin(t) * 2;
    
      // Figure 8
      mesh.position.x = Math.sin(t) * 2;
      mesh.position.z = Math.sin(t * 2) * 1;
    }
    

    Performance Tips

    1. Share clips: Same AnimationClip can be used on multiple mixers
    2. Optimize clips: Call clip.optimize() to remove redundant keyframes
    3. Disable when off-screen: Stop mixer updates for invisible objects
    4. Use LOD for animations: Simpler rigs for distant characters
    5. Limit active mixers: Each mixer.update() has a cost
    // Pause animation when not visible
    mesh.onBeforeRender = () => {
      action.paused = false;
    };
    
    mesh.onAfterRender = () => {
      // Check if will be visible next frame
      if (!isInFrustum(mesh)) {
        action.paused = true;
      }
    };
    
    // Cache clips
    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

    Требования и возможности

    Источник пакета
    https://github.com/cloudai-x/threejs-skills/tree/b1c623076c661fc9b03dac19292e825a5d106823/skills/threejs-animation

    Файлы версии

    ПутьРазмерSHA256
    SKILL.md12557b24dc96c7a854ab9...

    Частые вопросы

    Как установить Threejs Animation?
    Используйте команду npx skills add cloudai-x/threejs-skills --skill threejs-animation или скачайте ZIP-архив.
    Можно ли скачать Threejs Animation бесплатно?
    Да, опубликованную версию можно скачать из маркетплейса бесплатно.

    Похожие инструменты

    Смотреть все
    Story Long Write长篇网文写作。从大纲到正文,辅助长篇网络小说的创作,包括世界观、人物、情节线管理。触发方式:/story-long-write、/写长篇、「帮我开书」「写大纲」「日更」「续写」「继续写」「修改第X章」「回炉」「重写第X章」。Parallel Deep ResearchONLY use when user explicitly says 'deep research', 'exhaustive', 'comprehensive report', or 'thorough investigation'. Slower and more expensive than parallel-web-search. For normal research/lookup requests, use parallel-web-search instead. Supports multi-turn: pass --previous-interaction-id from a prior research or enrichment to continue with context.LangfuseInteract with Langfuse and access its documentation: tracing, monitoring, creating datasets, running experiments, and evaluating AI applications. Use when needing to (1) query or modify Langfuse data, (2) look up Langfuse documentation, concepts, integration guides, a feature or SDK usage, or (3) do any AI engineering task (AI observability, prompt engineering/management, evaluation and evaluator management, experimentation, dataset management, evaluation-driven CI/CD, feedback collection). Invoke it for tasks in this scope even when Langfuse is not configured or explicitly mentioned.
    Комментарии

    Войдите, чтобы оставить комментарий.

    Комментариев пока нет.

    Установить скилл

    Добавьте инструмент одной командой или скачайте проверенный архив версии.

    npx skills add cloudai-x/threejs-skills --skill threejs-animation
    Скачать ZIP
    Версия
    1.0.0+b1c623076c66
    Автор
    Владимир Ломтев
    Репозиторий
    cloudai-x/threejs-skills
    GitHub: cloudai-x/threejs-skills
    Excel Automation>
    Threejs Animation — Скилл для ИИ-агентов | AI Рассвет