@xtia/timeline 0.2.5 → 1.0.1

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.
Files changed (4) hide show
  1. package/README.md +298 -0
  2. package/index.d.ts +199 -150
  3. package/index.js +568 -228
  4. package/package.json +19 -13
package/index.d.ts CHANGED
@@ -1,195 +1,251 @@
1
- type ApplyTweenFunc = (v: number) => void;
2
- type EaseFunc = (v: number) => number;
3
- interface TweenData {
4
- time: number;
5
- duration: number;
6
- startValue: NumberOrNumberFunction;
7
- endValue: NumberOrNumberFunction;
8
- apply: ApplyTweenFunc;
9
- ease?: EaseFunc;
10
- }
11
- type NumberOrNumberFunction = number | (() => number);
12
- type EndAction = "continue" | "pause" | "loop";
13
- interface TimelineChain {
1
+ type PointEvent = {
2
+ direction: -1 | 1;
3
+ };
4
+ declare const EndAction: {
5
+ readonly pause: 0;
6
+ readonly continue: 1;
7
+ readonly wrap: 2;
8
+ readonly restart: 3;
9
+ };
10
+ /**
11
+ * Creates an autoplaying Timeline and returns a range from it
12
+ * @param duration
13
+ * @returns Object representing a range on a single-use, autoplaying Timeline
14
+ */
15
+ export declare function animate(duration: number): TimelineRange;
16
+ export declare class Timeline {
14
17
  /**
15
- * Add a callback to run at the end of the previous item in a chain, offset by the Timeline's current position
16
- * @param time Offset, time at which this event will be triggered
17
- * @param apply Called when a forward seek targets or passes this event's time.
18
- * @param revert Called when a backward seek passes this event's time. Default is no action
18
+ * Multiplies the speed at which `play()` progresses through the Timeline
19
+ *
20
+ * A value of 2 would double progression speed while .25 would slow it to a quarter
19
21
  */
20
- then(apply: () => void, revert?: () => void): TimelineChain;
22
+ timeScale: number;
23
+ get currentTime(): number;
24
+ set currentTime(v: number);
25
+ get isPlaying(): boolean;
26
+ get end(): TimelinePoint;
27
+ private _currentTime;
28
+ private _endPosition;
29
+ private interval;
30
+ private points;
31
+ private endAction;
32
+ private ranges;
33
+ private currentSortDirection;
34
+ private smoothSeeker;
35
+ private seeking;
36
+ readonly start: TimelinePoint;
37
+ private positionHandlers;
38
+ constructor();
21
39
  /**
22
- * Add a callback to run at the end of the previous item in a chain, offset by the Timeline's current position
23
- * @param time Offset, time at which this event will be triggered
24
- * @param apply Called when a forward seek targets or passes this event's time.
25
- * @param applyOnReverse Pass true to call `apply` regardless of direction of traversal, or false to specify no reversion action
40
+ * @param autoplay Pass `true` to begin playing at (1000 x this.timeScale) units per second immediately on creation
26
41
  */
27
- then(apply: () => void, applyOnReverse: boolean): TimelineChain;
42
+ constructor(autoplay: boolean);
28
43
  /**
29
- * Add a tween to this Timeline, starting at the end of the previous item in a chain
30
- * @param duration Duration of tween
31
- * @param apply Function called per frame, passed a value between `from` and `to` (with possible overshoot depending on easer)
32
- * @param from Initial (pre-start) value to pass to `apply()`. If passed a function it will be called for each frame calculation. (default 0)
33
- * @param to Final (post-end) value to pass to `apply()`. If passed a function it will be called for each frame calculation. (default 1)
34
- * @param ease Function that takes progression (generally between 0 and 1) and returns modified progression
44
+ * Creates a Timeline that begins playing immediately at (1000 x this.timeScale) units per second
45
+ * @param autoplayFps Specifies frames per second
35
46
  */
36
- thenTween(duration: number, apply: ApplyTweenFunc, from?: NumberOrNumberFunction, to?: NumberOrNumberFunction, ease?: EaseFunc): TimelineChain;
47
+ constructor(autoplayFps: number);
37
48
  /**
38
- * Ensures end time extends to (at least) the specified time past the end of the previous item in a chain
39
- * @param duration
49
+ * @param autoplay If this argument is `true`, the Timeline will begin playing immediately on creation. If the argument is a number, the Timeline will begin playing at the specified frames per second
50
+ * @param endAction Specifies what should happen when the final position is passed by `play()`/`autoplay`
51
+ *
52
+ * `"pause"`: **(default)** the Timeline will pause at its final position
53
+ * `"continue"`: The Timeline will continue progressing beyond its final position
54
+ * `"restart"`: The Timeline will seek back to 0 then forward to account for any overshoot and continue progressing
55
+ * `"wrap"`: The Timeline's position will continue to increase beyond the final position, but Points and Ranges will be activated as if looping
56
+ * `{restartAt: number}`: Like `"restart"` but seeking back to `restartAt` instead of 0
57
+ * `{wrapAt: number}`: Like `"wrap"` but as if restarting at `wrapAt` instead of 0
40
58
  */
41
- thenWait(duration: number): TimelineChain;
42
- }
43
- export declare class Timeline {
44
- private tweens;
45
- private events;
46
- private _position;
47
- private _end;
48
- private seeking;
49
- private playInterval;
50
- private currentSortDirection;
51
- private smoothSeekTimeline?;
52
- pauseAtEnd: boolean;
59
+ constructor(autoplay: boolean | number, endAction: {
60
+ wrapAt: number;
61
+ } | {
62
+ restartAt: number;
63
+ } | keyof typeof EndAction);
53
64
  /**
54
- * @property Sets a time at which to rewind back to 0. If `true`, looping will occur after the final tween or event.
65
+ * @deprecated "loop" endAction will be removed; use "restart" or `{restartAt: 0}` (disambiguates new looping strategies)
55
66
  */
56
- loop: number | boolean;
67
+ constructor(autoplay: boolean | number, endAction: "loop");
57
68
  /**
58
- * @property Time delta multiplier to change speed. Affects `step()` and `play()`
69
+ * Defines a single point on the Timeline
70
+ *
71
+ * @param position
72
+ * @returns A point on the Timeline as specified
73
+ *
74
+ * Listenable: this point will emit a PointEvent whenever a `seek()` reaches or passes it
59
75
  */
60
- timeScale: number;
76
+ point(position: number): TimelinePoint;
61
77
  /**
62
- * @param autoPlay Pass true to autoplay at 60 FPS
63
- * @param atEnd Choose what happens when the Timeline seeks beyond its final frame. Default is "pause"
78
+ * Defines a range on this Timeline
79
+ *
80
+ * @param start The position on this Timeline at which the range starts
81
+ * @param duration Length of the resulting range - if omitted, the range will end at the Timeline's **current** final position
82
+ * @returns A range on the Timeline
83
+ *
84
+ * Listenable: this range will emit a progression value (0..1) when a `seek()` passes or intersects it
64
85
  */
65
- constructor(autoPlay?: boolean, atEnd?: EndAction);
86
+ range(start: number | TimelinePoint, duration?: number): TimelineRange;
66
87
  /**
67
- * @param fps Pass a number, as frames per second, to autoplay at the specified frame rate.
68
- * @param atEnd Choose what happens when the Timeline seeks beyond its final frame. Default is "pause"
88
+ * Creates an observable range from position 0 to the Timeline's **current** final position
69
89
  */
70
- constructor(fps?: number | boolean, atEnd?: EndAction);
71
- get position(): number;
90
+ range(): TimelineRange;
91
+ private getWrappedPosition;
92
+ /**
93
+ * Seeks the Timeline to a specified position, triggering in order any point and range subscriptions between its current and new positions
94
+ * @param toPosition
95
+ */
96
+ seek(toPosition: number | TimelinePoint): void;
97
+ /**
98
+ * Smooth-seeks to a specified position
99
+ *
100
+ * Aborts and replaces any on-going smooth-seek process on this Timeline
101
+ * @param toPosition
102
+ * @param duration Duration of the smooth-seek process in milliseconds
103
+ * @param easer Optional easing function for the smooth-seek process
104
+ * @returns A promise, resolved when the smooth-seek process finishes
105
+ */
106
+ seek(toPosition: number | TimelinePoint, duration: number, easer?: Easer | keyof typeof easers): Promise<void>;
107
+ private seekDirect;
108
+ private seekPoints;
109
+ private seekRanges;
110
+ private sortEntries;
72
111
  /**
73
- * @property The final position at which an event or tween exists on this Timeline
112
+ * Starts progression of the Timeline from its current position at (1000 x this.timeScale) units per second
74
113
  */
75
- get end(): number;
114
+ play(): void;
115
+ play(fps: number): void;
116
+ pause(): void;
76
117
  /**
77
- * Add a tween to this Timeline
78
- * @param startTime Position at which tween starts
79
- * @param duration Duration of tween
80
- * @param apply Function called per frame, passed a value between `from` and `to` (with possible overshoot depending on easer)
81
- * @param from Initial (pre-start) value to pass to `apply()`. If passed a function it will be called for each frame calculation. (default 0)
82
- * @param to Final (post-end) value to pass to `apply()`. If passed a function it will be called for each frame calculation. (default 1)
83
- * @param ease Function that takes progression (generally between 0 and 1) and returns modified progression
84
- * @returns A chaining interface for the time at which the tween ends
118
+ * Progresses the Timeline by 1 unit
119
+ * @param delta
120
+ * @deprecated Use timeline.position++
85
121
  */
86
- tween(startTime: number, duration: number, apply: ApplyTweenFunc, from?: NumberOrNumberFunction, to?: NumberOrNumberFunction, ease?: EaseFunc): TimelineChain;
122
+ step(): void;
87
123
  /**
88
- * Add a tween to this Timeline
89
- * @param tween Object describing the tween
90
- * @returns A chaining interface for the time at which the tween ends
124
+ * Progresses the Timeline by a given delta
125
+ * @param delta
126
+ * @deprecated Use timeline.position += n
91
127
  */
92
- tween(tween: TweenData): TimelineChain;
128
+ step(delta: number): void;
129
+ tween<T extends Tweenable>(start: number | TimelinePoint, duration: number, apply: (v: T) => void, from: T, to: T, easer?: Easer): ChainingInterface;
130
+ tween<T extends Tweenable>(start: number | TimelinePoint, end: TimelinePoint, // ease migration for tl.tween(0, tl.end, ...)
131
+ apply: (v: T) => void, from: T, to: T, easer?: Easer): ChainingInterface;
132
+ at(position: number | TimelinePoint, action?: () => void, reverse?: boolean | (() => void)): ChainingInterface;
133
+ private createChainingInterface;
93
134
  /**
94
- * Add a callback to run at a specified time
95
- * @param time Time at which this event will be triggered
96
- * @param apply Called when a forward seek targets or passes this event's time
97
- * @param applyOnReverse Called when a backward seek passes this event's time. Default is no action
98
- * @returns A chaining interface for the specified time
135
+ * @deprecated use `timeline.currentTime`
99
136
  */
100
- at(time: number, apply: () => void, applyOnReverse?: () => void): TimelineChain;
137
+ get position(): number;
138
+ }
139
+ interface ChainingInterface {
140
+ thenTween(duration: number, apply: (v: number) => void, from?: number, to?: number, easer?: Easer): ChainingInterface;
141
+ then(action: () => void): ChainingInterface;
142
+ thenWait(duration: number): ChainingInterface;
143
+ readonly end: TimelinePoint;
144
+ }
145
+ export interface TimelineRange extends RangeProgression {
101
146
  /**
102
- * Add a callback to run at a specified time
103
- * @param time Time at which this event will be triggered
104
- * @param apply Called when a forward seek targets or passes this event's time
105
- * @param applyOnReverse Pass true to call `apply` regardless of direction of traversal, or false to specify no reversion action
106
- * @returns A chaining interface for the specified time
147
+ * Creates two ranges by seperating one at a given point
148
+ * @param position Point of separation, relative to the range's start - if omitted, the range will be separated halfway
149
+ *
150
+ * Must be greater than 0 and less than the range's duration
107
151
  */
108
- at(time: number, apply: () => void, applyOnReverse: boolean): TimelineChain;
152
+ bisect(position?: number): [TimelineRange, TimelineRange];
109
153
  /**
110
- * Ensures end time extends to (at least) the specified time
111
- * @param time
112
- * @returns A chaining interface for the specified time
154
+ * Creates a series of evenly-spread points across the range, excluding the range's start and end
155
+ * @param count Number of Points to return
113
156
  */
114
- at(time: number): TimelineChain;
157
+ spread(count: number): TimelinePoint[];
115
158
  /**
116
- * Add a callback to run at a specified time
117
- * @param time Time at which this event will be triggered
118
- * @param apply Called when a forward seek targets or passes this event's time
119
- * @param applyOnReverse Called when a backward seek targets or passes this event's time
120
- * @returns A chaining interface for the specified time
159
+ * Progresses the Timeline across the range
160
+ * @param easer
121
161
  */
122
- at(time: number, apply: false, applyOnReverse: () => void): TimelineChain;
162
+ play(easer?: Easer): Promise<void>;
163
+ /** The point on the Timeline at which this range begins */
164
+ readonly start: TimelinePoint;
165
+ /** The point on the Timeline at which this range ends */
166
+ readonly end: TimelinePoint;
167
+ /** The duration of this range */
168
+ readonly duration: number;
169
+ }
170
+ export interface TimelinePoint extends Emitter<PointEvent> {
123
171
  /**
124
- * Add a callback to run at a specified time, offset by the Timeline's current position
125
- * @param time Offset, time at which this event will be triggered
126
- * @param apply Called when a forward seek targets or passes this event's time
127
- * @param revert Called when a backward seek passes this event's time. Default is no action
128
- * @returns A chaining interface for the specified time
172
+ * Creates a range on the Timeline, with a given duration, starting at this point
173
+ * @param duration
129
174
  */
130
- in(time: number, apply?: () => void, revert?: () => void): TimelineChain;
175
+ range(duration: number): TimelineRange;
131
176
  /**
132
- * Add a callback to run at a specified time, offset by the Timeline's current position (plus, if playing, time since the last update)
133
- * @param time Offset, time at which this event will be triggered
134
- * @param apply Called when a forward seek targets or passes this event's time
135
- * @param applyOnReverse Pass true to call `apply` regardless of direction of traversal, or false to specify no reversion action
136
- * @returns A chaining interface for the specified time
177
+ * Creates a range on the Timeline, with a given end point, starting at this point
178
+ * @param endPoint
137
179
  */
138
- in(time: number, apply: () => void, applyOnReverse: boolean): TimelineChain;
180
+ to(endPoint: number | TimelinePoint): TimelineRange;
139
181
  /**
140
- * Set the Timeline's position, applying intersecting tweens and events
141
- * Ignores the `loop` property and sets position as specified
142
- * @param time The new position
143
- * @param smooth Milliseconds over which to smoothly seek
182
+ * Creates a point on the Timeline at an offset position from this one
183
+ * @param timeOffset
144
184
  */
145
- seek(time: number, smooth: number): void;
185
+ delta(timeOffset: number): TimelinePoint;
146
186
  /**
147
- * Set the Timeline's position, applying intersecting tweens and events
148
- * Ignores the `loop` property and sets position as specified
149
- * @param time The new position
150
- * @param smooth Pass true to smooth-seek over 400ms
187
+ * The point's absolute position on the Timeline
151
188
  */
152
- seek(time: number, smooth?: boolean): void;
153
- private _seek;
189
+ readonly position: number;
190
+ }
191
+ type Tweenable = number | number[] | string | Blendable;
192
+ interface Blendable {
193
+ blend(target: this, progress: number): this;
194
+ }
195
+ type Handler<T> = (value: T) => void;
196
+ type Disposer = () => void;
197
+ interface Emitter<T> {
154
198
  /**
155
- * Moves the timeline forwards (or backwards given negative delta) by a specified amount, applying intersecting tweens and events
156
- * Honours `loop` ending action
157
- * @param delta Amount of time to move forward by. This will be affected by the `timeScale` property
199
+ * Registers a function to receive emitted values
200
+ * @param handler
201
+ * @returns A function to deregister the handler
158
202
  */
159
- step(delta?: number, smooth?: number | boolean): void;
160
- private lastFrameTime;
203
+ listen(handler: Handler<T>): Disposer;
204
+ map<R>(mapFunc: (value: T) => R): Emitter<R>;
161
205
  /**
162
- * Begins moving forward in time from current `position` at a rate of 1000 x `timeScale` units per second
163
- * If the timeline is already playing, it will stop and resume at the specified `fps`
164
- * Honours `loop` and `pause` ending actions
165
- * @param fps Frames per second
206
+ * Selectively forwards emissions along the chain
207
+ * @param check Function that takes an emitted value and returns true if the emission should be forwarded along the chain
166
208
  */
167
- play(fps?: number): void;
209
+ filter(check: (value: T) => boolean): Emitter<T>;
168
210
  /**
169
- * Pauses automatic progression started via `play()`
211
+ * Discards emitted values that are the same as the last emitted value
212
+ * @param compare Function that takes the previous and next values and returns true if they should be considered equal
170
213
  */
171
- pause(): void;
172
- get isPlaying(): boolean;
214
+ noRepeat(compare?: (a: T, b: T) => boolean): Emitter<T>;
215
+ }
216
+ export interface TweenEmitter<T extends Tweenable> extends Emitter<T> {
217
+ }
218
+ export interface RangeProgression extends Emitter<number> {
173
219
  /**
174
- * Creates a Timeline as a tween
175
- * * Transposes the inner Timeline's `0` -> `innerDuration` to the parent Timeline's `startTime` -> `outerDuration`
176
- * * Experimental - this functionality may change in future versions
177
- * @param startTime Position on the parent Timeline at which the inner Timeline will start seeking
178
- * @param outerDuration Length of time occupied on the parent Timeline by the inner Timeline
179
- * @param innerDuration Duration of the inner Timeline to transpose to `startTime` -> `outerDuration`
180
- * @param ease Function that takes progression (generally between 0 and 1) and returns modified progression
181
- * @returns
220
+ * Creates a chainable progress emitter that applies an easing function to its parent's emitted values
221
+ *
222
+ * @param easer An easing function of the form `(progression: number) => number`
223
+ * @returns Listenable: emits an eased value
182
224
  */
183
- createInnerTimeline(startTime: number, outerDuration: number, innerDuration?: number, ease?: EaseFunc): Timeline;
184
- private createChainInterface;
185
- private seekTweens;
225
+ ease(easer?: Easer | keyof typeof easers): RangeProgression;
186
226
  /**
187
- * Initialises and starts a Timeline using chained calls to specify tweens and events
188
- * @param looping
189
- * @returns
227
+ * Creates an emitter that interpolates two given values by progression emitted by its parent
228
+ *
229
+ * Can interpolate types `number`, `number[]`, string and objects with a `blend(from: this, to: this): this` method
230
+ *
231
+ * #### String interpolation
232
+ * * If the strings contain tweenable tokens (numbers, colour codes) and are otherwise identical, those tokens are interpolated
233
+ * * Otherwise the `from` string is progressively replaced, left-to-right, with the `to` string
234
+ *
235
+ * eg
236
+ * ```ts
237
+ * range
238
+ * .tween("0px 0px 0px #0000", "4px 4px 8px #0005")
239
+ * .listen(s => element.style.textShadow = s);
240
+ * ```
241
+ *
242
+ * @param from Value to interpolate from
243
+ * @param to Value to interpolate to
244
+ * @returns Listenable: emits an interpolated value
190
245
  */
191
- static start(looping?: boolean): TimelineChain;
246
+ tween<T extends Tweenable>(from: T, to: T): TweenEmitter<T>;
192
247
  }
248
+ type Easer = (n: number) => number;
193
249
  export declare const easers: {
194
250
  linear: (x: number) => number;
195
251
  easeIn: (x: number) => number;
@@ -209,11 +265,4 @@ export declare const easers: {
209
265
  step3: (x: number) => 0 | 1 | 0.333 | 0.667;
210
266
  pingpong: (x: number) => number;
211
267
  };
212
- export declare const dynamicEasers: {
213
- average: (easers: EaseFunc[]) => (x: number) => number;
214
- blend: (fromEaser: EaseFunc, toEaser: EaseFunc, amount: number) => (x: number) => number;
215
- sine: (freq?: number) => (x: number) => number;
216
- multiply: (easer: EaseFunc, mul: number) => (x: number) => number;
217
- combine: (easers: EaseFunc[]) => (x: number) => number;
218
- };
219
268
  export {};