0
# Animation and Ticker
1
2
Animation system with frame-rate independent timing, ticker management, and sprite animation utilities. The ticker system provides the foundation for smooth animations and frame-based updates.
3
4
## Capabilities
5
6
### Ticker System
7
8
Core animation timing system with frame-rate independent updates.
9
10
```typescript { .api }
11
/**
12
* Ticker system for animation timing
13
*/
14
class Ticker extends EventEmitter {
15
constructor();
16
17
/** Is ticker started */
18
started: boolean;
19
20
/** Animation speed multiplier */
21
speed: number;
22
23
/** Delta time since last frame */
24
readonly deltaTime: number;
25
26
/** Delta time in milliseconds */
27
readonly deltaMS: number;
28
29
/** Elapsed time since last frame */
30
readonly elapsedMS: number;
31
32
/** Last frame timestamp */
33
readonly lastTime: number;
34
35
/** Minimum FPS before deltaTime clamping */
36
minFPS: number;
37
38
/** Maximum FPS cap */
39
maxFPS: number;
40
41
/** Target frames per second */
42
readonly FPS: number;
43
44
/**
45
* Add callback to ticker
46
* @param fn - Callback function
47
* @param context - Callback context
48
* @param priority - Execution priority
49
* @returns This ticker
50
*/
51
add(fn: TickerCallback, context?: any, priority?: UPDATE_PRIORITY): this;
52
53
/**
54
* Add callback to run once
55
* @param fn - Callback function
56
* @param context - Callback context
57
* @param priority - Execution priority
58
* @returns This ticker
59
*/
60
addOnce(fn: TickerCallback, context?: any, priority?: UPDATE_PRIORITY): this;
61
62
/**
63
* Remove callback from ticker
64
* @param fn - Callback function
65
* @param context - Callback context
66
* @returns This ticker
67
*/
68
remove(fn: TickerCallback, context?: any): this;
69
70
/**
71
* Start ticker
72
*/
73
start(): void;
74
75
/**
76
* Stop ticker
77
*/
78
stop(): void;
79
80
/**
81
* Destroy ticker
82
*/
83
destroy(): void;
84
85
/**
86
* Update ticker manually
87
* @param currentTime - Current timestamp
88
*/
89
update(currentTime?: number): void;
90
91
/** Shared ticker instance */
92
static readonly shared: Ticker;
93
94
/** System ticker (used by Application) */
95
static readonly system: Ticker;
96
}
97
98
/**
99
* Ticker callback function
100
*/
101
type TickerCallback = (ticker: Ticker) => void;
102
103
/**
104
* Update priorities for ticker callbacks
105
*/
106
enum UPDATE_PRIORITY {
107
INTERACTION = 50,
108
HIGH = 25,
109
NORMAL = 0,
110
LOW = -25,
111
UTILITY = -50
112
}
113
```
114
115
### Ticker Listener
116
117
Individual ticker listener management.
118
119
```typescript { .api }
120
/**
121
* Ticker listener for individual callback management
122
*/
123
class TickerListener {
124
constructor(fn: TickerCallback, context?: any, priority?: number, once?: boolean);
125
126
/** Callback function */
127
fn: TickerCallback;
128
129
/** Callback context */
130
context: any;
131
132
/** Execution priority */
133
priority: number;
134
135
/** Run once flag */
136
once: boolean;
137
138
/** Next listener in chain */
139
next: TickerListener;
140
141
/** Previous listener in chain */
142
previous: TickerListener;
143
144
/** Is destroyed */
145
destroyed: boolean;
146
147
/**
148
* Match function and context
149
* @param fn - Function to match
150
* @param context - Context to match
151
* @returns True if matches
152
*/
153
match(fn: TickerCallback, context?: any): boolean;
154
155
/**
156
* Emit callback
157
* @param ticker - Ticker instance
158
* @returns Next listener
159
*/
160
emit(ticker: Ticker): TickerListener;
161
162
/**
163
* Connect to another listener
164
* @param previous - Previous listener
165
*/
166
connect(previous: TickerListener): void;
167
168
/**
169
* Destroy listener
170
*/
171
destroy(): void;
172
}
173
```
174
175
### Animated Sprite
176
177
Sprite class with built-in texture-based animation support.
178
179
```typescript { .api }
180
/**
181
* Animated sprite with texture frame animation
182
*/
183
class AnimatedSprite extends Sprite {
184
constructor(textures: Texture[] | FrameObject[], autoUpdate?: boolean);
185
186
/** Animation textures/frames */
187
textures: Texture[] | FrameObject[];
188
189
/** Current frame index */
190
currentFrame: number;
191
192
/** Animation speed (frames per second at 60 FPS) */
193
animationSpeed: number;
194
195
/** Loop animation */
196
loop: boolean;
197
198
/** Update anchor with frames */
199
updateAnchor: boolean;
200
201
/** Callback when animation completes */
202
onComplete: () => void;
203
204
/** Callback when frame changes */
205
onFrameChange: (currentFrame: number) => void;
206
207
/** Callback when animation loops */
208
onLoop: () => void;
209
210
/** Total number of frames */
211
readonly totalFrames: number;
212
213
/** Is animation playing */
214
readonly playing: boolean;
215
216
/**
217
* Start playing animation
218
*/
219
play(): void;
220
221
/**
222
* Stop animation
223
*/
224
stop(): void;
225
226
/**
227
* Go to specific frame and play
228
* @param frameNumber - Frame to go to
229
*/
230
gotoAndPlay(frameNumber: number): void;
231
232
/**
233
* Go to specific frame and stop
234
* @param frameNumber - Frame to go to
235
*/
236
gotoAndStop(frameNumber: number): void;
237
238
/**
239
* Update animation
240
* @param deltaTime - Time since last update
241
*/
242
update(deltaTime: number): void;
243
244
/**
245
* Destroy animated sprite
246
* @param options - Destroy options
247
*/
248
destroy(options?: DestroyOptions): void;
249
250
/**
251
* Create from array of image sources
252
* @param images - Array of image sources
253
* @returns New animated sprite
254
*/
255
static fromImages(images: string[]): AnimatedSprite;
256
257
/**
258
* Create from sprite sheet frames
259
* @param sheet - Sprite sheet
260
* @param frameNames - Array of frame names
261
* @returns New animated sprite
262
*/
263
static fromFrames(frameNames: string[]): AnimatedSprite;
264
}
265
266
/**
267
* Animation frame with timing information
268
*/
269
interface FrameObject {
270
/** Frame texture */
271
texture: Texture;
272
273
/** Frame duration in milliseconds */
274
time: number;
275
}
276
```
277
278
### Animation Utilities
279
280
Utility functions and classes for animation management.
281
282
```typescript { .api }
283
/**
284
* Simple tween class for property animation
285
*/
286
class Tween {
287
constructor(target: any);
288
289
/** Target object */
290
target: any;
291
292
/** Is tween playing */
293
playing: boolean;
294
295
/** Tween duration */
296
duration: number;
297
298
/** Tween progress (0-1) */
299
progress: number;
300
301
/** Easing function */
302
easing: (t: number) => number;
303
304
/** Completion callback */
305
onComplete: () => void;
306
307
/** Update callback */
308
onUpdate: (progress: number) => void;
309
310
/**
311
* Animate to target values
312
* @param properties - Target property values
313
* @param duration - Animation duration in milliseconds
314
* @param easing - Easing function
315
* @returns This tween
316
*/
317
to(properties: Record<string, number>, duration: number, easing?: (t: number) => number): this;
318
319
/**
320
* Start tween
321
* @returns This tween
322
*/
323
start(): this;
324
325
/**
326
* Stop tween
327
* @returns This tween
328
*/
329
stop(): this;
330
331
/**
332
* Update tween
333
* @param deltaTime - Time since last update
334
*/
335
update(deltaTime: number): void;
336
337
/**
338
* Set completion callback
339
* @param callback - Completion callback
340
* @returns This tween
341
*/
342
call(callback: () => void): this;
343
}
344
345
/**
346
* Common easing functions
347
*/
348
const Easing = {
349
/** Linear interpolation */
350
linear: (t: number) => t,
351
352
/** Ease in (accelerate) */
353
easeIn: (t: number) => t * t,
354
355
/** Ease out (decelerate) */
356
easeOut: (t: number) => 1 - (1 - t) * (1 - t),
357
358
/** Ease in-out (accelerate then decelerate) */
359
easeInOut: (t: number) => t < 0.5 ? 2 * t * t : 1 - 2 * (1 - t) * (1 - t),
360
361
/** Elastic ease out */
362
elasticOut: (t: number) => Math.sin(-13 * (t + 1) * Math.PI / 2) * Math.pow(2, -10 * t) + 1,
363
364
/** Bounce ease out */
365
bounceOut: (t: number) => {
366
if (t < 1 / 2.75) {
367
return 7.5625 * t * t;
368
} else if (t < 2 / 2.75) {
369
return 7.5625 * (t -= 1.5 / 2.75) * t + 0.75;
370
} else if (t < 2.5 / 2.75) {
371
return 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375;
372
} else {
373
return 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375;
374
}
375
}
376
};
377
378
/**
379
* Animation timeline for sequencing animations
380
*/
381
class Timeline {
382
constructor();
383
384
/** Timeline duration */
385
duration: number;
386
387
/** Timeline progress */
388
progress: number;
389
390
/** Is timeline playing */
391
playing: boolean;
392
393
/** Timeline animations */
394
animations: TimelineAnimation[];
395
396
/**
397
* Add animation to timeline
398
* @param target - Target object
399
* @param properties - Properties to animate
400
* @param duration - Animation duration
401
* @param delay - Animation delay
402
* @returns This timeline
403
*/
404
add(target: any, properties: Record<string, number>, duration: number, delay?: number): this;
405
406
/**
407
* Play timeline
408
* @returns This timeline
409
*/
410
play(): this;
411
412
/**
413
* Stop timeline
414
* @returns This timeline
415
*/
416
stop(): this;
417
418
/**
419
* Update timeline
420
* @param deltaTime - Time since last update
421
*/
422
update(deltaTime: number): void;
423
}
424
425
interface TimelineAnimation {
426
target: any;
427
properties: Record<string, number>;
428
startValues: Record<string, number>;
429
duration: number;
430
delay: number;
431
startTime: number;
432
}
433
```
434
435
### Performance Animation
436
437
High-performance animation utilities for large numbers of objects.
438
439
```typescript { .api }
440
/**
441
* Animation pool for reusing animation objects
442
*/
443
class AnimationPool {
444
constructor();
445
446
/** Available animations */
447
available: Tween[];
448
449
/** Active animations */
450
active: Tween[];
451
452
/**
453
* Get animation from pool
454
* @param target - Target object
455
* @returns Pooled animation
456
*/
457
get(target: any): Tween;
458
459
/**
460
* Return animation to pool
461
* @param animation - Animation to return
462
*/
463
return(animation: Tween): void;
464
465
/**
466
* Update all active animations
467
* @param deltaTime - Time since last update
468
*/
469
update(deltaTime: number): void;
470
471
/**
472
* Clean up pool
473
*/
474
destroy(): void;
475
}
476
477
/**
478
* Batch animation system for many objects
479
*/
480
class BatchAnimator {
481
constructor();
482
483
/** Animation targets */
484
targets: any[];
485
486
/** Animation properties */
487
properties: string[];
488
489
/** Animation duration */
490
duration: number;
491
492
/** Animation progress */
493
progress: number;
494
495
/**
496
* Add target to batch
497
* @param target - Target object
498
* @param startValues - Starting values
499
* @param endValues - Ending values
500
*/
501
addTarget(target: any, startValues: Record<string, number>, endValues: Record<string, number>): void;
502
503
/**
504
* Update all targets
505
* @param deltaTime - Time since last update
506
*/
507
update(deltaTime: number): void;
508
509
/**
510
* Start batch animation
511
*/
512
start(): void;
513
514
/**
515
* Stop batch animation
516
*/
517
stop(): void;
518
}
519
```
520
521
**Usage Examples:**
522
523
```typescript
524
import {
525
Ticker,
526
AnimatedSprite,
527
Tween,
528
Timeline,
529
Easing,
530
Assets,
531
Sprite,
532
Container,
533
UPDATE_PRIORITY
534
} from 'pixi.js';
535
536
// Basic ticker usage
537
const ticker = new Ticker();
538
539
ticker.add((ticker) => {
540
// This runs every frame
541
console.log(`FPS: ${ticker.FPS}, Delta: ${ticker.deltaTime}`);
542
});
543
544
ticker.start();
545
546
// Animation with different priorities
547
ticker.add((ticker) => {
548
// High priority update (runs first)
549
updatePhysics(ticker.deltaTime);
550
}, null, UPDATE_PRIORITY.HIGH);
551
552
ticker.add((ticker) => {
553
// Normal priority update
554
updateVisuals(ticker.deltaTime);
555
}, null, UPDATE_PRIORITY.NORMAL);
556
557
ticker.add((ticker) => {
558
// Low priority update (runs last)
559
updateUI(ticker.deltaTime);
560
}, null, UPDATE_PRIORITY.LOW);
561
562
// Animated sprite creation
563
const walkTextures = [
564
await Assets.load('walk1.png'),
565
await Assets.load('walk2.png'),
566
await Assets.load('walk3.png'),
567
await Assets.load('walk4.png')
568
];
569
570
const animatedSprite = new AnimatedSprite(walkTextures);
571
animatedSprite.animationSpeed = 0.167; // 10 FPS at 60 FPS
572
animatedSprite.loop = true;
573
animatedSprite.play();
574
575
// Animation callbacks
576
animatedSprite.onComplete = () => {
577
console.log('Animation completed');
578
};
579
580
animatedSprite.onFrameChange = (currentFrame) => {
581
console.log(`Frame changed to: ${currentFrame}`);
582
};
583
584
animatedSprite.onLoop = () => {
585
console.log('Animation looped');
586
};
587
588
// Frame objects with custom timing
589
const customFrames = [
590
{ texture: walkTextures[0], time: 100 }, // 100ms
591
{ texture: walkTextures[1], time: 150 }, // 150ms
592
{ texture: walkTextures[2], time: 100 }, // 100ms
593
{ texture: walkTextures[3], time: 200 } // 200ms
594
];
595
596
const customAnimatedSprite = new AnimatedSprite(customFrames);
597
customAnimatedSprite.play();
598
599
// Simple property tweening
600
const sprite = new Sprite(await Assets.load('sprite.png'));
601
602
const tween = new Tween(sprite)
603
.to({ x: 400, y: 300, alpha: 0.5 }, 2000, Easing.easeInOut)
604
.call(() => {
605
console.log('Tween completed');
606
});
607
608
tween.start();
609
610
// Update tween manually or with ticker
611
ticker.add((ticker) => {
612
tween.update(ticker.elapsedMS);
613
});
614
615
// Complex animation timeline
616
const timeline = new Timeline();
617
618
timeline
619
.add(sprite, { x: 200 }, 1000, 0) // Move to x: 200 over 1s, start immediately
620
.add(sprite, { y: 200 }, 1000, 500) // Move to y: 200 over 1s, start after 0.5s
621
.add(sprite, { alpha: 0 }, 500, 1500) // Fade out over 0.5s, start after 1.5s
622
.play();
623
624
ticker.add((ticker) => {
625
timeline.update(ticker.elapsedMS);
626
});
627
628
// Sprite scaling animation with bounce
629
const scaleSprite = new Sprite(texture);
630
const scaleTween = new Tween(scaleSprite.scale)
631
.to({ x: 2, y: 2 }, 1000, Easing.bounceOut);
632
633
scaleTween.start();
634
635
// Rotation animation
636
const rotationSprite = new Sprite(texture);
637
ticker.add((ticker) => {
638
rotationSprite.rotation += 0.01 * ticker.deltaTime;
639
});
640
641
// Color animation using tint
642
const colorSprite = new Sprite(texture);
643
let hue = 0;
644
645
ticker.add((ticker) => {
646
hue += 0.01 * ticker.deltaTime;
647
const color = new Color();
648
color.setHsl(hue % 1, 1, 0.5);
649
colorSprite.tint = color.value;
650
});
651
652
// Performance optimization - pause ticker when not needed
653
document.addEventListener('visibilitychange', () => {
654
if (document.hidden) {
655
ticker.stop();
656
} else {
657
ticker.start();
658
}
659
});
660
661
// Animation state machine
662
class AnimationStateMachine {
663
private currentState: string = 'idle';
664
private animations: Record<string, AnimatedSprite> = {};
665
666
constructor(private sprite: Container) {}
667
668
addAnimation(name: string, animation: AnimatedSprite) {
669
this.animations[name] = animation;
670
this.sprite.addChild(animation);
671
animation.visible = false;
672
}
673
674
setState(newState: string) {
675
if (this.animations[this.currentState]) {
676
this.animations[this.currentState].visible = false;
677
this.animations[this.currentState].stop();
678
}
679
680
this.currentState = newState;
681
682
if (this.animations[newState]) {
683
this.animations[newState].visible = true;
684
this.animations[newState].play();
685
}
686
}
687
}
688
689
// Character with multiple animations
690
const character = new Container();
691
const stateMachine = new AnimationStateMachine(character);
692
693
stateMachine.addAnimation('idle', new AnimatedSprite(idleTextures));
694
stateMachine.addAnimation('walk', new AnimatedSprite(walkTextures));
695
stateMachine.addAnimation('jump', new AnimatedSprite(jumpTextures));
696
697
// Switch animations based on input
698
stateMachine.setState('walk');
699
700
// Particle animation system
701
const particles: Sprite[] = [];
702
const particleCount = 100;
703
704
for (let i = 0; i < particleCount; i++) {
705
const particle = new Sprite(particleTexture);
706
particle.x = Math.random() * 800;
707
particle.y = Math.random() * 600;
708
particle.anchor.set(0.5);
709
particles.push(particle);
710
app.stage.addChild(particle);
711
}
712
713
ticker.add((ticker) => {
714
particles.forEach((particle, index) => {
715
particle.rotation += 0.01 * ticker.deltaTime;
716
particle.y += Math.sin(Date.now() * 0.001 + index) * 0.5;
717
particle.alpha = 0.5 + Math.sin(Date.now() * 0.002 + index) * 0.5;
718
});
719
});
720
721
// Clean up animations
722
window.addEventListener('beforeunload', () => {
723
ticker.destroy();
724
tween.stop();
725
timeline.stop();
726
animatedSprite.destroy();
727
});
728
```