Animation in Three.js Simple Example

In Three.js, animation refers to creating and controlling the movement and changes of objects in a scene. A model refers to a 3D object loaded through Three.js, which can be a geometry, mesh, or complex model file (such as .obj or .gltf). Animations can exist within the model or be defined separately.

Edit keyframes:
Keyframe animation is completed through two APIs: KeyframeTrack and AnimationClip. In actual development, if you need to create a frame animation of a complex three-dimensional model, such as a person walking, running, etc., generally the art is done through software such as 3dmax and blender. Edited well, no programmer is required to implement it in code.

Play keyframes
Play existing frame animation data by operating the two APIs of AnimationAction and mixer AnimationMixer.

The parameter of the mixer THREE.AnimationMixer() is the parent object group of the two mesh models written in the case code. In actual development, the parameter Group can also be the model object returned by loading the external model.

When playing keyframe animation, pay attention to executing mixer.update (rendering interval time) in the rendering function render() to tell the frame animation system Threejs the time interval between two renderings. The time interval can be obtained through a clock class Clock provided by Threejs.

Summarize
1. You need a parent group, add grid objects to it, and name the grid objects.
2. Edit keyframes
(1) Use two APIs: KeyframeTrack and AnimationClip
(2) new THREE.KeyframeTrack can set position, color, scaling and other attributes in key frames, using time points and changing values.
(3) Set playback time duration
(4) Create a clip object, name it, duration, and keyframes.
3. Play keyframes
Operate the two APIs of AnimationAction and mixer AnimationMixer to play
(1) new THREE.AnimationMixer(group); Play the frame animation of all sub-objects in the group
(2)clip is used as a parameter and an operation object AnimationAction is returned through the mixer clipAction method.
(3) Set the playback mode by operating Action, adjust the playback speed, and whether to loop
(4)Start playing
4. Rendering
(1) Create a clock object
(2) Perform the rendering operation, request rendering again, render the next frame, and update the mixer related time.

Effect

Source code:


<template>
  <div ref="container"></div>
</template>


<script setup lang="ts">
//Import resources
import { ref, onMounted, onUnmounted } from 'vue';
import * as THREE from 'three';

//Introduce loader
import {RGBELoader} from "three/examples/jsm/loaders/RGBELoader";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";

const container = ref(null);
let scene = undefined;
let camera = undefined;
let renderer = undefined;
let controls = undefined; //controller
const model = ref(null);
const mixer = ref(null);
const clock = ref(null);

//Execute after loading is complete
onMounted(() => {

    //Renderer
    renderer = new THREE.WebGLRenderer({
      antialias: true,
    // alpha: true
    });
    renderer.setSize( window.innerWidth, window.innerHeight );
    container.value.appendChild(renderer.domElement);

    //Scenes
    scene = new THREE.Scene();
    scene.background = new THREE.Color( 0xf0f0f0 );

    //camera
    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.set(15,15,15);
    // camera.lookAt(new THREE.Vector3(0,0,0));
    camera.lookAt( scene.position );
    scene.add(camera);

    //light
    var light = new THREE.DirectionalLight( 0xffffff, 1 );
    light.position.set(3, 1, 1).normalize();//The vector attribute vector is converted into a unit vector, the direction is set to be the same as the original vector, and the length is 1
    light.intensity=1.5;//Intensity
    scene.add(light);


    //animated mesh model
    var material1 = new THREE.MeshLambertMaterial({
      color:0x0000ff
    });
    var geometry1 = new THREE.BoxGeometry(5,2,3);
    var mesh1 = new THREE.Mesh(geometry1, material1);
    mesh1.name="Box";
    mesh1.position.set(0,2,0);

    var material2 = new THREE.MeshLambertMaterial({
      color:0x00ff00
    });
    var geometry2 = new THREE.SphereGeometry(1, 50, 50);
    var mesh2 = new THREE.Mesh(geometry2, material2);
    mesh2.name="Sphere";
    mesh2.position.set(0,5,0);

    var group = new THREE.Group();
    group.add(mesh1,mesh2);
    scene.add(group);

    controls = new OrbitControls(camera, renderer.domElement);
    controls.update();


    //Edit the frame animation data of group sub-object mesh model mesh1 and mesh2
    //Create keyframe data named Box object
    var times = [0, 10]; //keyframe event array, discrete time point sequence
    var values = [0,0,0,10,0,0]//Array consisting of values corresponding to time points
    //Create a position keyframe object: time 0 corresponds to position 0,0,0, time 10 corresponds to position 150,0,0
    var posTrack = new THREE.KeyframeTrack('Box.position', times, values);
    //Create Yan'e keyframe object: 10 time corresponds to color 1, 0, 0 and 20 time corresponds to color 0, 0, 1
    var colorKF = new THREE.KeyframeTrack('Box.material.color', [10, 20], [1, 0, 0, 0, 0, 1]);
    //Create keyframe data named Sphere object, from 0-20 time period, scale size is scaled 3 times
    var scaleTrack = new THREE.KeyframeTrack('Sphere.scale', [0, 20], [1, 1, 1, 3, 3, 3]);

    //duration determines the default playback time, generally taking the maximum event of all frames of animation
    //duration is too small, and the frame animation data cannot be played completely. If it is too large, the frame animation will continue to play empty after playing.

    var duration = 20;

    //Multiple frame animation seat elements create a clip object, named "default", duration 20
    var clip = new THREE.AnimationClip("default", duration, [posTrack, colorKF, scaleTrack]);

    // Play the edited keyframes

    //Group is used as a parameter of the mixer, which can play the frame animation of all sub-objects in the group.
    var mixer = new THREE.AnimationMixer(group);
    //Clip as a parameter, return an operation object AnimationAction through the mixer clipAction method
    var AnimationAction = mixer.clipAction(clip);
    //Set the playback mode by operating Action
    AnimationAction.timeScale = 20; //Default 1, you can adjust the playback speed
    // AnimationAction.loop = THREE.LoopOnce; //Do not loop
    AnimationAction.play();//Start playing

    //Create a clock object Clock
    var clock = new THREE.Clock();

    // Render scene
    const animate = () => {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);

      //clock.getDelta() method obtains the time interval between two frames
      //Update mixer related time
      mixer.update(clock.getDelta());
    };

  animate();

})
</script>



<style scoped>

</style>