Skip to content

AnimationService

Manages keyframe animations and engine-based tweens for Three.js objects. The service owns the SDK-facing API; the lower-level tween/timeline runtime lives in AnimationEngine.

Access

Registered under the name "animation". No service dependencies.

AnimationService is not exported from the SDK entry point. Reach it by its registered name and use the class only as a type.

ts
import type { AnimationService } from "@optellix/xviewr-sdk";

await viewer.ready();
const anim = viewer.getService<AnimationService>("animation");

Public API

Lifecycle

  • init(context: ServiceContext): Promise<void>
  • destroy(): Promise<void>
  • getStatus(): ServiceStatus

Keyframe Animations

  • createAnimation(config: AnimationConfig): Animation - creates and registers a keyframe animation. Does not start it.
  • playAnimation(id: string): boolean - starts playback from the current time.
  • stopAnimation(id: string): boolean - stops and resets current time to 0.
  • pauseAnimation(id: string): boolean - pauses at the current time.
  • resumeAnimation(id: string): boolean - resumes a paused animation. Returns false if already completed.
  • setAnimationTime(id: string, time: number): boolean - seeks to a specific time and applies the interpolated value immediately.
  • getAnimation(id: string): Animation | null
  • removeAnimation(id: string): boolean - stops and removes the animation.

Timelines

  • createTimeline(config: TimelineConfig): Timeline
  • addTrackToTimeline(timelineId: string, track: Track): boolean
  • playTimeline(id: string): boolean
  • stopTimeline(id: string): boolean

Global Controls

  • pauseAll(): void - pauses the service clock; no keyframe animations advance until resumeAll.
  • resumeAll(): void
  • stopAllAnimations(): void - stops keyframe animations and engine tweens/timelines.
  • setTimeScale(scale: number): void - multiplies delta time for keyframe animations. 0 freezes, 2 doubles speed.
  • update(): void - advances active keyframe animations by one frame. The engine tween layer runs on its own RAF ticker.

Engine Helpers

  • animateWithEngine(target: any, properties: Record<string, any>, duration: number, options?: AnimationTweenVars): AnimationTween
  • animateVector3(target: any, property: string, toValue: THREE.Vector3, duration?: number, options?: AnimationTweenVars): AnimationTween - animates a Vector3 property.
  • animateProperties(target: any, properties: Record<string, any>, duration?: number, options?: AnimationTweenVars): AnimationTween - animates numeric properties, including dot-paths like "rotation.x".
  • createEngineTimeline(id: string, options?: AnimationTimelineVars): AnimationTimeline - creates and registers a named engine timeline.
  • stopEngineTimeline(id: string): boolean
  • stopAllEngineAnimations(): void

Transform Helpers

  • animateProperty(target: any, property: string, from: any, to: any, duration: number, options?: Partial<AnimationConfig>): Animation
  • animateTransform(object: THREE.Object3D, transforms: TransformKeyframe[], duration: number, options?: Partial<AnimationConfig>): Animation[]
  • animateTransformWithEngine(objects: THREE.Object3D[], startTransforms, endTransforms, duration: number, options?: AnimationTimelineVars): AnimationTimeline

Camera State Helpers

  • getOrbitState(controls: any, camera: THREE.Camera): CameraTransform
  • applyOrbitState(controls: any, camera: THREE.Camera, state: CameraTransform): void

Engine Runtime

AnimationEngine provides AnimationTween and AnimationTimeline. Tweens support:

  • kill(), pause(), play(), restart(), progress(), and isActive()
  • eventCallback("onStart" | "onUpdate" | "onComplete" | "onInterrupt", callback)
  • linear, none, and power1 through power4 easing modes with .in, .out, and .inOut

Types

ts
interface AnimationConfig {
  id?: string;
  name?: string;
  target: any;
  property: string;
  keyframes: Keyframe[];
  duration: number;
  loop?: boolean;
  easing?: EasingFunction;
  onUpdate?: (animation: Animation) => void;
  onComplete?: (animation: Animation) => void;
}

interface Keyframe {
  time: number;
  value: any;
}

interface TimelineConfig {
  id?: string;
  name?: string;
  loop?: boolean;
  onUpdate?: (timeline: Timeline) => void;
  onComplete?: (timeline: Timeline) => void;
}

interface Track {
  id?: string;
  name: string;
  startTime: number;
  duration: number;
  animation: Animation;
}

interface TransformKeyframe {
  time: number;
  position?: THREE.Vector3;
  rotation?: THREE.Euler;
  scale?: THREE.Vector3;
}

interface CameraTransform {
  target: { x: number; y: number; z: number };
  theta: number;
  phi: number;
  radius: number;
  zoom: number;
  fov?: number;
}

type EasingFunction = "linear" | "easeIn" | "easeOut" | "easeInOut";

Keyframe interpolation supports number, THREE.Vector3, THREE.Euler, and THREE.Color. Other types fall back to the start value.

Events

EventPayload
animation:created{ animation: Animation }
animation:started{ animation: Animation }
animation:stopped{ animation: Animation }
animation:paused{ animation: Animation }
animation:resumed{ animation: Animation }
animation:completed{ animation: Animation }
animation:removed{ id: string }
animation:all-pausednull
animation:all-resumednull
animation:timescale-changed{ scale: number }
animation:tween-started{ target: any; properties: any }
animation:tween-completed{ target: any; properties: any }
animation:timeline-engine-started{ id: string }
animation:timeline-engine-completed{ id: string }
timeline:created{ timeline: Timeline }
timeline:started{ timeline: Timeline }
timeline:stopped{ timeline: Timeline }
timeline:completed{ timeline: Timeline }
timeline:track-added{ timeline: Timeline; track: Track }

Example

ts
const anim = viewer.getService<AnimationService>("animation");
if (!anim) return;

const mesh = viewer.getService("mesh")?.getById("part-001");
const fly = anim.createAnimation({
  target: mesh,
  property: "position.y",
  keyframes: [
    { time: 0, value: 0 },
    { time: 1.5, value: 10 },
    { time: 3, value: 0 },
  ],
  duration: 3,
  loop: true,
  easing: "easeInOut",
});
anim.playAnimation(fly.id);

const camera = viewer.getService("camera");
anim.animateVector3(
  camera?.getCamera(),
  "position",
  new THREE.Vector3(50, 30, 80),
  2.5,
  { ease: "power2.out" }
);

anim.setTimeScale(0.5);

XViewr SDK and xConvert CLI documentation.