Files
scriptc/tests/fixtures/three/animation.mjs
Chris Tate a07998f667 Expand static three.js workflows and host integration (#621)
* Expand static three.js workflows and host integration

* Preserve JavaScript class state in static three.js workflows

* Preserve inferred JavaScript behavior across static workflows

* Preserve inferred callables and native compatibility boundaries

* Retain annotated JavaScript factory exports and bootstrap-safe call spreads

* Preserve Buffer and child callback identities in static packages

* Clarify JavaScript symbol spread support
2026-10-02 19:56:34 -05:00

94 lines
4.1 KiB
JavaScript

import { AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, BooleanKeyframeTrack, Group, InterpolateDiscrete, LoopOnce, LoopRepeat, NumberKeyframeTrack, Object3D, PropertyBinding, QuaternionKeyframeTrack, StringKeyframeTrack, VectorKeyframeTrack } from "three";
// animation-tracks
{
const number = new NumberKeyframeTrack('.position[x]', [0, 1, 2], [0, 10, 20]);
console.log('number', number.createInterpolant().evaluate(0.5)[0], number.validate());
number.trim(0.5, 2).shift(1).scale(2);
console.log('trim', number.times[0], number.times.length);
const vector = new VectorKeyframeTrack('.position', [0, 1], [0, 0, 0, 2, 4, 6]);
console.log('vector', vector.createInterpolant().evaluate(0.5)[1]);
const quat = new QuaternionKeyframeTrack('.quaternion', [0, 1], [0, 0, 0, 1, 0, 1, 0, 0]);
console.log('quat', quat.createInterpolant().evaluate(0.5)[1].toFixed(4));
const flag = new BooleanKeyframeTrack('.visible', [0, 1], [true, false]);
console.log('bool', flag.createInterpolant().evaluate(0.5)[0]);
const text = new StringKeyframeTrack('.name', [0, 1], ['a', 'b']);
console.log('string', text.createInterpolant().evaluate(1)[0]);
const clip = new AnimationClip('test', -1, [vector]);
console.log('clip', clip.duration, clip.clone().tracks.length);
}
// animation-mixer
{
const root = new Object3D();
const binding = new PropertyBinding(root, '.position');
binding.setValue([2, 4, 6], 0);
const values = [0, 0, 0];
binding.getValue(values, 0);
console.log('whole-vector', values.join(','), root.matrixWorldNeedsUpdate);
binding.unbind();
const mixer = new AnimationMixer(root);
mixer.clipAction(new AnimationClip('vector', 1, [new VectorKeyframeTrack('.position', [0, 1], [0, 0, 0, 2, 4, 6])])).play();
mixer.update(0.5);
console.log('vector-playback', root.position.x, root.position.y, root.position.z);
mixer.stopAllAction();
mixer.uncacheRoot(root);
}
{
const root = new Object3D(), mixer = new AnimationMixer(root), clip = new AnimationClip('move', 1, [new NumberKeyframeTrack('.position[x]', [0, 1], [0, 10])]);
const action = mixer.clipAction(clip);
action.play();
mixer.update(0.25);
console.log('quarter', root.position.x, action.isRunning());
mixer.update(0.5);
console.log('threequarters', root.position.x);
action.setLoop(LoopOnce, 1);
action.clampWhenFinished = true;
mixer.update(1);
console.log('end', root.position.x, action.paused);
mixer.stopAllAction();
mixer.uncacheRoot(root);
console.log('uncached', mixer.existingAction(clip) === null);
}
// animation-crossfade
{
const root = new Object3D(), mixer = new AnimationMixer(root);
const a = mixer.clipAction(new AnimationClip('a', 2, [new NumberKeyframeTrack('.position[x]', [0, 2], [0, 10])]));
const b = mixer.clipAction(new AnimationClip('b', 2, [new NumberKeyframeTrack('.position[x]', [0, 2], [10, 20])]));
a.play();
mixer.update(0.25);
b.reset().play().crossFadeFrom(a, 0.5, false);
mixer.update(0.25);
console.log('blend', root.position.x.toFixed(4), a.getEffectiveWeight().toFixed(3), b.getEffectiveWeight().toFixed(3));
mixer.update(0.25);
console.log('complete', a.getEffectiveWeight(), b.getEffectiveWeight());
}
// property-binding
{
const root = new Group(), child = new Object3D();
child.name = 'child';
root.add(child);
const binding = new PropertyBinding(root, 'child.position[x]');
binding.bind();
const values = [7];
binding.setValue(values, 0);
const result = [0];
binding.getValue(result, 0);
console.log('binding', child.position.x, result[0]);
binding.unbind();
const group = new AnimationObjectGroup(root, child);
console.log('group', group.stats.objects.total, group.stats.objects.inUse);
group.remove(child);
console.log('removed', group.stats.objects.inUse);
}
// loader-animation
{
const clip = new AnimationClip('move', 1, [new NumberKeyframeTrack('.position[x]', [0, 1], [0, 1])]);
const result = new AnimationLoader().parse([clip.toJSON()]);
console.log('animation', result.length, result[0].name, result[0].tracks[0].values[1]);
}