@xtia/timeline 0.2.5 → 1.0.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.
Files changed (4) hide show
  1. package/README.md +291 -0
  2. package/index.d.ts +189 -150
  3. package/index.js +543 -228
  4. package/package.json +19 -13
package/index.d.ts CHANGED
@@ -1,195 +1,241 @@
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;
72
92
  /**
73
- * @property The final position at which an event or tween exists on this Timeline
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
74
95
  */
75
- get end(): number;
96
+ seek(toPosition: number | TimelinePoint): void;
76
97
  /**
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
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
85
105
  */
86
- tween(startTime: number, duration: number, apply: ApplyTweenFunc, from?: NumberOrNumberFunction, to?: NumberOrNumberFunction, ease?: EaseFunc): TimelineChain;
106
+ seek(toPosition: number | TimelinePoint, duration: number, easer?: Easer): Promise<void>;
107
+ private seekDirect;
108
+ private seekPoints;
109
+ private seekRanges;
110
+ private sortEntries;
87
111
  /**
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
112
+ * Starts progression of the Timeline from its current position at (1000 x this.timeScale) units per second
91
113
  */
92
- tween(tween: TweenData): TimelineChain;
114
+ play(): void;
115
+ play(fps: number): void;
116
+ pause(): void;
93
117
  /**
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
118
+ * Progresses the Timeline by 1 unit
119
+ * @param delta
120
+ * @deprecated Use timeline.position++
99
121
  */
100
- at(time: number, apply: () => void, applyOnReverse?: () => void): TimelineChain;
122
+ step(): void;
101
123
  /**
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
124
+ * Progresses the Timeline by a given delta
125
+ * @param delta
126
+ * @deprecated Use timeline.position += n
107
127
  */
108
- at(time: number, apply: () => void, applyOnReverse: boolean): 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;
109
134
  /**
110
- * Ensures end time extends to (at least) the specified time
111
- * @param time
112
- * @returns A chaining interface for the specified time
135
+ * @deprecated use `timeline.currentTime`
113
136
  */
114
- at(time: number): 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 {
115
146
  /**
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
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
121
151
  */
122
- at(time: number, apply: false, applyOnReverse: () => void): TimelineChain;
152
+ bisect(position?: number): [TimelineRange, TimelineRange];
123
153
  /**
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
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
129
156
  */
130
- in(time: number, apply?: () => void, revert?: () => void): TimelineChain;
157
+ spread(count: number): TimelinePoint[];
131
158
  /**
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
159
+ * Progresses the Timeline across the range
160
+ * @param easer
137
161
  */
138
- in(time: number, apply: () => void, applyOnReverse: boolean): 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> {
139
171
  /**
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
172
+ * Creates a range on the Timeline, with a given duration, starting at this point
173
+ * @param duration
144
174
  */
145
- seek(time: number, smooth: number): void;
175
+ range(duration: number): TimelineRange;
146
176
  /**
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
177
+ * Creates a range on the Timeline, with a given end point, starting at this point
178
+ * @param endPoint
151
179
  */
152
- seek(time: number, smooth?: boolean): void;
153
- private _seek;
180
+ to(endPoint: number | TimelinePoint): TimelineRange;
154
181
  /**
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
182
+ * Creates a point on the Timeline at an offset position from this one
183
+ * @param timeOffset
158
184
  */
159
- step(delta?: number, smooth?: number | boolean): void;
160
- private lastFrameTime;
185
+ delta(timeOffset: number): TimelinePoint;
161
186
  /**
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
187
+ * The point's absolute position on the Timeline
166
188
  */
167
- play(fps?: number): void;
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> {
168
198
  /**
169
- * Pauses automatic progression started via `play()`
199
+ * Registers a function to receive emitted values
200
+ * @param handler
201
+ * @returns A function to deregister the handler
170
202
  */
171
- pause(): void;
172
- get isPlaying(): boolean;
203
+ listen(handler: Handler<T>): Disposer;
204
+ map<R>(mapFunc: (value: T) => R): Emitter<R>;
205
+ }
206
+ export interface TweenEmitter<T extends Tweenable> extends Emitter<T> {
207
+ }
208
+ export interface RangeProgression extends Emitter<number> {
173
209
  /**
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
210
+ * Creates a chainable progress emitter that applies an easing function to its parent's emitted values
211
+ *
212
+ * @param easer An easing function of the form `(progression: number) => number`
213
+ * @returns Listenable: emits an eased value
182
214
  */
183
- createInnerTimeline(startTime: number, outerDuration: number, innerDuration?: number, ease?: EaseFunc): Timeline;
184
- private createChainInterface;
185
- private seekTweens;
215
+ ease(easer?: Easer | keyof typeof easers): RangeProgression;
186
216
  /**
187
- * Initialises and starts a Timeline using chained calls to specify tweens and events
188
- * @param looping
189
- * @returns
217
+ * Creates an emitter that interpolates two given values by progression emitted by its parent
218
+ *
219
+ * Can interpolate types `number`, `number[]`, string and objects with a `blend(from: this, to: this): this` method
220
+ *
221
+ * #### String interpolation
222
+ * * If the strings contain tweenable tokens (numbers, colour codes) and are otherwise identical, those tokens are interpolated
223
+ * * Otherwise the `from` string is progressively replaced, left-to-right, with the `to` string
224
+ *
225
+ * eg
226
+ * ```ts
227
+ * range
228
+ * .tween("0px 0px 0px #0000", "4px 4px 8px #0005")
229
+ * .listen(s => element.style.textShadow = s);
230
+ * ```
231
+ *
232
+ * @param from Value to interpolate from
233
+ * @param to Value to interpolate to
234
+ * @returns Listenable: emits an interpolated value
190
235
  */
191
- static start(looping?: boolean): TimelineChain;
236
+ tween<T extends Tweenable>(from: T, to: T): TweenEmitter<T>;
192
237
  }
238
+ type Easer = (n: number) => number;
193
239
  export declare const easers: {
194
240
  linear: (x: number) => number;
195
241
  easeIn: (x: number) => number;
@@ -209,11 +255,4 @@ export declare const easers: {
209
255
  step3: (x: number) => 0 | 1 | 0.333 | 0.667;
210
256
  pingpong: (x: number) => number;
211
257
  };
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
258
  export {};