@ue-too/animate 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -113
- package/animatable-attribute.d.ts +1 -1
- package/composite-animation.d.ts +1 -1
- package/index.d.ts +2 -2
- package/index.js.map +3 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,11 +24,13 @@ Keyframe-based animation library for TypeScript canvas applications.
|
|
|
24
24
|
## Installation
|
|
25
25
|
|
|
26
26
|
Using Bun:
|
|
27
|
+
|
|
27
28
|
```bash
|
|
28
29
|
bun add @ue-too/animate
|
|
29
30
|
```
|
|
30
31
|
|
|
31
32
|
Using npm:
|
|
33
|
+
|
|
32
34
|
```bash
|
|
33
35
|
npm install @ue-too/animate
|
|
34
36
|
```
|
|
@@ -44,13 +46,15 @@ let opacity = 0;
|
|
|
44
46
|
|
|
45
47
|
// Create fade-in animation
|
|
46
48
|
const fadeIn = new Animation(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
[
|
|
50
|
+
{ percentage: 0, value: 0 }, // Start at 0% with value 0
|
|
51
|
+
{ percentage: 1, value: 1 }, // End at 100% with value 1
|
|
52
|
+
],
|
|
53
|
+
value => {
|
|
54
|
+
opacity = value;
|
|
55
|
+
}, // Apply function updates the value
|
|
56
|
+
numberHelperFunctions, // Number interpolation helper
|
|
57
|
+
1000 // Duration in milliseconds
|
|
54
58
|
);
|
|
55
59
|
|
|
56
60
|
// Start the animation
|
|
@@ -58,9 +62,9 @@ fadeIn.start();
|
|
|
58
62
|
|
|
59
63
|
// In your animation loop (e.g., requestAnimationFrame)
|
|
60
64
|
function gameLoop(deltaTime: number) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
fadeIn.animate(deltaTime); // Update animation with elapsed time
|
|
66
|
+
console.log('Opacity:', opacity);
|
|
67
|
+
requestAnimationFrame(() => gameLoop(16)); // ~60 FPS
|
|
64
68
|
}
|
|
65
69
|
```
|
|
66
70
|
|
|
@@ -72,18 +76,19 @@ Keyframes define values at specific points in an animation's progress:
|
|
|
72
76
|
|
|
73
77
|
```typescript
|
|
74
78
|
type Keyframe<T> = {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
percentage: number; // 0.0 (start) to 1.0 (end)
|
|
80
|
+
value: T; // Value at this point
|
|
81
|
+
easingFn?: (t: number) => number; // Optional easing for this segment
|
|
78
82
|
};
|
|
79
83
|
```
|
|
80
84
|
|
|
81
85
|
**Example with easing:**
|
|
86
|
+
|
|
82
87
|
```typescript
|
|
83
88
|
const keyframes = [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
{ percentage: 0, value: 0 },
|
|
90
|
+
{ percentage: 0.5, value: 100, easingFn: t => t * t }, // Ease-in quadratic
|
|
91
|
+
{ percentage: 1, value: 200 },
|
|
87
92
|
];
|
|
88
93
|
```
|
|
89
94
|
|
|
@@ -93,7 +98,7 @@ Helpers provide type-specific interpolation logic:
|
|
|
93
98
|
|
|
94
99
|
```typescript
|
|
95
100
|
interface AnimatableAttributeHelper<T> {
|
|
96
|
-
|
|
101
|
+
lerp(ratio: number, start: Keyframe<T>, end: Keyframe<T>): T;
|
|
97
102
|
}
|
|
98
103
|
```
|
|
99
104
|
|
|
@@ -113,6 +118,7 @@ const animation = new Animation<T>(
|
|
|
113
118
|
```
|
|
114
119
|
|
|
115
120
|
**Methods:**
|
|
121
|
+
|
|
116
122
|
- `start()`: Start the animation
|
|
117
123
|
- `stop()`: Stop and reset the animation
|
|
118
124
|
- `pause()`: Pause at current position
|
|
@@ -124,6 +130,7 @@ const animation = new Animation<T>(
|
|
|
124
130
|
- `tearDown()`: Clean up animation state
|
|
125
131
|
|
|
126
132
|
**Properties:**
|
|
133
|
+
|
|
127
134
|
- `loops: boolean`: Whether animation loops
|
|
128
135
|
- `maxLoopCount?: number`: Maximum number of loops (undefined = infinite)
|
|
129
136
|
- `duration: number`: Animation duration in milliseconds
|
|
@@ -146,6 +153,7 @@ const composite = new CompositeAnimation(
|
|
|
146
153
|
```
|
|
147
154
|
|
|
148
155
|
**Methods:**
|
|
156
|
+
|
|
149
157
|
- `addAnimation(name: string, animator: Animator, startTime: number)`: Add animation at specific time
|
|
150
158
|
- `addAnimationAfter(name: string, animator: Animator, after: string)`: Add after another animation
|
|
151
159
|
- `addAnimationBefore(name: string, animator: Animator, before: string)`: Add before another animation
|
|
@@ -164,13 +172,15 @@ import { Animation, numberHelperFunctions } from '@ue-too/animate';
|
|
|
164
172
|
|
|
165
173
|
let scale = 1;
|
|
166
174
|
const scaleAnimation = new Animation(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
175
|
+
[
|
|
176
|
+
{ percentage: 0, value: 1 },
|
|
177
|
+
{ percentage: 1, value: 2 },
|
|
178
|
+
],
|
|
179
|
+
value => {
|
|
180
|
+
scale = value;
|
|
181
|
+
},
|
|
182
|
+
numberHelperFunctions,
|
|
183
|
+
500
|
|
174
184
|
);
|
|
175
185
|
```
|
|
176
186
|
|
|
@@ -185,13 +195,15 @@ import { Point } from '@ue-too/math';
|
|
|
185
195
|
let position: Point = { x: 0, y: 0 };
|
|
186
196
|
|
|
187
197
|
const moveAnimation = new Animation(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
198
|
+
[
|
|
199
|
+
{ percentage: 0, value: { x: 0, y: 0 } },
|
|
200
|
+
{ percentage: 1, value: { x: 100, y: 100 } },
|
|
201
|
+
],
|
|
202
|
+
value => {
|
|
203
|
+
position = value;
|
|
204
|
+
},
|
|
205
|
+
pointHelperFunctions,
|
|
206
|
+
1000
|
|
195
207
|
);
|
|
196
208
|
```
|
|
197
209
|
|
|
@@ -200,19 +212,21 @@ const moveAnimation = new Animation(
|
|
|
200
212
|
Interpolate RGB colors:
|
|
201
213
|
|
|
202
214
|
```typescript
|
|
203
|
-
import { Animation,
|
|
215
|
+
import { Animation, RGB, rgbHelperFunctions } from '@ue-too/animate';
|
|
204
216
|
|
|
205
217
|
let color: RGB = { r: 255, g: 0, b: 0 };
|
|
206
218
|
|
|
207
219
|
const colorAnimation = new Animation(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
220
|
+
[
|
|
221
|
+
{ percentage: 0, value: { r: 255, g: 0, b: 0 } }, // Red
|
|
222
|
+
{ percentage: 0.5, value: { r: 255, g: 255, b: 0 } }, // Yellow
|
|
223
|
+
{ percentage: 1, value: { r: 0, g: 255, b: 0 } }, // Green
|
|
224
|
+
],
|
|
225
|
+
value => {
|
|
226
|
+
color = value;
|
|
227
|
+
},
|
|
228
|
+
rgbHelperFunctions,
|
|
229
|
+
2000
|
|
216
230
|
);
|
|
217
231
|
```
|
|
218
232
|
|
|
@@ -226,13 +240,15 @@ import { Animation, stringHelperFunctions } from '@ue-too/animate';
|
|
|
226
240
|
let state = 'idle';
|
|
227
241
|
|
|
228
242
|
const stateAnimation = new Animation(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
243
|
+
[
|
|
244
|
+
{ percentage: 0, value: 'idle' },
|
|
245
|
+
{ percentage: 1, value: 'active' },
|
|
246
|
+
],
|
|
247
|
+
value => {
|
|
248
|
+
state = value;
|
|
249
|
+
},
|
|
250
|
+
stringHelperFunctions,
|
|
251
|
+
500
|
|
236
252
|
);
|
|
237
253
|
```
|
|
238
254
|
|
|
@@ -246,15 +262,17 @@ import { Animation, integerHelperFunctions } from '@ue-too/animate';
|
|
|
246
262
|
let frameIndex = 0;
|
|
247
263
|
|
|
248
264
|
const frameAnimation = new Animation(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
265
|
+
[
|
|
266
|
+
{ percentage: 0, value: 0 },
|
|
267
|
+
{ percentage: 0.33, value: 1 },
|
|
268
|
+
{ percentage: 0.66, value: 2 },
|
|
269
|
+
{ percentage: 1, value: 3 },
|
|
270
|
+
],
|
|
271
|
+
value => {
|
|
272
|
+
frameIndex = value;
|
|
273
|
+
},
|
|
274
|
+
integerHelperFunctions,
|
|
275
|
+
400
|
|
258
276
|
);
|
|
259
277
|
```
|
|
260
278
|
|
|
@@ -268,23 +286,27 @@ import { Animation, numberHelperFunctions } from '@ue-too/animate';
|
|
|
268
286
|
let opacity = 0;
|
|
269
287
|
|
|
270
288
|
const fadeIn = new Animation(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
289
|
+
[
|
|
290
|
+
{ percentage: 0, value: 0 },
|
|
291
|
+
{ percentage: 1, value: 1, easingFn: t => t * t }, // Ease-in
|
|
292
|
+
],
|
|
293
|
+
value => {
|
|
294
|
+
opacity = value;
|
|
295
|
+
},
|
|
296
|
+
numberHelperFunctions,
|
|
297
|
+
500
|
|
278
298
|
);
|
|
279
299
|
|
|
280
300
|
const fadeOut = new Animation(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
301
|
+
[
|
|
302
|
+
{ percentage: 0, value: 1 },
|
|
303
|
+
{ percentage: 1, value: 0, easingFn: t => 1 - (1 - t) * (1 - t) }, // Ease-out
|
|
304
|
+
],
|
|
305
|
+
value => {
|
|
306
|
+
opacity = value;
|
|
307
|
+
},
|
|
308
|
+
numberHelperFunctions,
|
|
309
|
+
500
|
|
288
310
|
);
|
|
289
311
|
```
|
|
290
312
|
|
|
@@ -297,14 +319,20 @@ import { Point } from '@ue-too/math';
|
|
|
297
319
|
let spritePosition: Point = { x: 0, y: 0 };
|
|
298
320
|
|
|
299
321
|
const bounce = new Animation(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
322
|
+
[
|
|
323
|
+
{ percentage: 0, value: { x: 0, y: 0 } },
|
|
324
|
+
{
|
|
325
|
+
percentage: 0.5,
|
|
326
|
+
value: { x: 0, y: -50 },
|
|
327
|
+
easingFn: t => 1 - Math.pow(1 - t, 3),
|
|
328
|
+
}, // Ease-out up
|
|
329
|
+
{ percentage: 1, value: { x: 0, y: 0 }, easingFn: t => t * t * t }, // Ease-in down
|
|
330
|
+
],
|
|
331
|
+
value => {
|
|
332
|
+
spritePosition = value;
|
|
333
|
+
},
|
|
334
|
+
pointHelperFunctions,
|
|
335
|
+
1000
|
|
308
336
|
);
|
|
309
337
|
|
|
310
338
|
bounce.loops = true; // Loop forever
|
|
@@ -313,30 +341,52 @@ bounce.loops = true; // Loop forever
|
|
|
313
341
|
### Sequential Animation Sequence
|
|
314
342
|
|
|
315
343
|
```typescript
|
|
316
|
-
import {
|
|
344
|
+
import {
|
|
345
|
+
Animation,
|
|
346
|
+
CompositeAnimation,
|
|
347
|
+
numberHelperFunctions,
|
|
348
|
+
pointHelperFunctions,
|
|
349
|
+
} from '@ue-too/animate';
|
|
317
350
|
|
|
318
|
-
let x = 0,
|
|
351
|
+
let x = 0,
|
|
352
|
+
y = 0,
|
|
353
|
+
opacity = 0;
|
|
319
354
|
|
|
320
355
|
// Create individual animations
|
|
321
356
|
const fadeIn = new Animation(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
357
|
+
[
|
|
358
|
+
{ percentage: 0, value: 0 },
|
|
359
|
+
{ percentage: 1, value: 1 },
|
|
360
|
+
],
|
|
361
|
+
value => {
|
|
362
|
+
opacity = value;
|
|
363
|
+
},
|
|
364
|
+
numberHelperFunctions,
|
|
365
|
+
500
|
|
326
366
|
);
|
|
327
367
|
|
|
328
368
|
const slideRight = new Animation(
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
369
|
+
[
|
|
370
|
+
{ percentage: 0, value: 0 },
|
|
371
|
+
{ percentage: 1, value: 100 },
|
|
372
|
+
],
|
|
373
|
+
value => {
|
|
374
|
+
x = value;
|
|
375
|
+
},
|
|
376
|
+
numberHelperFunctions,
|
|
377
|
+
500
|
|
333
378
|
);
|
|
334
379
|
|
|
335
380
|
const slideDown = new Animation(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
381
|
+
[
|
|
382
|
+
{ percentage: 0, value: 0 },
|
|
383
|
+
{ percentage: 1, value: 50 },
|
|
384
|
+
],
|
|
385
|
+
value => {
|
|
386
|
+
y = value;
|
|
387
|
+
},
|
|
388
|
+
numberHelperFunctions,
|
|
389
|
+
300
|
|
340
390
|
);
|
|
341
391
|
|
|
342
392
|
// Create sequence: fade in, then slide right, then slide down
|
|
@@ -349,9 +399,9 @@ sequence.start();
|
|
|
349
399
|
|
|
350
400
|
// Update in game loop
|
|
351
401
|
function update(deltaTime: number) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
402
|
+
sequence.animate(deltaTime);
|
|
403
|
+
// Render sprite at (x, y) with opacity
|
|
404
|
+
requestAnimationFrame(() => update(16));
|
|
355
405
|
}
|
|
356
406
|
```
|
|
357
407
|
|
|
@@ -376,12 +426,12 @@ sequence.addAnimationAfter('scale', scaleAnimation, 'fadeIn');
|
|
|
376
426
|
const animation = new Animation(/* ... */);
|
|
377
427
|
|
|
378
428
|
animation.onStart(() => {
|
|
379
|
-
|
|
429
|
+
console.log('Animation started!');
|
|
380
430
|
});
|
|
381
431
|
|
|
382
432
|
animation.onEnd(() => {
|
|
383
|
-
|
|
384
|
-
|
|
433
|
+
console.log('Animation completed!');
|
|
434
|
+
// Trigger next action
|
|
385
435
|
});
|
|
386
436
|
|
|
387
437
|
animation.start();
|
|
@@ -410,20 +460,23 @@ const easeOut = (t: number) => 1 - (1 - t) * (1 - t);
|
|
|
410
460
|
|
|
411
461
|
// Ease-in-out quadratic
|
|
412
462
|
const easeInOut = (t: number) =>
|
|
413
|
-
|
|
463
|
+
t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
|
|
414
464
|
|
|
415
465
|
// Elastic ease-out
|
|
416
466
|
const elasticOut = (t: number) => {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
467
|
+
const c4 = (2 * Math.PI) / 3;
|
|
468
|
+
return t === 0
|
|
469
|
+
? 0
|
|
470
|
+
: t === 1
|
|
471
|
+
? 1
|
|
472
|
+
: Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
|
|
420
473
|
};
|
|
421
474
|
|
|
422
475
|
// Use in keyframe
|
|
423
476
|
const keyframe = {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
477
|
+
percentage: 1,
|
|
478
|
+
value: 100,
|
|
479
|
+
easingFn: easeInOut,
|
|
427
480
|
};
|
|
428
481
|
```
|
|
429
482
|
|
|
@@ -440,18 +493,20 @@ This package is written in TypeScript with complete type definitions:
|
|
|
440
493
|
type Position = { x: number; y: number };
|
|
441
494
|
|
|
442
495
|
const posAnimation: Animation<Position> = new Animation(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
496
|
+
[{ percentage: 0, value: { x: 0, y: 0 } }],
|
|
497
|
+
(value: Position) => {
|
|
498
|
+
/* ... */
|
|
499
|
+
},
|
|
500
|
+
pointHelperFunctions,
|
|
501
|
+
1000
|
|
447
502
|
);
|
|
448
503
|
|
|
449
504
|
// Custom helper functions are type-safe
|
|
450
505
|
const myHelper: AnimatableAttributeHelper<number> = {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
506
|
+
lerp: (ratio, start, end) => {
|
|
507
|
+
// TypeScript knows start.value and end.value are numbers
|
|
508
|
+
return start.value + ratio * (end.value - start.value);
|
|
509
|
+
},
|
|
455
510
|
};
|
|
456
511
|
```
|
|
457
512
|
|
|
@@ -473,6 +528,7 @@ This animation library follows these principles:
|
|
|
473
528
|
- **Memory**: Each animation retains keyframe data and callbacks
|
|
474
529
|
|
|
475
530
|
**Performance Tips:**
|
|
531
|
+
|
|
476
532
|
- Reuse animation instances when possible
|
|
477
533
|
- Use composite animations to group related animations
|
|
478
534
|
- Unsubscribe from callbacks (`onStart`, `onEnd`) when no longer needed
|
package/composite-animation.d.ts
CHANGED
package/index.d.ts
CHANGED
|
@@ -98,5 +98,5 @@
|
|
|
98
98
|
* @see {@link Animation} for single value animations
|
|
99
99
|
* @see {@link CompositeAnimation} for animation sequencing
|
|
100
100
|
*/
|
|
101
|
-
export * from
|
|
102
|
-
export * from
|
|
101
|
+
export * from './animatable-attribute';
|
|
102
|
+
export * from './composite-animation';
|
package/index.js.map
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
"composite-animation.ts"
|
|
6
6
|
],
|
|
7
7
|
"sourcesContent": [
|
|
8
|
-
"import { PointCal, Point } from \"@ue-too/math\";\n\n/**\n * Represents a keyframe in an animation timeline.\n *\n * @remarks\n * A keyframe defines a value at a specific point in the animation's progress.\n * Keyframes are defined with a percentage from 0.0 (start) to 1.0 (end), along\n * with the value at that point and an optional easing function for interpolation\n * to the next keyframe.\n *\n * @typeParam T - The type of value being animated (number, Point, RGB, etc.)\n *\n * @example\n * ```typescript\n * const keyframe: Keyframe<number> = {\n * percentage: 0.5,\n * value: 50,\n * easingFn: (t) => t * t // Ease-in quadratic\n * };\n * ```\n *\n * @category Types\n */\nexport type Keyframe<T> = {\n /** Animation progress from 0.0 (start) to 1.0 (end) */\n percentage: number;\n /** Value at this keyframe */\n value: T;\n /** Optional easing function for interpolation to next keyframe */\n easingFn?: (percentage: number) => number;\n}\n\n/**\n * Interface for type-specific interpolation helpers.\n *\n * @remarks\n * Animation helpers provide the `lerp` (linear interpolation) logic for specific types.\n * Different types require different interpolation strategies:\n * - Numbers: Simple linear interpolation\n * - Points: Component-wise interpolation\n * - Colors (RGB): Component-wise color interpolation\n * - Strings: Step-based (threshold) interpolation\n *\n * @typeParam T - The type of value being interpolated\n *\n * @example\n * ```typescript\n * const myHelper: AnimatableAttributeHelper<number> = {\n * lerp: (ratio, start, end) => {\n * const t = (ratio - start.percentage) / (end.percentage - start.percentage);\n * return start.value + t * (end.value - start.value);\n * }\n * };\n * ```\n *\n * @category Helpers\n */\nexport interface AnimatableAttributeHelper<T> {\n /**\n * Interpolates between two keyframes at a given ratio.\n *\n * @param ratio - Current animation progress (0.0 to 1.0)\n * @param start - Starting keyframe\n * @param end - Ending keyframe\n * @returns Interpolated value at the given ratio\n */\n lerp(ratio: number, start: Keyframe<T>, end: Keyframe<T>): T;\n}\n\n/**\n * Built-in interpolation helper for animating Point values.\n *\n * @remarks\n * Provides linear interpolation for 2D points with optional easing.\n * Interpolates both x and y components independently.\n *\n * @category Helpers\n */\nexport const pointHelperFunctions: AnimatableAttributeHelper<Point> = {\n lerp: (ratio: number, start: Keyframe<Point>, end: Keyframe<Point>): Point => {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(start.value, PointCal.multiplyVectorByScalar(PointCal.subVector(end.value, start.value), transformed));\n return res;\n }\n};\n\nexport class PointAnimationHelper implements AnimatableAttributeHelper<Point> {\n\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<Point>, end: Keyframe<Point>): Point {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(start.value, PointCal.multiplyVectorByScalar(PointCal.subVector(end.value, start.value), transformed));\n return res;\n }\n\n}\n\n/**\n * Built-in interpolation helper for animating number values.\n *\n * @remarks\n * Provides linear interpolation for numeric values with optional easing.\n *\n * @category Helpers\n */\nexport const numberHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (ratio: number, start: Keyframe<number>, end: Keyframe<number>): number => {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n }\n}\n\nexport class NumberAnimationHelper implements AnimatableAttributeHelper<number>{\n\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<number>, end: Keyframe<number>): number {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n }\n}\n\n/**\n * Built-in interpolation helper for animating string values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold. Returns start value until\n * 50% progress, then switches to end value. Useful for discrete property changes.\n *\n * @category Helpers\n */\nexport const stringHelperFunctions: AnimatableAttributeHelper<string> = {\n lerp: (ratio: number, start: Keyframe<string>, end: Keyframe<string>): string => {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\nexport class StringAnimationHelper implements AnimatableAttributeHelper<string>{\n constructor(){\n\n }\n \n lerp(ratio: number, start: Keyframe<string>, end: Keyframe<string>): string {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\n/**\n * Built-in interpolation helper for animating integer values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold, similar to strings.\n * Useful for discrete numeric properties like indices or counts.\n *\n * @category Helpers\n */\nexport const integerHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (ratio: number, start: Keyframe<number>, end: Keyframe<number>): number => {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\nexport class IntegerAnimationHelper implements AnimatableAttributeHelper<number>{\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<number>, end: Keyframe<number>): number {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\n/**\n * RGB color type for color animations.\n *\n * @remarks\n * Represents a color with red, green, and blue components (0-255).\n *\n * @category Types\n */\nexport type RGB = {r: number, g: number, b: number};\n\n/**\n * Built-in interpolation helper for animating RGB color values.\n *\n * @remarks\n * Provides linear interpolation for RGB colors with component-wise blending.\n *\n * @category Helpers\n */\nexport const rgbHelperFunctions: AnimatableAttributeHelper<RGB> = {\n lerp: (ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB => {\n const res = {\n r: start.value.r + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.r - start.value.r),\n g: start.value.g + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.g - start.value.g),\n b: start.value.b + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.b - start.value.b),\n }\n return res;\n }\n}\n\nexport class RGBAnimationHelper implements AnimatableAttributeHelper<RGB> {\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB {\n const res = {\n r: start.value.r + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.r - start.value.r),\n g: start.value.g + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.g - start.value.g),\n b: start.value.b + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.b - start.value.b),\n }\n return res;\n }\n}\n",
|
|
9
|
-
"import { AnimatableAttributeHelper, Keyframe } from \"./animatable-attribute\";\n\n/**\n * Linear easing function (no easing).\n *\n * @param percentage - Animation progress (0.0 to 1.0)\n * @returns Same as input (linear progression)\n *\n * @category Easing\n */\nexport const linear = (percentage: number) => {\n return percentage;\n}\n\n/**\n * Core interface for all animators in the animation system.\n *\n * @remarks\n * The Animator interface defines the contract for both individual animations ({@link Animation})\n * and composite animations ({@link CompositeAnimation}). All animators support:\n * - Lifecycle control (start, stop, pause, resume)\n * - Duration management with delays and drag time\n * - Looping with optional max loop count\n * - Parent-child relationships for composition\n * - Event callbacks for start and end\n *\n * @category Core\n */\nexport interface Animator{\n loops: boolean;\n duration: number;\n delay: number;\n drag: number;\n nonCascadingDuration(newDuration: number): void;\n start(): void;\n stop(): void;\n pause(): void;\n resume(): void;\n animate(deltaTime: number): void;\n setUp(): void;\n resetAnimationState(): void;\n tearDown(): void;\n setParent(parent: AnimatorContainer): void;\n detachParent(): void;\n toggleReverse(reverse: boolean): void;\n onEnd(callback: Function): UnSubscribe;\n onStart(callback: Function): UnSubscribe;\n clearOnStart(): void;\n clearOnEnd(): void;\n maxLoopCount: number | undefined;\n playing: boolean;\n}\n\n/**\n * Function type for unsubscribing from animation events.\n *\n * @category Core\n */\nexport type UnSubscribe = () => void;\n\n/**\n * Interface for containers that hold and manage child animators.\n *\n * @remarks\n * Implemented by {@link CompositeAnimation} to manage hierarchical animation structures.\n * Handles duration updates and prevents cyclic dependencies.\n *\n * @category Core\n */\nexport interface AnimatorContainer {\n updateDuration(): void;\n checkCyclicChildren(): boolean;\n containsAnimation(animationInInterest: Animator): boolean;\n}\n\n/**\n * Container for sequencing and composing multiple animations.\n *\n * @remarks\n * CompositeAnimation allows you to orchestrate complex animation sequences by:\n * - **Sequencing**: Add animations to play one after another\n * - **Overlapping**: Start animations before previous ones complete\n * - **Synchronizing**: Play multiple animations simultaneously\n * - **Nesting**: Compose animations contain other composite animations\n *\n * ## Key Features\n *\n * - Add animations at specific time offsets\n * - Position animations relative to other animations (`addAnimationAfter`, `addAnimationBefore`)\n * - Automatic duration calculation based on child animations\n * - Hierarchical composition for complex sequences\n * - Prevent cyclic animation dependencies\n *\n * @example\n * Basic sequence\n * ```typescript\n * const sequence = new CompositeAnimation();\n *\n * // Add first animation at start (time 0)\n * sequence.addAnimation('fadeIn', fadeAnimation, 0);\n *\n * // Add second animation after first completes\n * sequence.addAnimationAfter('slideIn', slideAnimation, 'fadeIn');\n *\n * // Add third animation to overlap with second (100ms after second starts)\n * sequence.addAnimationAdmist('scaleUp', scaleAnimation, 'slideIn', 100);\n *\n * sequence.start();\n * ```\n *\n * @category Core\n */\nexport class CompositeAnimation implements Animator, AnimatorContainer{\n\n private animations: Map<string, {animator: Animator, startTime?: number}>;\n private localTime: number;\n private _duration: number;\n private onGoing: boolean;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private _dragTime: number;\n private _delayTime: number;\n private parent: AnimatorContainer | undefined;\n private _maxLoopCount: number | undefined;\n\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n\n private reverse: boolean;\n\n constructor(animations: Map<string, {animator: Animator, startTime?: number}> = new Map(), loop: boolean = false, parent: AnimatorContainer | undefined = undefined, setupFn: Function = ()=>{}, tearDownFn: Function = ()=>{}){\n this.animations = animations;\n this._duration = 0;\n this.calculateDuration();\n this.localTime = -1;\n this.onGoing = false;\n this.loop = loop;\n this.setUpFn = setupFn;\n this.tearDownFn = tearDownFn;\n this._delayTime = 0;\n this._dragTime = 0;\n this.parent = parent;\n this.animations.forEach((animation) => {\n animation.animator.setParent(this);\n });\n this.reverse = false;\n this.playedTime = 0;\n }\n\n toggleReverse(reverse: boolean){\n if(this.reverse == reverse){\n return;\n }\n this.reverse = reverse;\n this.animations.forEach((animation) => {\n animation.animator.toggleReverse(reverse);\n });\n }\n \n setParent(parent: AnimatorContainer){\n this.parent = parent;\n }\n\n detachParent(){\n this.parent = undefined;\n }\n\n animate(deltaTime: number): void {\n if(!this.onGoing || this.localTime > this._duration + this._delayTime + this._dragTime || this.localTime < 0 || this.animations.size == 0){\n return;\n }\n this.localTime += deltaTime;\n if (this.localTime - deltaTime <= 0 && deltaTime > 0){\n // console.log(\"composite animation start\");\n this.startCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n }\n this.animateChildren(deltaTime);\n this.checkTerminalAndLoop();\n }\n\n checkTerminalAndLoop(){\n if(this.localTime >= this._duration + this._delayTime + this._dragTime){\n // console.log(\"composite animation end\");\n this.playedTime += 1;\n this.endCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n if(!this.loops || (this.maxLoopCount != undefined && this.playedTime >= this.maxLoopCount)){\n // this.onGoing = false;\n this.stop();\n } else {\n // if loop is true and current loop is not the last loop, then prepare to start the animations again\n // this.onGoing = true;\n // this.localTime = 0;\n // this.animations.forEach((animation) => {\n // if(animation.animator.loops){\n // animation.animator.startAnimation();\n // }\n // });\n this.start();\n }\n }\n }\n\n animateChildren(deltaTime: number){\n const prevLocalTime = this.localTime - deltaTime;\n if(this.localTime < this._delayTime){\n return;\n }\n this.animations.forEach((animation, name: string) => {\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n if(!this.childShouldAnimate(animation, prevLocalTime)){\n this.wrapUpAnimator({animator: animation.animator, startTime: animation.startTime, name: name}, prevLocalTime);\n return;\n }\n if(prevLocalTime - this._delayTime < animation.startTime){\n animation.animator.animate(this.localTime - this._delayTime - animation.startTime);\n } else {\n animation.animator.animate(deltaTime);\n }\n });\n }\n\n childShouldAnimate(animation: {animator: Animator, startTime?: number}, prevLocalTime: number): boolean{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n if(this.localTime - this._delayTime >= animation.startTime && this.localTime - this._delayTime <= animation.startTime + animation.animator.duration){\n return true;\n }\n return false;\n }\n\n wrapUpAnimator(animation: {animator: Animator, startTime?: number, name: string}, prevLocalTime: number){\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n if(this.localTime - this._delayTime > animation.startTime + animation.animator.duration && prevLocalTime - this._delayTime < animation.startTime + animation.animator.duration){\n // console.log(\"wrap up\", animation.name);\n // console.log(\"time remaining\", animation.startTime + animation.animator.duration - (prevLocalTime - this._delayTime));\n \n animation.animator.animate(animation.startTime + animation.animator.duration - (prevLocalTime - this._delayTime));\n }\n }\n\n pause(): void {\n this.onGoing = false;\n this.animations.forEach((animation) => {\n animation.animator.pause();\n });\n }\n\n resume(): void {\n this.onGoing = true;\n this.animations.forEach((animation) => {\n animation.animator.resume();\n });\n }\n\n start(): void {\n this.onGoing = true;\n this.setUp();\n this.localTime = 0;\n this.animations.forEach((animation) => {\n animation.animator.start();\n });\n }\n\n stop(): void {\n this.onGoing = false;\n this.playedTime = 0;\n this.localTime = this._duration + 0.1;\n this.animations.forEach((animation) => {\n animation.animator.stop();\n });\n this.tearDown();\n }\n\n get duration(): number {\n return this._duration + this._delayTime + this._dragTime;\n }\n\n set duration(duration: number) {\n if(duration < 0){\n return;\n }\n const originalDuration = this._duration + this._delayTime + this._dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach((animation)=>{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if(newDuration < 0){\n return;\n }\n const originalDuration = this._duration + this._delayTime + this._dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach((animation)=>{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.animations.forEach((animation) => {\n animation.animator.resetAnimationState();\n });\n }\n\n getTrueDuration(): number{\n return this._duration;\n }\n\n setUp(): void {\n this.setUpFn();\n this.animations.forEach((animation) => {\n animation.animator.setUp();\n });\n }\n\n tearDown(): void {\n this.tearDownFn();\n this.animations.forEach((animation) => {\n animation.animator.tearDown();\n }); \n }\n\n addAnimation(name: string, animation: Animator, startTime: number = 0, endCallback: Function = ()=>{}){\n if(this.animations.has(name)){\n return;\n }\n if(this.parent !== undefined && this.parent.containsAnimation(animation)){\n return;\n }\n this.animations.set(name, {animator: animation, startTime: startTime});\n animation.setParent(this);\n if(this.localTime > startTime){\n animation.animate(this.localTime - startTime);\n }\n const endTime = startTime + animation.duration;\n this._duration = Math.max(this._duration, endTime);\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n addAnimationAfter(name: string, animation: Animator, afterName: string, delay: number = 0){\n let afterAnimation = this.animations.get(afterName);\n if(afterAnimation == undefined){\n return;\n }\n if(afterAnimation.startTime == undefined){\n afterAnimation.startTime = 0;\n }\n let startTime = afterAnimation.startTime + afterAnimation.animator.duration;\n startTime += delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n addAnimationAdmist(name: string, animation: Animator, admistName: string, delay: number){\n let admistAnimation = this.animations.get(admistName);\n if(admistAnimation == undefined){\n return;\n }\n if(admistAnimation.startTime == undefined){\n admistAnimation.startTime = 0;\n }\n let startTime = admistAnimation.startTime + delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n addAnimationBefore(name: string, animation: Animator, beforeName: string, aheadTime: number = 0){\n let beforeAnimation = this.animations.get(beforeName);\n if(beforeAnimation == undefined){\n return;\n }\n if(beforeAnimation.startTime == undefined){\n beforeAnimation.startTime = 0;\n }\n let startTime = beforeAnimation.startTime;\n startTime -= aheadTime;\n this.addAnimation(name, animation, startTime);\n if (startTime < 0){\n const pushOver = 0 - startTime;\n this.animations.forEach((animation) => {\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n animation.startTime += pushOver;\n });\n }\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n removeAnimation(name: string){\n let animation = this.animations.get(name);\n let deleted = this.animations.delete(name);\n if(deleted){\n if(animation != undefined){\n animation.animator.detachParent();\n }\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n }\n\n set delay(delayTime: number){\n this._delayTime = delayTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get delay(): number{\n return this._delayTime;\n }\n\n set drag(dragTime: number){\n this._dragTime = dragTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this._dragTime;\n }\n\n removeDelay(){\n this._delayTime = 0;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n removeDrag(){\n this._dragTime = 0;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n updateDuration(): void {\n if(this.checkCyclicChildren()){\n return;\n }\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n calculateDuration(){\n this._duration = 0;\n this.animations.forEach((animation)=>{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n const endTime = animation.startTime + animation.animator.duration;\n this._duration = Math.max(this._duration, endTime);\n });\n }\n \n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n checkCyclicChildren(): boolean {\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while(allChildren.length > 0){\n const current = allChildren.pop();\n if(current == undefined){\n continue;\n }\n if(visited.has(current)){\n return true;\n }\n visited.add(current);\n if(current instanceof CompositeAnimation){\n current.animations.forEach((animation) => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n forceToggleLoop(loop: boolean){\n this.loop = true;\n this.animations.forEach((animation) => {\n animation.animator.loops = true;\n });\n }\n\n containsAnimation(animationInInterest: Animator): boolean {\n if(this.parent !== undefined){\n return this.parent.containsAnimation(animationInInterest);\n }\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while(allChildren.length > 0){\n const current = allChildren.pop();\n if(current == undefined){\n continue;\n }\n if(current == animationInInterest){\n return true;\n }\n if(visited.has(current)){\n continue;\n }\n visited.add(current);\n if(current instanceof CompositeAnimation){\n current.animations.forEach((animation) => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n onEnd(callback: Function): UnSubscribe{\n this.endCallbacks.push(callback);\n return ()=>{\n this.endCallbacks = this.endCallbacks.filter((cb) => cb != callback);\n }\n }\n\n onStart(callback: Function): UnSubscribe{\n this.startCallbacks.push(callback);\n return ()=>{\n this.startCallbacks = this.startCallbacks.filter((cb) => cb != callback);\n }\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\n/**\n * Keyframe-based animation for a single value.\n *\n * @remarks\n * The Animation class interpolates a value through a series of keyframes over time.\n * It handles:\n * - Keyframe interpolation with binary search for efficiency\n * - Easing functions for smooth motion curves\n * - Reverse playback\n * - Looping with optional max loop count\n * - Delays before start and drag time after completion\n * - Lifecycle callbacks\n *\n * ## How It Works\n *\n * 1. Define keyframes at percentages (0.0 to 1.0) along the timeline\n * 2. Provide a callback to apply the animated value\n * 3. Provide an interpolation helper for the value type\n * 4. Call `animate(deltaTime)` each frame to progress the animation\n *\n * @typeParam T - The type of value being animated\n *\n * @example\n * Animating a number with easing\n * ```typescript\n * let opacity = 0;\n *\n * const fadeIn = new Animation(\n * [\n * { percentage: 0, value: 0 },\n * { percentage: 1, value: 1, easingFn: (t) => t * t } // Ease-in\n * ],\n * (value) => { opacity = value; },\n * numberHelperFunctions,\n * 1000 // 1 second duration\n * );\n *\n * fadeIn.start();\n *\n * // In animation loop\n * function loop(deltaTime: number) {\n * fadeIn.animate(deltaTime);\n * element.style.opacity = opacity;\n * }\n * ```\n *\n * @category Core\n */\nexport class Animation<T> implements Animator{\n\n private localTime: number; // local time starting from 0 up til duration\n private _duration: number;\n private keyframes: Keyframe<T>[];\n private animatableAttributeHelper: AnimatableAttributeHelper<T>;\n private applyAnimationValue: (value: T) => void;\n private easeFn: (percentage: number) => number;\n private onGoing: boolean;\n private currentKeyframeIndex: number;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private parent: AnimatorContainer | undefined;\n private delayTime: number = 0;\n private dragTime: number = 0;\n\n private reverse: boolean = false;\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n private startAfterDelayCallbacks: Function[] = [];\n\n private zeroPercentageValue: T;\n private _maxLoopCount: number | undefined;\n private _fillMode: 'none' | 'forwards' | 'backwards' | 'both' = 'none';\n\n constructor(keyFrames: Keyframe<T>[], applyAnimationValue: (value: T) => void, animatableAttributeHelper: AnimatableAttributeHelper<T>, duration: number = 1000, loop: boolean = false, parent: AnimatorContainer | undefined = undefined, setUpFn: Function = ()=>{}, tearDownFn: Function = ()=>{}, easeFn: (percentage: number) => number = linear){\n this._duration = duration;\n this.keyframes = keyFrames;\n this.animatableAttributeHelper = animatableAttributeHelper;\n this.applyAnimationValue = applyAnimationValue;\n this.easeFn = easeFn;\n this.onGoing = false;\n this.localTime = duration + 0.1;\n this.currentKeyframeIndex = 0;\n this.loop = loop;\n this.setUpFn = setUpFn;\n this.tearDownFn = tearDownFn;\n this.parent = parent;\n this.playedTime = 0;\n this.zeroPercentageValue = this.findValue(0, keyFrames, animatableAttributeHelper);\n }\n\n toggleReverse(reverse: boolean): void{\n this.reverse = reverse;\n }\n\n start(): void{\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.onGoing = true;\n // this.applyAnimationValue(this.zeroPercentageValue);\n this.setUp();\n }\n\n stop(): void{\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.playedTime = 0;\n this.tearDown();\n }\n\n pause(): void{\n this.onGoing = false;\n }\n\n resume(){\n this.onGoing = true;\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n animate(deltaTime: number){\n if(this.onGoing != true || this.localTime < 0) {\n return;\n }\n if(deltaTime == 0){\n return;\n }\n this.localTime += deltaTime;\n // console.log(\"--------------------\");\n // console.log(\"local time\", this.localTime);\n // console.log(\"delta time\", deltaTime);\n if(this.localTime - deltaTime <= 0 && deltaTime > 0){\n // console.log(\"--------------------\");\n // console.log(\"current localtime\", this.localTime);\n // console.log(\"current delta time\", deltaTime);\n // console.log(\"previous local time\", this.localTime - deltaTime);\n // console.log(\"animation start\");\n // console.log(`the animation has been played ${this.playedTime} times`);\n // console.log(`the animation is now playing for the ${this.playedTime + 1} time`);\n this.startCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n }\n if(this.localTime >= this.delayTime && (this.localTime <= this.delayTime + this._duration + this.dragTime || this.localTime - deltaTime <= this.delayTime + this._duration + this.dragTime)){\n // console.log(\"local time\", this.localTime);\n // console.log(\"duration\", this.duration);\n // console.log(\"local time would trigger end\", this.localTime >= this._duration + this.delayTime + this.dragTime);\n // console.log(\"delta time\", deltaTime);\n if(this.localTime - deltaTime <= this.delayTime && this.delayTime !== 0 && deltaTime > 0){\n this.startAfterDelayCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n this.applyAnimationValue(this.zeroPercentageValue);\n }\n let localTimePercentage = (this.localTime - this.delayTime) / (this._duration);\n let targetPercentage = this.easeFn(localTimePercentage);\n if (localTimePercentage > 1){\n targetPercentage = this.easeFn(1);\n }\n let value: T;\n // console.log(\"currentKeyframeIndex\", this.currentKeyframeIndex, \"length\", this.keyFrames.length);\n if(this.currentKeyframeIndex < this.keyframes.length && this.currentKeyframeIndex >= 0 && (this.reverse ? 1 - this.keyframes[this.currentKeyframeIndex].percentage == targetPercentage : this.keyframes[this.currentKeyframeIndex].percentage == targetPercentage) ){\n value = this.keyframes[this.currentKeyframeIndex].value;\n } else {\n value = this.findValue(targetPercentage, this.keyframes, this.animatableAttributeHelper);\n }\n if(this.reverse){\n while(this.currentKeyframeIndex >= 0 && 1 - this.keyframes[this.currentKeyframeIndex].percentage <= targetPercentage){\n this.currentKeyframeIndex -= 1;\n }\n } else {\n while(this.currentKeyframeIndex < this.keyframes.length && this.keyframes[this.currentKeyframeIndex].percentage <= targetPercentage){\n this.currentKeyframeIndex += 1;\n }\n }\n this.applyAnimationValue(value);\n if(this.localTime >= this._duration + this.dragTime + this.delayTime){\n // console.log(\"animation should end\");\n this.playedTime += 1;\n this.endCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n if(!this.loops || (this._maxLoopCount != undefined && this.playedTime >= (this.maxLoopCount ?? 0))){\n // this.onGoing = false;\n // console.log(\"animation should stop after \", this.playedTime, \" loops\");\n this.stop();\n } else {\n // console.log(\"animation should restart\");\n this.onGoing = true;\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.start();\n }\n }\n // if((this.localTime >= this._duration + this.delayTime + this.dragTime) && this.loop){\n // // this.startAnimation();\n // this.localTime = 0;\n // this.onGoing = true;\n // this.currentKeyframeIndex = 0;\n // }\n }\n }\n\n findValue(valuePercentage: number, keyframes: Keyframe<T>[], animatableAttributeHelper: AnimatableAttributeHelper<T>): T{\n if(valuePercentage > 1){\n if(this.reverse){\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[1], keyframes[0]);\n }\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[keyframes.length - 2], keyframes[keyframes.length - 1]);\n }\n if(valuePercentage < 0){\n if(this.reverse){\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[keyframes.length - 2], keyframes[keyframes.length - 1]);\n }\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[1], keyframes[0]);\n }\n let left = 0;\n let right = keyframes.length - 1;\n while (left <= right) {\n let mid = left + Math.floor((right - left) / 2);\n const midPercentage = this.reverse ? 1 - keyframes[mid].percentage : keyframes[mid].percentage;\n if(midPercentage == valuePercentage) {\n return keyframes[mid].value;\n } else if(midPercentage < valuePercentage){\n if(this.reverse){\n right = mid - 1;\n } else {\n left = mid + 1;\n }\n } else {\n if(this.reverse){\n left = mid + 1;\n } else {\n right = mid - 1;\n }\n }\n }\n if(left > keyframes.length - 1){\n // excceding the keyframes\n left = keyframes.length - 1;\n }\n const interpolateStartFrame = this.reverse ? {percentage: 1 - keyframes[left].percentage, value: keyframes[left].value} : keyframes[left - 1];\n const interplateEndFrame = this.reverse ? {percentage: 1 - keyframes[left - 1].percentage, value: keyframes[left - 1].value} : keyframes[left];\n // return animatableAttributeHelper.lerp(valuePercentage, keyframes[left - 1], keyframes[left]);\n return animatableAttributeHelper.lerp(valuePercentage, interpolateStartFrame, interplateEndFrame);\n }\n\n setUp(): void {\n // this.applyAnimationValue(this.keyframes[0].value);\n this.setUpFn();\n }\n\n tearDown(): void {\n this.tearDownFn(); \n }\n\n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n get duration(): number {\n return this._duration + this.delayTime + this.dragTime;\n }\n\n set duration(duration: number) {\n if(duration < 0){\n return;\n }\n const originalDuration = this._duration + this.delayTime + this.dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = this._duration * scale;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if(newDuration < 0){\n return;\n }\n const originalDuration = this._duration + this.delayTime + this.dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = newDuration;\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.applyAnimationValue(this.keyframes[0].value);\n this.currentKeyframeIndex = 0;\n this.setUp();\n }\n\n wrapUp(): void {\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.currentKeyframeIndex = 0;\n }\n\n get delay(): number {\n return this.delayTime;\n }\n\n set delay(delayTime: number){\n this.delayTime = delayTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this.dragTime;\n }\n\n set drag(dragTime: number){\n this.dragTime = dragTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get trueDuration(): number {\n return this._duration;\n }\n\n set trueDuration(duration: number){\n this._duration = duration;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n setParent(parent: AnimatorContainer){\n this.parent = parent;\n }\n\n detachParent(): void {\n this.parent = undefined;\n }\n\n set keyFrames(keyFrames: Keyframe<T>[]){\n this.keyframes = keyFrames;\n this.zeroPercentageValue = this.findValue(0, keyFrames, this.animatableAttributeHelper);\n }\n\n get keyFrames(): Keyframe<T>[]{\n return this.keyframes;\n }\n\n get easeFunction(): (percentage: number) => number {\n return this.easeFn;\n }\n\n set easeFunction(easeFn: (percentage: number) => number){\n this.easeFn = easeFn;\n }\n\n onEnd(callback: Function): UnSubscribe{\n this.endCallbacks.push(callback);\n return ()=>{\n this.endCallbacks = this.endCallbacks.filter((cb) => cb != callback);\n }\n }\n\n onStart(callback: Function): UnSubscribe{\n this.startCallbacks.push(callback);\n return ()=>{\n this.startCallbacks = this.startCallbacks.filter((cb) => cb != callback);\n }\n }\n\n onStartAfterDelay(callback: Function): UnSubscribe{\n this.startAfterDelayCallbacks.push(callback);\n return ()=>{\n this.startAfterDelayCallbacks = this.startAfterDelayCallbacks.filter((cb) => cb != callback);\n }\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\nexport interface Keyframes<T> {\n keyframes: Keyframe<T>[];\n from(value: T): Keyframes<T>;\n to(value: T): Keyframes<T>;\n insertAt(percentage: number, value: T): void;\n clearFrames(): void;\n}\n\nexport class KeyFramesContiner<T> {\n\n private _keyframes: Keyframe<T>[];\n\n constructor(){\n this._keyframes = [];\n }\n\n get keyframes(): Keyframe<T>[] {\n return this._keyframes;\n }\n\n from(value: T): Keyframes<T>{\n if(this._keyframes.length == 0){\n this._keyframes.push({percentage: 0, value: value});\n } else {\n if(this._keyframes[0].percentage == 0){\n this._keyframes[0].value = value;\n } else {\n this._keyframes.unshift({percentage: 0, value: value});\n }\n }\n return this;\n }\n\n to(value: T): Keyframes<T>{\n if(this._keyframes.length == 0){\n this._keyframes.push({percentage: 1, value: value});\n } else {\n if(this._keyframes[this._keyframes.length - 1].percentage == 1){\n this._keyframes[this._keyframes.length - 1].value = value;\n } else {\n this._keyframes.push({percentage: 1, value: value});\n }\n }\n return this;\n }\n\n insertAt(percentage: number, value: T): void{\n this._keyframes.push({percentage: percentage, value: value});\n }\n\n clearFrames(): void{\n this._keyframes = [];\n }\n}\n"
|
|
8
|
+
"import { Point, PointCal } from '@ue-too/math';\n\n/**\n * Represents a keyframe in an animation timeline.\n *\n * @remarks\n * A keyframe defines a value at a specific point in the animation's progress.\n * Keyframes are defined with a percentage from 0.0 (start) to 1.0 (end), along\n * with the value at that point and an optional easing function for interpolation\n * to the next keyframe.\n *\n * @typeParam T - The type of value being animated (number, Point, RGB, etc.)\n *\n * @example\n * ```typescript\n * const keyframe: Keyframe<number> = {\n * percentage: 0.5,\n * value: 50,\n * easingFn: (t) => t * t // Ease-in quadratic\n * };\n * ```\n *\n * @category Types\n */\nexport type Keyframe<T> = {\n /** Animation progress from 0.0 (start) to 1.0 (end) */\n percentage: number;\n /** Value at this keyframe */\n value: T;\n /** Optional easing function for interpolation to next keyframe */\n easingFn?: (percentage: number) => number;\n};\n\n/**\n * Interface for type-specific interpolation helpers.\n *\n * @remarks\n * Animation helpers provide the `lerp` (linear interpolation) logic for specific types.\n * Different types require different interpolation strategies:\n * - Numbers: Simple linear interpolation\n * - Points: Component-wise interpolation\n * - Colors (RGB): Component-wise color interpolation\n * - Strings: Step-based (threshold) interpolation\n *\n * @typeParam T - The type of value being interpolated\n *\n * @example\n * ```typescript\n * const myHelper: AnimatableAttributeHelper<number> = {\n * lerp: (ratio, start, end) => {\n * const t = (ratio - start.percentage) / (end.percentage - start.percentage);\n * return start.value + t * (end.value - start.value);\n * }\n * };\n * ```\n *\n * @category Helpers\n */\nexport interface AnimatableAttributeHelper<T> {\n /**\n * Interpolates between two keyframes at a given ratio.\n *\n * @param ratio - Current animation progress (0.0 to 1.0)\n * @param start - Starting keyframe\n * @param end - Ending keyframe\n * @returns Interpolated value at the given ratio\n */\n lerp(ratio: number, start: Keyframe<T>, end: Keyframe<T>): T;\n}\n\n/**\n * Built-in interpolation helper for animating Point values.\n *\n * @remarks\n * Provides linear interpolation for 2D points with optional easing.\n * Interpolates both x and y components independently.\n *\n * @category Helpers\n */\nexport const pointHelperFunctions: AnimatableAttributeHelper<Point> = {\n lerp: (\n ratio: number,\n start: Keyframe<Point>,\n end: Keyframe<Point>\n ): Point => {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(\n start.value,\n PointCal.multiplyVectorByScalar(\n PointCal.subVector(end.value, start.value),\n transformed\n )\n );\n return res;\n },\n};\n\nexport class PointAnimationHelper implements AnimatableAttributeHelper<Point> {\n constructor() {}\n\n lerp(ratio: number, start: Keyframe<Point>, end: Keyframe<Point>): Point {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(\n start.value,\n PointCal.multiplyVectorByScalar(\n PointCal.subVector(end.value, start.value),\n transformed\n )\n );\n return res;\n }\n}\n\n/**\n * Built-in interpolation helper for animating number values.\n *\n * @remarks\n * Provides linear interpolation for numeric values with optional easing.\n *\n * @category Helpers\n */\nexport const numberHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number => {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n },\n};\n\nexport class NumberAnimationHelper implements AnimatableAttributeHelper<number> {\n constructor() {}\n\n lerp(\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n }\n}\n\n/**\n * Built-in interpolation helper for animating string values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold. Returns start value until\n * 50% progress, then switches to end value. Useful for discrete property changes.\n *\n * @category Helpers\n */\nexport const stringHelperFunctions: AnimatableAttributeHelper<string> = {\n lerp: (\n ratio: number,\n start: Keyframe<string>,\n end: Keyframe<string>\n ): string => {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n },\n};\n\nexport class StringAnimationHelper implements AnimatableAttributeHelper<string> {\n constructor() {}\n\n lerp(\n ratio: number,\n start: Keyframe<string>,\n end: Keyframe<string>\n ): string {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n }\n}\n\n/**\n * Built-in interpolation helper for animating integer values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold, similar to strings.\n * Useful for discrete numeric properties like indices or counts.\n *\n * @category Helpers\n */\nexport const integerHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number => {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n },\n};\n\nexport class IntegerAnimationHelper implements AnimatableAttributeHelper<number> {\n constructor() {}\n\n lerp(\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n }\n}\n\n/**\n * RGB color type for color animations.\n *\n * @remarks\n * Represents a color with red, green, and blue components (0-255).\n *\n * @category Types\n */\nexport type RGB = { r: number; g: number; b: number };\n\n/**\n * Built-in interpolation helper for animating RGB color values.\n *\n * @remarks\n * Provides linear interpolation for RGB colors with component-wise blending.\n *\n * @category Helpers\n */\nexport const rgbHelperFunctions: AnimatableAttributeHelper<RGB> = {\n lerp: (ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB => {\n const res = {\n r:\n start.value.r +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.r - start.value.r),\n g:\n start.value.g +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.g - start.value.g),\n b:\n start.value.b +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.b - start.value.b),\n };\n return res;\n },\n};\n\nexport class RGBAnimationHelper implements AnimatableAttributeHelper<RGB> {\n constructor() {}\n\n lerp(ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB {\n const res = {\n r:\n start.value.r +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.r - start.value.r),\n g:\n start.value.g +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.g - start.value.g),\n b:\n start.value.b +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.b - start.value.b),\n };\n return res;\n }\n}\n",
|
|
9
|
+
"import { AnimatableAttributeHelper, Keyframe } from './animatable-attribute';\n\n/**\n * Linear easing function (no easing).\n *\n * @param percentage - Animation progress (0.0 to 1.0)\n * @returns Same as input (linear progression)\n *\n * @category Easing\n */\nexport const linear = (percentage: number) => {\n return percentage;\n};\n\n/**\n * Core interface for all animators in the animation system.\n *\n * @remarks\n * The Animator interface defines the contract for both individual animations ({@link Animation})\n * and composite animations ({@link CompositeAnimation}). All animators support:\n * - Lifecycle control (start, stop, pause, resume)\n * - Duration management with delays and drag time\n * - Looping with optional max loop count\n * - Parent-child relationships for composition\n * - Event callbacks for start and end\n *\n * @category Core\n */\nexport interface Animator {\n loops: boolean;\n duration: number;\n delay: number;\n drag: number;\n nonCascadingDuration(newDuration: number): void;\n start(): void;\n stop(): void;\n pause(): void;\n resume(): void;\n animate(deltaTime: number): void;\n setUp(): void;\n resetAnimationState(): void;\n tearDown(): void;\n setParent(parent: AnimatorContainer): void;\n detachParent(): void;\n toggleReverse(reverse: boolean): void;\n onEnd(callback: Function): UnSubscribe;\n onStart(callback: Function): UnSubscribe;\n clearOnStart(): void;\n clearOnEnd(): void;\n maxLoopCount: number | undefined;\n playing: boolean;\n}\n\n/**\n * Function type for unsubscribing from animation events.\n *\n * @category Core\n */\nexport type UnSubscribe = () => void;\n\n/**\n * Interface for containers that hold and manage child animators.\n *\n * @remarks\n * Implemented by {@link CompositeAnimation} to manage hierarchical animation structures.\n * Handles duration updates and prevents cyclic dependencies.\n *\n * @category Core\n */\nexport interface AnimatorContainer {\n updateDuration(): void;\n checkCyclicChildren(): boolean;\n containsAnimation(animationInInterest: Animator): boolean;\n}\n\n/**\n * Container for sequencing and composing multiple animations.\n *\n * @remarks\n * CompositeAnimation allows you to orchestrate complex animation sequences by:\n * - **Sequencing**: Add animations to play one after another\n * - **Overlapping**: Start animations before previous ones complete\n * - **Synchronizing**: Play multiple animations simultaneously\n * - **Nesting**: Compose animations contain other composite animations\n *\n * ## Key Features\n *\n * - Add animations at specific time offsets\n * - Position animations relative to other animations (`addAnimationAfter`, `addAnimationBefore`)\n * - Automatic duration calculation based on child animations\n * - Hierarchical composition for complex sequences\n * - Prevent cyclic animation dependencies\n *\n * @example\n * Basic sequence\n * ```typescript\n * const sequence = new CompositeAnimation();\n *\n * // Add first animation at start (time 0)\n * sequence.addAnimation('fadeIn', fadeAnimation, 0);\n *\n * // Add second animation after first completes\n * sequence.addAnimationAfter('slideIn', slideAnimation, 'fadeIn');\n *\n * // Add third animation to overlap with second (100ms after second starts)\n * sequence.addAnimationAdmist('scaleUp', scaleAnimation, 'slideIn', 100);\n *\n * sequence.start();\n * ```\n *\n * @category Core\n */\nexport class CompositeAnimation implements Animator, AnimatorContainer {\n private animations: Map<string, { animator: Animator; startTime?: number }>;\n private localTime: number;\n private _duration: number;\n private onGoing: boolean;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private _dragTime: number;\n private _delayTime: number;\n private parent: AnimatorContainer | undefined;\n private _maxLoopCount: number | undefined;\n\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n\n private reverse: boolean;\n\n constructor(\n animations: Map<\n string,\n { animator: Animator; startTime?: number }\n > = new Map(),\n loop: boolean = false,\n parent: AnimatorContainer | undefined = undefined,\n setupFn: Function = () => {},\n tearDownFn: Function = () => {}\n ) {\n this.animations = animations;\n this._duration = 0;\n this.calculateDuration();\n this.localTime = -1;\n this.onGoing = false;\n this.loop = loop;\n this.setUpFn = setupFn;\n this.tearDownFn = tearDownFn;\n this._delayTime = 0;\n this._dragTime = 0;\n this.parent = parent;\n this.animations.forEach(animation => {\n animation.animator.setParent(this);\n });\n this.reverse = false;\n this.playedTime = 0;\n }\n\n toggleReverse(reverse: boolean) {\n if (this.reverse == reverse) {\n return;\n }\n this.reverse = reverse;\n this.animations.forEach(animation => {\n animation.animator.toggleReverse(reverse);\n });\n }\n\n setParent(parent: AnimatorContainer) {\n this.parent = parent;\n }\n\n detachParent() {\n this.parent = undefined;\n }\n\n animate(deltaTime: number): void {\n if (\n !this.onGoing ||\n this.localTime >\n this._duration + this._delayTime + this._dragTime ||\n this.localTime < 0 ||\n this.animations.size == 0\n ) {\n return;\n }\n this.localTime += deltaTime;\n if (this.localTime - deltaTime <= 0 && deltaTime > 0) {\n // console.log(\"composite animation start\");\n this.startCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n }\n this.animateChildren(deltaTime);\n this.checkTerminalAndLoop();\n }\n\n checkTerminalAndLoop() {\n if (\n this.localTime >=\n this._duration + this._delayTime + this._dragTime\n ) {\n // console.log(\"composite animation end\");\n this.playedTime += 1;\n this.endCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n if (\n !this.loops ||\n (this.maxLoopCount != undefined &&\n this.playedTime >= this.maxLoopCount)\n ) {\n // this.onGoing = false;\n this.stop();\n } else {\n // if loop is true and current loop is not the last loop, then prepare to start the animations again\n // this.onGoing = true;\n // this.localTime = 0;\n // this.animations.forEach((animation) => {\n // if(animation.animator.loops){\n // animation.animator.startAnimation();\n // }\n // });\n this.start();\n }\n }\n }\n\n animateChildren(deltaTime: number) {\n const prevLocalTime = this.localTime - deltaTime;\n if (this.localTime < this._delayTime) {\n return;\n }\n this.animations.forEach((animation, name: string) => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n if (!this.childShouldAnimate(animation, prevLocalTime)) {\n this.wrapUpAnimator(\n {\n animator: animation.animator,\n startTime: animation.startTime,\n name: name,\n },\n prevLocalTime\n );\n return;\n }\n if (prevLocalTime - this._delayTime < animation.startTime) {\n animation.animator.animate(\n this.localTime - this._delayTime - animation.startTime\n );\n } else {\n animation.animator.animate(deltaTime);\n }\n });\n }\n\n childShouldAnimate(\n animation: { animator: Animator; startTime?: number },\n prevLocalTime: number\n ): boolean {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n if (\n this.localTime - this._delayTime >= animation.startTime &&\n this.localTime - this._delayTime <=\n animation.startTime + animation.animator.duration\n ) {\n return true;\n }\n return false;\n }\n\n wrapUpAnimator(\n animation: { animator: Animator; startTime?: number; name: string },\n prevLocalTime: number\n ) {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n if (\n this.localTime - this._delayTime >\n animation.startTime + animation.animator.duration &&\n prevLocalTime - this._delayTime <\n animation.startTime + animation.animator.duration\n ) {\n // console.log(\"wrap up\", animation.name);\n // console.log(\"time remaining\", animation.startTime + animation.animator.duration - (prevLocalTime - this._delayTime));\n\n animation.animator.animate(\n animation.startTime +\n animation.animator.duration -\n (prevLocalTime - this._delayTime)\n );\n }\n }\n\n pause(): void {\n this.onGoing = false;\n this.animations.forEach(animation => {\n animation.animator.pause();\n });\n }\n\n resume(): void {\n this.onGoing = true;\n this.animations.forEach(animation => {\n animation.animator.resume();\n });\n }\n\n start(): void {\n this.onGoing = true;\n this.setUp();\n this.localTime = 0;\n this.animations.forEach(animation => {\n animation.animator.start();\n });\n }\n\n stop(): void {\n this.onGoing = false;\n this.playedTime = 0;\n this.localTime = this._duration + 0.1;\n this.animations.forEach(animation => {\n animation.animator.stop();\n });\n this.tearDown();\n }\n\n get duration(): number {\n return this._duration + this._delayTime + this._dragTime;\n }\n\n set duration(duration: number) {\n if (duration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this._delayTime + this._dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if (newDuration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this._delayTime + this._dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.animations.forEach(animation => {\n animation.animator.resetAnimationState();\n });\n }\n\n getTrueDuration(): number {\n return this._duration;\n }\n\n setUp(): void {\n this.setUpFn();\n this.animations.forEach(animation => {\n animation.animator.setUp();\n });\n }\n\n tearDown(): void {\n this.tearDownFn();\n this.animations.forEach(animation => {\n animation.animator.tearDown();\n });\n }\n\n addAnimation(\n name: string,\n animation: Animator,\n startTime: number = 0,\n endCallback: Function = () => {}\n ) {\n if (this.animations.has(name)) {\n return;\n }\n if (\n this.parent !== undefined &&\n this.parent.containsAnimation(animation)\n ) {\n return;\n }\n this.animations.set(name, {\n animator: animation,\n startTime: startTime,\n });\n animation.setParent(this);\n if (this.localTime > startTime) {\n animation.animate(this.localTime - startTime);\n }\n const endTime = startTime + animation.duration;\n this._duration = Math.max(this._duration, endTime);\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n addAnimationAfter(\n name: string,\n animation: Animator,\n afterName: string,\n delay: number = 0\n ) {\n let afterAnimation = this.animations.get(afterName);\n if (afterAnimation == undefined) {\n return;\n }\n if (afterAnimation.startTime == undefined) {\n afterAnimation.startTime = 0;\n }\n let startTime =\n afterAnimation.startTime + afterAnimation.animator.duration;\n startTime += delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n addAnimationAdmist(\n name: string,\n animation: Animator,\n admistName: string,\n delay: number\n ) {\n let admistAnimation = this.animations.get(admistName);\n if (admistAnimation == undefined) {\n return;\n }\n if (admistAnimation.startTime == undefined) {\n admistAnimation.startTime = 0;\n }\n let startTime = admistAnimation.startTime + delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n addAnimationBefore(\n name: string,\n animation: Animator,\n beforeName: string,\n aheadTime: number = 0\n ) {\n let beforeAnimation = this.animations.get(beforeName);\n if (beforeAnimation == undefined) {\n return;\n }\n if (beforeAnimation.startTime == undefined) {\n beforeAnimation.startTime = 0;\n }\n let startTime = beforeAnimation.startTime;\n startTime -= aheadTime;\n this.addAnimation(name, animation, startTime);\n if (startTime < 0) {\n const pushOver = 0 - startTime;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n animation.startTime += pushOver;\n });\n }\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n removeAnimation(name: string) {\n let animation = this.animations.get(name);\n let deleted = this.animations.delete(name);\n if (deleted) {\n if (animation != undefined) {\n animation.animator.detachParent();\n }\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n }\n\n set delay(delayTime: number) {\n this._delayTime = delayTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get delay(): number {\n return this._delayTime;\n }\n\n set drag(dragTime: number) {\n this._dragTime = dragTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this._dragTime;\n }\n\n removeDelay() {\n this._delayTime = 0;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n removeDrag() {\n this._dragTime = 0;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n updateDuration(): void {\n if (this.checkCyclicChildren()) {\n return;\n }\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n calculateDuration() {\n this._duration = 0;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n const endTime = animation.startTime + animation.animator.duration;\n this._duration = Math.max(this._duration, endTime);\n });\n }\n\n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n checkCyclicChildren(): boolean {\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while (allChildren.length > 0) {\n const current = allChildren.pop();\n if (current == undefined) {\n continue;\n }\n if (visited.has(current)) {\n return true;\n }\n visited.add(current);\n if (current instanceof CompositeAnimation) {\n current.animations.forEach(animation => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n forceToggleLoop(loop: boolean) {\n this.loop = true;\n this.animations.forEach(animation => {\n animation.animator.loops = true;\n });\n }\n\n containsAnimation(animationInInterest: Animator): boolean {\n if (this.parent !== undefined) {\n return this.parent.containsAnimation(animationInInterest);\n }\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while (allChildren.length > 0) {\n const current = allChildren.pop();\n if (current == undefined) {\n continue;\n }\n if (current == animationInInterest) {\n return true;\n }\n if (visited.has(current)) {\n continue;\n }\n visited.add(current);\n if (current instanceof CompositeAnimation) {\n current.animations.forEach(animation => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n onEnd(callback: Function): UnSubscribe {\n this.endCallbacks.push(callback);\n return () => {\n this.endCallbacks = this.endCallbacks.filter(cb => cb != callback);\n };\n }\n\n onStart(callback: Function): UnSubscribe {\n this.startCallbacks.push(callback);\n return () => {\n this.startCallbacks = this.startCallbacks.filter(\n cb => cb != callback\n );\n };\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\n/**\n * Keyframe-based animation for a single value.\n *\n * @remarks\n * The Animation class interpolates a value through a series of keyframes over time.\n * It handles:\n * - Keyframe interpolation with binary search for efficiency\n * - Easing functions for smooth motion curves\n * - Reverse playback\n * - Looping with optional max loop count\n * - Delays before start and drag time after completion\n * - Lifecycle callbacks\n *\n * ## How It Works\n *\n * 1. Define keyframes at percentages (0.0 to 1.0) along the timeline\n * 2. Provide a callback to apply the animated value\n * 3. Provide an interpolation helper for the value type\n * 4. Call `animate(deltaTime)` each frame to progress the animation\n *\n * @typeParam T - The type of value being animated\n *\n * @example\n * Animating a number with easing\n * ```typescript\n * let opacity = 0;\n *\n * const fadeIn = new Animation(\n * [\n * { percentage: 0, value: 0 },\n * { percentage: 1, value: 1, easingFn: (t) => t * t } // Ease-in\n * ],\n * (value) => { opacity = value; },\n * numberHelperFunctions,\n * 1000 // 1 second duration\n * );\n *\n * fadeIn.start();\n *\n * // In animation loop\n * function loop(deltaTime: number) {\n * fadeIn.animate(deltaTime);\n * element.style.opacity = opacity;\n * }\n * ```\n *\n * @category Core\n */\nexport class Animation<T> implements Animator {\n private localTime: number; // local time starting from 0 up til duration\n private _duration: number;\n private keyframes: Keyframe<T>[];\n private animatableAttributeHelper: AnimatableAttributeHelper<T>;\n private applyAnimationValue: (value: T) => void;\n private easeFn: (percentage: number) => number;\n private onGoing: boolean;\n private currentKeyframeIndex: number;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private parent: AnimatorContainer | undefined;\n private delayTime: number = 0;\n private dragTime: number = 0;\n\n private reverse: boolean = false;\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n private startAfterDelayCallbacks: Function[] = [];\n\n private zeroPercentageValue: T;\n private _maxLoopCount: number | undefined;\n private _fillMode: 'none' | 'forwards' | 'backwards' | 'both' = 'none';\n\n constructor(\n keyFrames: Keyframe<T>[],\n applyAnimationValue: (value: T) => void,\n animatableAttributeHelper: AnimatableAttributeHelper<T>,\n duration: number = 1000,\n loop: boolean = false,\n parent: AnimatorContainer | undefined = undefined,\n setUpFn: Function = () => {},\n tearDownFn: Function = () => {},\n easeFn: (percentage: number) => number = linear\n ) {\n this._duration = duration;\n this.keyframes = keyFrames;\n this.animatableAttributeHelper = animatableAttributeHelper;\n this.applyAnimationValue = applyAnimationValue;\n this.easeFn = easeFn;\n this.onGoing = false;\n this.localTime = duration + 0.1;\n this.currentKeyframeIndex = 0;\n this.loop = loop;\n this.setUpFn = setUpFn;\n this.tearDownFn = tearDownFn;\n this.parent = parent;\n this.playedTime = 0;\n this.zeroPercentageValue = this.findValue(\n 0,\n keyFrames,\n animatableAttributeHelper\n );\n }\n\n toggleReverse(reverse: boolean): void {\n this.reverse = reverse;\n }\n\n start(): void {\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.onGoing = true;\n // this.applyAnimationValue(this.zeroPercentageValue);\n this.setUp();\n }\n\n stop(): void {\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.playedTime = 0;\n this.tearDown();\n }\n\n pause(): void {\n this.onGoing = false;\n }\n\n resume() {\n this.onGoing = true;\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n animate(deltaTime: number) {\n if (this.onGoing != true || this.localTime < 0) {\n return;\n }\n if (deltaTime == 0) {\n return;\n }\n this.localTime += deltaTime;\n // console.log(\"--------------------\");\n // console.log(\"local time\", this.localTime);\n // console.log(\"delta time\", deltaTime);\n if (this.localTime - deltaTime <= 0 && deltaTime > 0) {\n // console.log(\"--------------------\");\n // console.log(\"current localtime\", this.localTime);\n // console.log(\"current delta time\", deltaTime);\n // console.log(\"previous local time\", this.localTime - deltaTime);\n // console.log(\"animation start\");\n // console.log(`the animation has been played ${this.playedTime} times`);\n // console.log(`the animation is now playing for the ${this.playedTime + 1} time`);\n this.startCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n }\n if (\n this.localTime >= this.delayTime &&\n (this.localTime <=\n this.delayTime + this._duration + this.dragTime ||\n this.localTime - deltaTime <=\n this.delayTime + this._duration + this.dragTime)\n ) {\n // console.log(\"local time\", this.localTime);\n // console.log(\"duration\", this.duration);\n // console.log(\"local time would trigger end\", this.localTime >= this._duration + this.delayTime + this.dragTime);\n // console.log(\"delta time\", deltaTime);\n if (\n this.localTime - deltaTime <= this.delayTime &&\n this.delayTime !== 0 &&\n deltaTime > 0\n ) {\n this.startAfterDelayCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n this.applyAnimationValue(this.zeroPercentageValue);\n }\n let localTimePercentage =\n (this.localTime - this.delayTime) / this._duration;\n let targetPercentage = this.easeFn(localTimePercentage);\n if (localTimePercentage > 1) {\n targetPercentage = this.easeFn(1);\n }\n let value: T;\n // console.log(\"currentKeyframeIndex\", this.currentKeyframeIndex, \"length\", this.keyFrames.length);\n if (\n this.currentKeyframeIndex < this.keyframes.length &&\n this.currentKeyframeIndex >= 0 &&\n (this.reverse\n ? 1 -\n this.keyframes[this.currentKeyframeIndex]\n .percentage ==\n targetPercentage\n : this.keyframes[this.currentKeyframeIndex].percentage ==\n targetPercentage)\n ) {\n value = this.keyframes[this.currentKeyframeIndex].value;\n } else {\n value = this.findValue(\n targetPercentage,\n this.keyframes,\n this.animatableAttributeHelper\n );\n }\n if (this.reverse) {\n while (\n this.currentKeyframeIndex >= 0 &&\n 1 - this.keyframes[this.currentKeyframeIndex].percentage <=\n targetPercentage\n ) {\n this.currentKeyframeIndex -= 1;\n }\n } else {\n while (\n this.currentKeyframeIndex < this.keyframes.length &&\n this.keyframes[this.currentKeyframeIndex].percentage <=\n targetPercentage\n ) {\n this.currentKeyframeIndex += 1;\n }\n }\n this.applyAnimationValue(value);\n if (\n this.localTime >=\n this._duration + this.dragTime + this.delayTime\n ) {\n // console.log(\"animation should end\");\n this.playedTime += 1;\n this.endCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n if (\n !this.loops ||\n (this._maxLoopCount != undefined &&\n this.playedTime >= (this.maxLoopCount ?? 0))\n ) {\n // this.onGoing = false;\n // console.log(\"animation should stop after \", this.playedTime, \" loops\");\n this.stop();\n } else {\n // console.log(\"animation should restart\");\n this.onGoing = true;\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.start();\n }\n }\n // if((this.localTime >= this._duration + this.delayTime + this.dragTime) && this.loop){\n // // this.startAnimation();\n // this.localTime = 0;\n // this.onGoing = true;\n // this.currentKeyframeIndex = 0;\n // }\n }\n }\n\n findValue(\n valuePercentage: number,\n keyframes: Keyframe<T>[],\n animatableAttributeHelper: AnimatableAttributeHelper<T>\n ): T {\n if (valuePercentage > 1) {\n if (this.reverse) {\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[1],\n keyframes[0]\n );\n }\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[keyframes.length - 2],\n keyframes[keyframes.length - 1]\n );\n }\n if (valuePercentage < 0) {\n if (this.reverse) {\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[keyframes.length - 2],\n keyframes[keyframes.length - 1]\n );\n }\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[1],\n keyframes[0]\n );\n }\n let left = 0;\n let right = keyframes.length - 1;\n while (left <= right) {\n let mid = left + Math.floor((right - left) / 2);\n const midPercentage = this.reverse\n ? 1 - keyframes[mid].percentage\n : keyframes[mid].percentage;\n if (midPercentage == valuePercentage) {\n return keyframes[mid].value;\n } else if (midPercentage < valuePercentage) {\n if (this.reverse) {\n right = mid - 1;\n } else {\n left = mid + 1;\n }\n } else {\n if (this.reverse) {\n left = mid + 1;\n } else {\n right = mid - 1;\n }\n }\n }\n if (left > keyframes.length - 1) {\n // excceding the keyframes\n left = keyframes.length - 1;\n }\n const interpolateStartFrame = this.reverse\n ? {\n percentage: 1 - keyframes[left].percentage,\n value: keyframes[left].value,\n }\n : keyframes[left - 1];\n const interplateEndFrame = this.reverse\n ? {\n percentage: 1 - keyframes[left - 1].percentage,\n value: keyframes[left - 1].value,\n }\n : keyframes[left];\n // return animatableAttributeHelper.lerp(valuePercentage, keyframes[left - 1], keyframes[left]);\n return animatableAttributeHelper.lerp(\n valuePercentage,\n interpolateStartFrame,\n interplateEndFrame\n );\n }\n\n setUp(): void {\n // this.applyAnimationValue(this.keyframes[0].value);\n this.setUpFn();\n }\n\n tearDown(): void {\n this.tearDownFn();\n }\n\n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n get duration(): number {\n return this._duration + this.delayTime + this.dragTime;\n }\n\n set duration(duration: number) {\n if (duration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this.delayTime + this.dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = this._duration * scale;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if (newDuration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this.delayTime + this.dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = newDuration;\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.applyAnimationValue(this.keyframes[0].value);\n this.currentKeyframeIndex = 0;\n this.setUp();\n }\n\n wrapUp(): void {\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.currentKeyframeIndex = 0;\n }\n\n get delay(): number {\n return this.delayTime;\n }\n\n set delay(delayTime: number) {\n this.delayTime = delayTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this.dragTime;\n }\n\n set drag(dragTime: number) {\n this.dragTime = dragTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get trueDuration(): number {\n return this._duration;\n }\n\n set trueDuration(duration: number) {\n this._duration = duration;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n setParent(parent: AnimatorContainer) {\n this.parent = parent;\n }\n\n detachParent(): void {\n this.parent = undefined;\n }\n\n set keyFrames(keyFrames: Keyframe<T>[]) {\n this.keyframes = keyFrames;\n this.zeroPercentageValue = this.findValue(\n 0,\n keyFrames,\n this.animatableAttributeHelper\n );\n }\n\n get keyFrames(): Keyframe<T>[] {\n return this.keyframes;\n }\n\n get easeFunction(): (percentage: number) => number {\n return this.easeFn;\n }\n\n set easeFunction(easeFn: (percentage: number) => number) {\n this.easeFn = easeFn;\n }\n\n onEnd(callback: Function): UnSubscribe {\n this.endCallbacks.push(callback);\n return () => {\n this.endCallbacks = this.endCallbacks.filter(cb => cb != callback);\n };\n }\n\n onStart(callback: Function): UnSubscribe {\n this.startCallbacks.push(callback);\n return () => {\n this.startCallbacks = this.startCallbacks.filter(\n cb => cb != callback\n );\n };\n }\n\n onStartAfterDelay(callback: Function): UnSubscribe {\n this.startAfterDelayCallbacks.push(callback);\n return () => {\n this.startAfterDelayCallbacks =\n this.startAfterDelayCallbacks.filter(cb => cb != callback);\n };\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\nexport interface Keyframes<T> {\n keyframes: Keyframe<T>[];\n from(value: T): Keyframes<T>;\n to(value: T): Keyframes<T>;\n insertAt(percentage: number, value: T): void;\n clearFrames(): void;\n}\n\nexport class KeyFramesContiner<T> {\n private _keyframes: Keyframe<T>[];\n\n constructor() {\n this._keyframes = [];\n }\n\n get keyframes(): Keyframe<T>[] {\n return this._keyframes;\n }\n\n from(value: T): Keyframes<T> {\n if (this._keyframes.length == 0) {\n this._keyframes.push({ percentage: 0, value: value });\n } else {\n if (this._keyframes[0].percentage == 0) {\n this._keyframes[0].value = value;\n } else {\n this._keyframes.unshift({ percentage: 0, value: value });\n }\n }\n return this;\n }\n\n to(value: T): Keyframes<T> {\n if (this._keyframes.length == 0) {\n this._keyframes.push({ percentage: 1, value: value });\n } else {\n if (this._keyframes[this._keyframes.length - 1].percentage == 1) {\n this._keyframes[this._keyframes.length - 1].value = value;\n } else {\n this._keyframes.push({ percentage: 1, value: value });\n }\n }\n return this;\n }\n\n insertAt(percentage: number, value: T): void {\n this._keyframes.push({ percentage: percentage, value: value });\n }\n\n clearFrames(): void {\n this._keyframes = [];\n }\n}\n"
|
|
10
10
|
],
|
|
11
|
-
"mappings": "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",
|
|
11
|
+
"mappings": "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",
|
|
12
12
|
"debugId": "A64492CFE695240C64756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ue-too/animate",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.15.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"./package.json": "./package.json"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@ue-too/math": "^0.
|
|
23
|
+
"@ue-too/math": "^0.15.0"
|
|
24
24
|
},
|
|
25
25
|
"main": "./index.js",
|
|
26
26
|
"types": "./index.d.ts",
|