AnimationEventManager
by Matt
HTML
<base href="https://rawcdn.githack.com/mrdoob/three.js/r152/examples/" />
<script async src="https://cdn.jsdelivr.net/npm/[email protected]/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/",
"lil-gui": "https://cdn.jsdelivr.net/npm/[email protected]/dist/lil-gui.esm.min.js"
}
}
</script>
CSS
canvas {
position: fixed;
inset: 0;
}
JavaScript
import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
let stats, clock;
let scene, camera, renderer, mixer;
let eventManager;
class AnimationEventManager {
constructor(action) {
this.action = action
this.clip = action.getClip()
this.listeners = []
this._prevTime = -Infinity
}
addTimeListener(time, callback) {
this.listeners.push({
time,
callback
})
}
update() {
const time = this.action.time
const dir = Math.sign(time - this._prevTime)
if (dir === -1) {
this._prevTime -= this.clip.duration
}
for (const listener of this.listeners) {
if ( this._prevTime < listener.time && listener.time <= time) {
listener.callback()
}
}
this._prevTime = time
}
}
init();
animate();
function init() {
scene = new THREE.Scene();
//
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 25, 25, 50 );
camera.lookAt( scene.position );
//
const axesHelper = new THREE.AxesHelper( 10 );
scene.add( axesHelper );
//
const geometry = new THREE.BoxGeometry( 5, 5, 5 );
const material = new THREE.MeshBasicMaterial( { color: 0xffffff, transparent: true } );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// create a keyframe track (i.e. a timed sequence of keyframes) for each animated property
// Note: the keyframe track type should correspond to the type of the property being animated
// POSITION
const positionKF = new THREE.VectorKeyframeTrack( '.position', [ 0, 1, 2 ], [ 0, 0, 0, 30, 0, 0, 0, 0, 0 ] );
// SCALE
const scaleKF = new THREE.VectorKeyframeTrack( '.scale', [ 0, 1, 2 ], [ 1, 1, 1, 2, 2, 2, 1, 1, 1 ] );
// ROTATION
// Rotation should be performed using quaternions, using a THREE.QuaternionKeyframeTrack
// Interpolating Euler angles (.rotation property) can be...