@xtia/timeline 1.0.5 → 1.0.7
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 +410 -6
- package/index.js +8 -1
- package/internal/emitters.d.ts +55 -29
- package/internal/emitters.js +241 -106
- package/internal/point.d.ts +15 -6
- package/internal/point.js +43 -0
- package/internal/range.d.ts +14 -4
- package/internal/range.js +98 -0
- package/internal/timeline.d.ts +3 -3
- package/internal/timeline.js +7 -66
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Timeline** is a general‑purpose, environment-agnostic choreography engine that lets you orchestrate any sequence of value changes; numbers, vectors, colour tokens, custom blendable objects, or arbitrary data structures.
|
|
6
6
|
|
|
7
|
+
* [API Reference](#reference)
|
|
7
8
|
|
|
8
9
|
## Basic Use:
|
|
9
10
|
|
|
@@ -33,8 +34,9 @@ timeline
|
|
|
33
34
|
);
|
|
34
35
|
|
|
35
36
|
// use an easing function
|
|
36
|
-
|
|
37
|
+
timeline
|
|
37
38
|
.end
|
|
39
|
+
.delta(500)
|
|
38
40
|
.range(3000)
|
|
39
41
|
.ease("bounce")
|
|
40
42
|
.tween("50%", "0%")
|
|
@@ -93,7 +95,7 @@ eased.listen(
|
|
|
93
95
|
const frames = eased
|
|
94
96
|
.tween(0, 30)
|
|
95
97
|
.map(Math.floor)
|
|
96
|
-
.
|
|
98
|
+
.dedupe()
|
|
97
99
|
.tap(n => console.log("Showing frame #", n))
|
|
98
100
|
.map(n => `animation-frame-${n}.png`)
|
|
99
101
|
.listen(filename => img.src = filename);
|
|
@@ -164,7 +166,6 @@ Tween emitters can interpolate numbers, arrays of numbers, strings, and objects
|
|
|
164
166
|
|
|
165
167
|
```ts
|
|
166
168
|
// tween four values in a CSS string
|
|
167
|
-
// see this live: https://codepen.io/xtaltia/pen/PwZYbKY
|
|
168
169
|
timeline
|
|
169
170
|
.range(0, 2000)
|
|
170
171
|
.ease("elastic")
|
|
@@ -175,9 +176,12 @@ timeline
|
|
|
175
176
|
timeline
|
|
176
177
|
.range(0, 2000)
|
|
177
178
|
.tween("--------", "########")
|
|
179
|
+
.dedupe()
|
|
178
180
|
.listen(v => document.title = v);
|
|
179
181
|
```
|
|
180
182
|
|
|
183
|
+
You can try out the [shadow tweening example at StackBlitz](https://stackblitz.com/edit/timeline-string-tween?file=src%2Fmain.ts)
|
|
184
|
+
|
|
181
185
|
## Autoplay and Looping Strategies
|
|
182
186
|
|
|
183
187
|
To create a Timeline that immediately starts playing, pass `true` to its constructor:
|
|
@@ -259,10 +263,12 @@ loadingTimeline
|
|
|
259
263
|
.tween("0%", "100%");
|
|
260
264
|
.listen(v => progressBar.style.width = v);
|
|
261
265
|
|
|
266
|
+
// and do something when they're loaded
|
|
262
267
|
loadingTimeline
|
|
263
268
|
.end
|
|
264
269
|
.listen(startGame);
|
|
265
270
|
|
|
271
|
+
// to drive it, just seek forward by 1 for each loaded resource
|
|
266
272
|
resourceUrls.forEach(url => {
|
|
267
273
|
preload(url).then(
|
|
268
274
|
() => loadingTimeline.currentTime++
|
|
@@ -278,7 +284,7 @@ timeline.seek(timeline.end, 400, "overshootIn");
|
|
|
278
284
|
|
|
279
285
|
## Backward-compatibility
|
|
280
286
|
|
|
281
|
-
Despite the massive overhaul, the previous API is present and expanded
|
|
287
|
+
Despite the massive overhaul, the previous API is present and expanded and upgrading to 1.0.0 should be frictionless in the vast majority of cases.
|
|
282
288
|
|
|
283
289
|
#### Breaking changes
|
|
284
290
|
|
|
@@ -287,7 +293,7 @@ Despite the massive overhaul, the previous API is present and expanded and upgr
|
|
|
287
293
|
#### Mitigation
|
|
288
294
|
|
|
289
295
|
* `timeline.tween()` now accepts TimelinePoint as a starting position, and provides an overload that replaces the `duration: number` parameter with `end: TimelinePoint`.
|
|
290
|
-
* Should you encounter a case where this change still causes issue, eg `
|
|
296
|
+
* Should you encounter a case where this change still causes issue, eg `timeline.tween(0, timeline.end / 2, ...)`, `timeline.end.position` is equivalent to the old API's `timeline.end`.
|
|
291
297
|
|
|
292
298
|
#### Enhancements (non-breaking)
|
|
293
299
|
|
|
@@ -298,4 +304,402 @@ Despite the massive overhaul, the previous API is present and expanded and upgr
|
|
|
298
304
|
|
|
299
305
|
* `timeline.position` will be replaced with `timeline.currentTime` to be consistent with other seekable concepts.
|
|
300
306
|
* `"loop"` endAction is now `"restart"` to disambiguate from new looping strategies.
|
|
301
|
-
* `timeline.step()` is redundant now that `currentTime` is writable; use `timeline.currentTime += delta` instead.
|
|
307
|
+
* `timeline.step()` is redundant now that `currentTime` is writable; use `timeline.currentTime += delta` instead.
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
## Reference
|
|
312
|
+
|
|
313
|
+
### `Timeline` class
|
|
314
|
+
|
|
315
|
+
A self-contained collection of points and ranges that trigger events as the Timeline seeks to and through them.
|
|
316
|
+
|
|
317
|
+
#### Properties
|
|
318
|
+
|
|
319
|
+
##### `currentTime: number`
|
|
320
|
+
|
|
321
|
+
Reads or sets the Timeline's current time position. Setting this property will perform a `seek()`, triggering any listener that is passed or landed on.
|
|
322
|
+
|
|
323
|
+
##### `timeScale: number`
|
|
324
|
+
|
|
325
|
+
Controls the speed at which a Timeline will progress when driven by the `play()` method (including by autoplay).
|
|
326
|
+
|
|
327
|
+
##### `isPlaying: boolean`
|
|
328
|
+
|
|
329
|
+
Returns true if the Timeline is actively being driven by the `play()` method (including by autoplay).
|
|
330
|
+
|
|
331
|
+
##### `end: `[`TimelinePoint`](#timelinepoint-interface)
|
|
332
|
+
|
|
333
|
+
Returns the **current** final point in the Timeline.
|
|
334
|
+
|
|
335
|
+
##### `start: `[`TimelinePoint`](#timelinepoint-interface)
|
|
336
|
+
|
|
337
|
+
Returns a point representing position 0.
|
|
338
|
+
|
|
339
|
+
#### Methods
|
|
340
|
+
|
|
341
|
+
##### `point(position): `[`TimelinePoint`](#timelinepoint-interface)
|
|
342
|
+
|
|
343
|
+
Returns a point that represents a specific position on the Timeline.
|
|
344
|
+
|
|
345
|
+
If `position` is greater than that Timeline's end-position, the end-position will be extended to `position`.
|
|
346
|
+
|
|
347
|
+
*Note*, for deterministic consistency, points will be triggered if a forward-moving seek lands exactly on the point's position (or passes it entirely), while a backward-moving seek will trigger points that are passed or moved from.
|
|
348
|
+
|
|
349
|
+
##### `range(start, duration): `[`TimelineRange`](#timelinerange-interface)
|
|
350
|
+
|
|
351
|
+
Returns a range that represents a section of the Timeline.
|
|
352
|
+
|
|
353
|
+
If the end of the range is beyond the Timeline's end-position, the end-position will be extended to the end of the range.
|
|
354
|
+
|
|
355
|
+
If `duration` is omitted, the range will extend from `start` to the **current** end-position of the Timeline.
|
|
356
|
+
|
|
357
|
+
If `start` is omitted, the range will start at 0 and represent the full **current** range of the Timeline.
|
|
358
|
+
|
|
359
|
+
##### `seek(toPosition): void`
|
|
360
|
+
|
|
361
|
+
Sets the Timeline's internal position (`currentTime`), triggering in chronological order listeners attached to any [`TimelinePoint`](#timelinepoint-interface) or [`TimelineRange`](#timelinerange-interface) that are passed or landed on.
|
|
362
|
+
|
|
363
|
+
##### `seek(toPosition, duration, easer?): Promise<void>`
|
|
364
|
+
|
|
365
|
+
Performs an interruptable 'smooth seek' to a specified position, lasting `duration` milliseconds, with optional easing.
|
|
366
|
+
|
|
367
|
+
Returns a Promise that will be resolved when the smooth seek is completed (or is interrupted by another seek\*).
|
|
368
|
+
|
|
369
|
+
\* Resolution on interruption is not finalised in the library's design and the effect should be considered exceptional; relying on it is not recommended. Future versions might reject the promise when its seek is interrupted.
|
|
370
|
+
|
|
371
|
+
##### `play(): void`
|
|
372
|
+
|
|
373
|
+
Begins playing through the Timeline, from its current position, at (1000 x `timeScale`) units per second, updating 60 times per second.
|
|
374
|
+
|
|
375
|
+
##### `play(fps): void`
|
|
376
|
+
|
|
377
|
+
Begins playing through the Timeline, from its current position, at (1000 x `timeScale`) units per second, updating `fps` times per second.
|
|
378
|
+
|
|
379
|
+
##### `tween<T>(start, duration, apply, from, to, easer?): `[`ChainingInterface`](#chaininginterface-interface)
|
|
380
|
+
|
|
381
|
+
Creates a [`TimelineRange`](#timelinerange-interface) and attaches a tweening listener.
|
|
382
|
+
|
|
383
|
+
Equivalent to
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
timeline
|
|
387
|
+
.range(start, duration)
|
|
388
|
+
.ease(easer)
|
|
389
|
+
.tween(from, to)
|
|
390
|
+
.listen(apply);
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Returns a [`ChainingInterface`](#chaininginterface-interface) representing the point at which the tween ends.
|
|
394
|
+
|
|
395
|
+
##### `tween<T>(start, end, apply, from, to, easer?): `[`ChainingInterface`](#chaininginterface-interface)
|
|
396
|
+
|
|
397
|
+
As above, but if the second argument is a [`TimelinePoint`](#timelinepoint-interface), it will specify when on the Timeline the tween will *end*.
|
|
398
|
+
|
|
399
|
+
##### `at(position, apply, reverse?): `[`ChainingInterface`](#chaininginterface-interface)
|
|
400
|
+
|
|
401
|
+
Creates a [`TimelinePoint`](#timelinepoint-interface) and attaches a listener that will trigger when the Timeline seeks past or to that point.
|
|
402
|
+
|
|
403
|
+
If `reverse` is a function, that will be called instead of `apply` when the seek that triggered the event was moving backwards. If `reverse` is `true`, `apply` will be called regardless of which direction the seek moved. If `reverse` is false or omitted, this listener will ignore backward-moving seeks.
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
### `TimelinePoint` interface
|
|
409
|
+
|
|
410
|
+
Represents a single point on a [`Timeline`](#timeline-class).
|
|
411
|
+
|
|
412
|
+
##### Inherits [`Emitter<PointEvent>`](#emittert-interface)
|
|
413
|
+
|
|
414
|
+
Listeners will be invoked with a [`PointEvent`](#pointevent-interface) when a seek passes or lands on the point.
|
|
415
|
+
|
|
416
|
+
*Note*, during a point event, the parent Timeline's `currentTime` property will return that point's position, even if the Timeline is configured with a [*wrap* end action](#autoplay-and-looping-strategies) and its true position is beyond its end. For deterministic consistency, ranges will emit values for the point's position before the point emits.
|
|
417
|
+
|
|
418
|
+
#### Properties
|
|
419
|
+
|
|
420
|
+
##### `position: number`
|
|
421
|
+
|
|
422
|
+
This point's position on the Timeline.
|
|
423
|
+
|
|
424
|
+
#### Methods
|
|
425
|
+
|
|
426
|
+
##### `range(duration): TimelineRange`
|
|
427
|
+
|
|
428
|
+
Creates a [`TimelineRange`](#timelinerange-interface) on the Timeline to which the point belongs, of the specified duration.
|
|
429
|
+
|
|
430
|
+
##### `to(endPoint): TimelineRange`
|
|
431
|
+
|
|
432
|
+
Creates a [`TimelineRange`](#timelinerange-interface) on the Timeline to which the point belongs, ending at the specified point.
|
|
433
|
+
|
|
434
|
+
##### `delta(timeOffset): TimelinePoint`
|
|
435
|
+
|
|
436
|
+
Creates a `TimelinePoint` at an offset from the this point.
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
### `PointEvent` interface
|
|
442
|
+
|
|
443
|
+
Provides information relevant to [`TimelinePoint`](#timelinepoint-interface) events.
|
|
444
|
+
|
|
445
|
+
#### Properties
|
|
446
|
+
|
|
447
|
+
##### `direction: -1 | 1`
|
|
448
|
+
|
|
449
|
+
Provides the direction of the seek that triggered a point event. `direction === 1` indicates that the seek moved forward and `direction === -1` indicates that the seek was moving backwards.
|
|
450
|
+
|
|
451
|
+
Allows point listeners to undo effects when the Timeline is reversed.
|
|
452
|
+
|
|
453
|
+
```ts
|
|
454
|
+
timeline
|
|
455
|
+
.point(4000)
|
|
456
|
+
.listen(
|
|
457
|
+
event => element.classList.toggle(
|
|
458
|
+
"visible",
|
|
459
|
+
event.direction > 0
|
|
460
|
+
)
|
|
461
|
+
);
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
### `TimelineRange` interface
|
|
468
|
+
|
|
469
|
+
Represents a fixed-length, fixed position section of a [`Timeline`](#timeline-class).
|
|
470
|
+
|
|
471
|
+
##### Inherits [`RangeProgression`](#rangeprogression-interface)
|
|
472
|
+
|
|
473
|
+
Emits a normalised progression (0..1) of the range when the parent Timeline seeks over or into it.
|
|
474
|
+
|
|
475
|
+
#### Properties
|
|
476
|
+
|
|
477
|
+
##### `start: `[`TimelinePoint`](#timelinepoint-interface)
|
|
478
|
+
|
|
479
|
+
The point on the Timeline at which this range starts.
|
|
480
|
+
|
|
481
|
+
##### `end: `[`TimelinePoint`](#timelinepoint-interface)
|
|
482
|
+
|
|
483
|
+
The point on the Timeline at which this range ends.
|
|
484
|
+
|
|
485
|
+
##### `duration: number`
|
|
486
|
+
|
|
487
|
+
The length of the range.
|
|
488
|
+
|
|
489
|
+
#### Methods
|
|
490
|
+
|
|
491
|
+
##### `bisect(position?): [TimelineRange, TimelineRange]`
|
|
492
|
+
|
|
493
|
+
Creates two ranges representing two distinct sections of the parent. `position` is relative to the parent's start.
|
|
494
|
+
|
|
495
|
+
##### `spread(count): `[`TimelinePoint`](#timelinepoint-interface)[]
|
|
496
|
+
|
|
497
|
+
Creates and returns `count` points spread evenly over the range.
|
|
498
|
+
|
|
499
|
+
##### `play(easer?): Promise<void>`
|
|
500
|
+
|
|
501
|
+
Instructs the Timeline to which this range belongs to play through the represented range. This playthrough counts as a smooth seek for seek interruption purposes.
|
|
502
|
+
|
|
503
|
+
Returns a Promise that will be resolved when the range playthrough completes.
|
|
504
|
+
|
|
505
|
+
##### `grow(delta, anchor?): TimelineRange`
|
|
506
|
+
|
|
507
|
+
Creates a new range on the parent Timeline. The location and duration of the new range are copied from this range and grown from an anchor point, specified as a normalised (0..1) progression of the parent range.
|
|
508
|
+
|
|
509
|
+
##### `grow(delta, anchor?): TimelineRange`
|
|
510
|
+
|
|
511
|
+
Creates a new range on the parent Timeline. The location and duration of the new range are copied from this range and scaled multiplicatively from an anchor point, specified as a normalised (0..1) progression of the parent range.
|
|
512
|
+
|
|
513
|
+
##### `contains(point)`
|
|
514
|
+
|
|
515
|
+
Returns true if the given [`TimelinePoint`](#timelinepoint-interface) sits within this range.
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
### `RangeProgression` interface
|
|
521
|
+
|
|
522
|
+
Represents a step in an immutable [`TimelineRange`](#timelinerange-interface) event transformation pipeline.
|
|
523
|
+
|
|
524
|
+
##### Inherits [`Emitter<number>`](#emittert-interface)
|
|
525
|
+
|
|
526
|
+
Listeners will be invoked when a seek passes or lands within a range.
|
|
527
|
+
|
|
528
|
+
#### Methods
|
|
529
|
+
|
|
530
|
+
##### `ease(easer?): RangeProgression`
|
|
531
|
+
|
|
532
|
+
Creates an emitter that applies an easing function to parent emissions.
|
|
533
|
+
|
|
534
|
+
##### `tween<T>(from, to): `[`Emitter<T>`](#emittert-interface)
|
|
535
|
+
|
|
536
|
+
Creates an emitter blends two values, biased by progression emitted by the parent.
|
|
537
|
+
|
|
538
|
+
`T` may be `string`, `number`, `number[]` or an object type that includes
|
|
539
|
+
|
|
540
|
+
```ts
|
|
541
|
+
blend(from: this, to: this, progress: number): this
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
##### `snap(steps): RangeProgression`
|
|
545
|
+
|
|
546
|
+
Creates an emitter that quantises progression emitted by the parent to the nearest of `steps` discrete values.
|
|
547
|
+
|
|
548
|
+
##### `threshold(threshold): RangeProgression`
|
|
549
|
+
|
|
550
|
+
Creates an emitter that emits 0 when the parent emits a value below `threshold` and 1 when a parent emission is equal to or greater than `threshold`.
|
|
551
|
+
|
|
552
|
+
```ts
|
|
553
|
+
emittedValue = parentEmission < threshold ? 0 : 1
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
##### `clamp(min?, max?): RangeProgression`
|
|
557
|
+
|
|
558
|
+
Creates an emitter that clamps progression between `min` and `max`.
|
|
559
|
+
|
|
560
|
+
##### `repeat(count): RangeProgression`
|
|
561
|
+
|
|
562
|
+
Creates an emitter that multiplies progression and wraps at 1, thereby mapping to a repeating scale.
|
|
563
|
+
|
|
564
|
+
##### `tap(cb): RangeProgression`
|
|
565
|
+
|
|
566
|
+
Creates an emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
|
|
567
|
+
|
|
568
|
+
##### `filter(check: (value) => boolean): RangeProgression`
|
|
569
|
+
|
|
570
|
+
Creates an emitter that selectively discards parent emissions.
|
|
571
|
+
|
|
572
|
+
If `check(value)` returns true, the value will be emitted.
|
|
573
|
+
|
|
574
|
+
##### `dedupe(): RangeProgression`
|
|
575
|
+
|
|
576
|
+
Creates an emitter that discards emitted values that are the same as the last value emitted by the new emitter
|
|
577
|
+
|
|
578
|
+
##### `offset(delta): RangeProgression`
|
|
579
|
+
|
|
580
|
+
Creates an emitter that offsets its parent's values by the given delta, wrapping at 1
|
|
581
|
+
|
|
582
|
+
##### `fork(cb: (branch) => void): RangeProgression`
|
|
583
|
+
|
|
584
|
+
Immediately invokes `cb` with this emitter and returns this emitter for further chaining.
|
|
585
|
+
|
|
586
|
+
Allows branching without breaking a composition chain, eg:
|
|
587
|
+
|
|
588
|
+
```ts
|
|
589
|
+
range
|
|
590
|
+
.tween("0%", "100%")
|
|
591
|
+
.fork(branch => {
|
|
592
|
+
branch
|
|
593
|
+
.map(s => `Loading: ${s}`)
|
|
594
|
+
.listen(s => document.title = s)
|
|
595
|
+
})
|
|
596
|
+
.listen(v => progressBar.style.width = v);
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
### `Emitter<T>` interface
|
|
603
|
+
|
|
604
|
+
#### Methods
|
|
605
|
+
|
|
606
|
+
##### `listen(handler: Handler<T>): UnsubscribeFunc`
|
|
607
|
+
|
|
608
|
+
Attaches a handler to the emitter and returns a function that will unsubscribe the handler.
|
|
609
|
+
|
|
610
|
+
##### `map<R>(mapFunc: (value: T) => R): Emitter<R>`
|
|
611
|
+
|
|
612
|
+
Creates an emitter that performs an arbitrary transformation.
|
|
613
|
+
|
|
614
|
+
##### `filter(check: (value: T) => boolean): Emitter<T>`
|
|
615
|
+
|
|
616
|
+
Creates an emitter that selectively discards parent emissions.
|
|
617
|
+
|
|
618
|
+
If `check(value)` returns true, the value will be emitted.
|
|
619
|
+
|
|
620
|
+
##### `dedupe(compare?: (a: T, b: T) => boolean): Emitter<T>`
|
|
621
|
+
|
|
622
|
+
Creates an emitter that discards emitted values that are the same as the last value emitted by the new emitter
|
|
623
|
+
|
|
624
|
+
##### `tap(cb: Handler<T>): Emitter<T>`
|
|
625
|
+
|
|
626
|
+
Creates an emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
|
|
627
|
+
|
|
628
|
+
##### `fork(cb: (branch: Emitter<T>) => void): Emitter<T>`
|
|
629
|
+
|
|
630
|
+
Immediately invokes `cb` with this emitter and returns this emitter for further chaining.
|
|
631
|
+
|
|
632
|
+
Allows branching without breaking a composition chain, eg:
|
|
633
|
+
|
|
634
|
+
```ts
|
|
635
|
+
range
|
|
636
|
+
.tween("0%", "100%")
|
|
637
|
+
.fork(branch => {
|
|
638
|
+
branch
|
|
639
|
+
.map(s => `Loading: ${s}`)
|
|
640
|
+
.listen(s => document.title = s)
|
|
641
|
+
})
|
|
642
|
+
.listen(v => progressBar.style.width = v);
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
### `animate(duration)` function
|
|
649
|
+
|
|
650
|
+
Creates and returns a [`TimelineRange`](#timelinerange-interface) that will automatically play over `duration` milliseconds.
|
|
651
|
+
|
|
652
|
+
### `ChainingInterface` interface
|
|
653
|
+
|
|
654
|
+
Conveys composable sequential tweens and events with the simplified API. Each instance represents a specific point on the parent Timeline.
|
|
655
|
+
|
|
656
|
+
```ts
|
|
657
|
+
timeline
|
|
658
|
+
.tween(0, 1000, doThing, 0, 100)
|
|
659
|
+
.thenWait(500)
|
|
660
|
+
.then(doOtherThing)
|
|
661
|
+
.thenWait(250)
|
|
662
|
+
.thenTween(2000, dothing, 100, 0);
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
#### Properties
|
|
666
|
+
|
|
667
|
+
##### `end: `[`TimelinePoint`](#timelinepoint-interface)
|
|
668
|
+
|
|
669
|
+
The point on the Timeline at which the effect of the previous chained call ends.
|
|
670
|
+
|
|
671
|
+
#### Methods
|
|
672
|
+
|
|
673
|
+
##### `thenTween(duration, apply, from, to, easer): ChainingInterface`
|
|
674
|
+
|
|
675
|
+
Adds a tween, beginning at the point the interface represents. Returns a new `ChainingInterface` representing the end of the new tween.
|
|
676
|
+
|
|
677
|
+
##### `then(action: () => void): ChainingInterface`
|
|
678
|
+
|
|
679
|
+
Adds a point event at the point the interface represents.
|
|
680
|
+
|
|
681
|
+
##### `thenWait(duration): ChainingInterface`
|
|
682
|
+
|
|
683
|
+
Creates a new `ChainingInterface` by offsetting the parent by `duration`.
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
### `easers` const
|
|
688
|
+
|
|
689
|
+
The following easers are provided:
|
|
690
|
+
|
|
691
|
+
`linear`, `easeIn`, `easeIn4`, `easeOut`, `easeOut4`, `circleIn`, `circleIn4`, `circleOut`, `circleOut4`, `easeInOut`, `elastic`, `overshootIn`, `sine`, `invert`, `bounce`, `noise`, `pingpong`
|
|
692
|
+
|
|
693
|
+
Methods that accept an easing function accept both `(progress: number) => number` and any of the names above.
|
|
694
|
+
|
|
695
|
+
```ts
|
|
696
|
+
timeline
|
|
697
|
+
.tween(s, e, a, f, t, v => Math.sqrt(v))
|
|
698
|
+
.thenTween(s, e, a, f, t, c, "elastic");
|
|
699
|
+
|
|
700
|
+
timeline
|
|
701
|
+
.range(0, 1000)
|
|
702
|
+
.ease("circleOut")
|
|
703
|
+
.ease(easers.easeIn)
|
|
704
|
+
// ...
|
|
705
|
+
```
|
package/index.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.easers = exports.animate = exports.Timeline = void 0;
|
|
3
|
+
exports.easers = exports.RangeProgression = exports.Emitter = exports.TimelineRange = exports.TimelinePoint = exports.animate = exports.Timeline = void 0;
|
|
4
4
|
var timeline_1 = require("./internal/timeline");
|
|
5
5
|
Object.defineProperty(exports, "Timeline", { enumerable: true, get: function () { return timeline_1.Timeline; } });
|
|
6
6
|
Object.defineProperty(exports, "animate", { enumerable: true, get: function () { return timeline_1.animate; } });
|
|
7
|
+
var point_1 = require("./internal/point");
|
|
8
|
+
Object.defineProperty(exports, "TimelinePoint", { enumerable: true, get: function () { return point_1.TimelinePoint; } });
|
|
9
|
+
var range_1 = require("./internal/range");
|
|
10
|
+
Object.defineProperty(exports, "TimelineRange", { enumerable: true, get: function () { return range_1.TimelineRange; } });
|
|
11
|
+
var emitters_1 = require("./internal/emitters");
|
|
12
|
+
Object.defineProperty(exports, "Emitter", { enumerable: true, get: function () { return emitters_1.Emitter; } });
|
|
13
|
+
Object.defineProperty(exports, "RangeProgression", { enumerable: true, get: function () { return emitters_1.RangeProgression; } });
|
|
7
14
|
var easing_1 = require("./internal/easing");
|
|
8
15
|
Object.defineProperty(exports, "easers", { enumerable: true, get: function () { return easing_1.easers; } });
|
package/internal/emitters.d.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { Easer, easers } from "./easing";
|
|
2
|
-
import {
|
|
3
|
-
/** @internal */
|
|
4
|
-
export declare function createEmitter<T>(listen: ListenFunc<T>): Emitter<T>;
|
|
5
|
-
/** @internal */
|
|
6
|
-
export declare function createEmitter<T, API extends object>(onListen: ListenFunc<T>, api: Omit<API, keyof Emitter<T>>): Emitter<T> & API;
|
|
7
|
-
/** @internal */
|
|
8
|
-
export declare function createProgressEmitter<API extends object>(onListen: ListenFunc<number>, api: Omit<API, keyof RangeProgression>): RangeProgression & API;
|
|
9
|
-
/** @internal */
|
|
10
|
-
export declare function createProgressEmitter(onListen: ListenFunc<number>): RangeProgression;
|
|
2
|
+
import { Tweenable } from "./tween";
|
|
11
3
|
type Handler<T> = (value: T) => void;
|
|
12
|
-
type ListenFunc<T> = (handler: Handler<T>) => UnsubscribeFunc;
|
|
4
|
+
export type ListenFunc<T> = (handler: Handler<T>) => UnsubscribeFunc;
|
|
13
5
|
export type UnsubscribeFunc = () => void;
|
|
14
|
-
export
|
|
6
|
+
export declare class Emitter<T> {
|
|
7
|
+
protected onListen: ListenFunc<T>;
|
|
8
|
+
protected constructor(onListen: ListenFunc<T>);
|
|
9
|
+
/**
|
|
10
|
+
* Used by tap() to create a clone of an Emitter with a redirected onListen
|
|
11
|
+
* Should be overridden in all Emitter subclasses
|
|
12
|
+
* @see {@link TimelineRange.redirect}
|
|
13
|
+
* @param listen
|
|
14
|
+
* @returns {this}
|
|
15
|
+
*/
|
|
16
|
+
protected redirect: (listen: ListenFunc<T>) => Emitter<T>;
|
|
15
17
|
/**
|
|
16
18
|
* Registers a function to receive emitted values
|
|
17
19
|
* @param handler
|
|
@@ -37,7 +39,7 @@ export interface Emitter<T> {
|
|
|
37
39
|
* If no `compare` function is provided, values will be compared via `===`
|
|
38
40
|
* @returns Listenable: emits non-repeating values
|
|
39
41
|
*/
|
|
40
|
-
|
|
42
|
+
dedupe(compare?: (a: T, b: T) => boolean): Emitter<T>;
|
|
41
43
|
/**
|
|
42
44
|
* Creates a chainable emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
|
|
43
45
|
*
|
|
@@ -49,9 +51,29 @@ export interface Emitter<T> {
|
|
|
49
51
|
* @param cb A function to be called as a side effect for each value emitted by the parent emitter.
|
|
50
52
|
* @returns A new emitter that forwards all values from the parent, invoking `cb` as a side effect.
|
|
51
53
|
*/
|
|
52
|
-
tap(cb: Handler<T>):
|
|
54
|
+
tap(cb: Handler<T>): this;
|
|
55
|
+
/**
|
|
56
|
+
* Immediately passes this emitter to a callback and returns this emitter
|
|
57
|
+
*
|
|
58
|
+
* Allows branching without breaking a composition chain
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* range
|
|
63
|
+
* .tween("0%", "100%")
|
|
64
|
+
* .fork(branch => {
|
|
65
|
+
* branch
|
|
66
|
+
* .map(s => `Loading: ${s}`)
|
|
67
|
+
* .listen(s => document.title = s)
|
|
68
|
+
* })
|
|
69
|
+
* .listen(v => progressBar.style.width = v);
|
|
70
|
+
* ```
|
|
71
|
+
* @param cb
|
|
72
|
+
*/
|
|
73
|
+
fork(cb: (branch: this) => void): this;
|
|
53
74
|
}
|
|
54
|
-
export
|
|
75
|
+
export declare class RangeProgression extends Emitter<number> {
|
|
76
|
+
protected redirect: (listen: ListenFunc<number>) => RangeProgression;
|
|
55
77
|
/**
|
|
56
78
|
* Creates a chainable progress emitter that applies an easing function to its parent's emitted values
|
|
57
79
|
*
|
|
@@ -59,6 +81,7 @@ export interface RangeProgression extends Emitter<number> {
|
|
|
59
81
|
* @returns Listenable: emits eased progression values
|
|
60
82
|
*/
|
|
61
83
|
ease(easer?: Easer | keyof typeof easers): RangeProgression;
|
|
84
|
+
ease(easer?: undefined): RangeProgression;
|
|
62
85
|
/**
|
|
63
86
|
* Creates a chainable emitter that interpolates two given values by progression emitted by its parent
|
|
64
87
|
*
|
|
@@ -99,7 +122,7 @@ export interface RangeProgression extends Emitter<number> {
|
|
|
99
122
|
* @param to Value to interpolate to
|
|
100
123
|
* @returns Listenable: emits interpolated values
|
|
101
124
|
*/
|
|
102
|
-
tween<T extends
|
|
125
|
+
tween<T extends Tweenable>(from: T, to: T): Emitter<T>;
|
|
103
126
|
/**
|
|
104
127
|
* Creates a chainable progress emitter that quantises progress, as emitted by its parent, to the nearest of `steps` discrete values.
|
|
105
128
|
*
|
|
@@ -124,21 +147,23 @@ export interface RangeProgression extends Emitter<number> {
|
|
|
124
147
|
clamp(min?: number, max?: number): RangeProgression;
|
|
125
148
|
/**
|
|
126
149
|
* Creates a chainable progress emitter that maps incoming values to a repeating linear scale
|
|
127
|
-
* @param count Number of repetitions
|
|
128
|
-
*/
|
|
129
|
-
repeat(count: number): RangeProgression;
|
|
130
|
-
/**
|
|
131
|
-
* Creates a chainable progress emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
|
|
132
|
-
*
|
|
133
|
-
* The callback `cb` is called exactly once per parent emission, regardless of how many listeners are attached to the returned emitter.
|
|
134
|
-
* All listeners attached to the returned emitter receive the same values as the parent emitter.
|
|
135
150
|
*
|
|
136
|
-
*
|
|
151
|
+
* ```plain
|
|
152
|
+
* count=2
|
|
153
|
+
* 1
|
|
154
|
+
* | / /
|
|
155
|
+
* o| / /
|
|
156
|
+
* u| / /
|
|
157
|
+
* t| / /
|
|
158
|
+
* | / /
|
|
159
|
+
* |/_____/_____
|
|
160
|
+
* 0 in 1
|
|
161
|
+
* ```
|
|
137
162
|
*
|
|
138
|
-
* @param
|
|
139
|
-
* @returns
|
|
163
|
+
* @param count Number of repetitions
|
|
164
|
+
* @returns Listenable: emits scaled and repeating values
|
|
140
165
|
*/
|
|
141
|
-
|
|
166
|
+
repeat(count: number): RangeProgression;
|
|
142
167
|
/**
|
|
143
168
|
* Creates a chainable progress emitter that selectively forwards emissions along the chain
|
|
144
169
|
* @param check Function that takes an emitted value and returns true if the emission should be forwarded along the chain
|
|
@@ -149,9 +174,9 @@ export interface RangeProgression extends Emitter<number> {
|
|
|
149
174
|
* Creates a chainable progress emitter that discards emitted values that are the same as the last value emitted by the new emitter
|
|
150
175
|
* @returns Listenable: emits non-repeating values
|
|
151
176
|
*/
|
|
152
|
-
|
|
177
|
+
dedupe(): RangeProgression;
|
|
153
178
|
/**
|
|
154
|
-
* Creates a chainable progress emitter that offsets its parent's values by the given delta, wrapping
|
|
179
|
+
* Creates a chainable progress emitter that offsets its parent's values by the given delta, wrapping at 1
|
|
155
180
|
*
|
|
156
181
|
* ```plain
|
|
157
182
|
* 1
|
|
@@ -165,6 +190,7 @@ export interface RangeProgression extends Emitter<number> {
|
|
|
165
190
|
* ```
|
|
166
191
|
*
|
|
167
192
|
* @param delta
|
|
193
|
+
* @returns Listenable: emits offset values
|
|
168
194
|
*/
|
|
169
195
|
offset(delta: number): RangeProgression;
|
|
170
196
|
}
|