@xtia/timeline 1.1.5 → 1.1.6
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/internal/timeline.d.ts +4 -4
- package/internal/timeline.js +50 -32
- package/package.json +1 -1
package/internal/timeline.d.ts
CHANGED
|
@@ -48,8 +48,8 @@ export declare class Timeline {
|
|
|
48
48
|
apply(handler: () => void): UnsubscribeFunc;
|
|
49
49
|
private _progression;
|
|
50
50
|
/**
|
|
51
|
-
* Listenable: emits a progression value (0..1)
|
|
52
|
-
* position changes, and when the Timeline's total duration is extended
|
|
51
|
+
* Listenable: emits a progression value (0..1), representing progression through the entire Timeline,
|
|
52
|
+
* when the Timeline's internal position changes, and when the Timeline's total duration is extended
|
|
53
53
|
*/
|
|
54
54
|
get progression(): RangeProgression;
|
|
55
55
|
constructor();
|
|
@@ -102,10 +102,9 @@ export declare class Timeline {
|
|
|
102
102
|
*/
|
|
103
103
|
range(start: number | TimelinePoint, duration: number): TimelineRange;
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
105
|
+
* Defines a range from position 0 to the Timeline's **current** final position
|
|
106
106
|
*/
|
|
107
107
|
range(): TimelineRange;
|
|
108
|
-
private getWrappedPosition;
|
|
109
108
|
/**
|
|
110
109
|
* Seeks the Timeline to a specified position, triggering in order any point and range subscriptions between its current and new positions
|
|
111
110
|
* @param toPosition
|
|
@@ -123,6 +122,7 @@ export declare class Timeline {
|
|
|
123
122
|
seek(toPosition: number | TimelinePoint, durationMs: number, easer?: Easer | keyof typeof easers): Promise<void>;
|
|
124
123
|
seek(toPosition: number | TimelinePoint, duration: Period, easer?: Easer | keyof typeof easers): Promise<void>;
|
|
125
124
|
private seekDirect;
|
|
125
|
+
private seekWrapped;
|
|
126
126
|
private seekPoints;
|
|
127
127
|
private seekRanges;
|
|
128
128
|
private sortEntries;
|
package/internal/timeline.js
CHANGED
|
@@ -40,8 +40,8 @@ export class Timeline {
|
|
|
40
40
|
return this._frameEvents.listen(handler);
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* Listenable: emits a progression value (0..1)
|
|
44
|
-
* position changes, and when the Timeline's total duration is extended
|
|
43
|
+
* Listenable: emits a progression value (0..1), representing progression through the entire Timeline,
|
|
44
|
+
* when the Timeline's internal position changes, and when the Timeline's total duration is extended
|
|
45
45
|
*/
|
|
46
46
|
get progression() {
|
|
47
47
|
if (this._progression === null) {
|
|
@@ -161,22 +161,6 @@ export class Timeline {
|
|
|
161
161
|
const range = new TimelineRange(addHandler, this, startPoint, endPoint);
|
|
162
162
|
return range;
|
|
163
163
|
}
|
|
164
|
-
getWrappedPosition(n) {
|
|
165
|
-
if (this.endAction.type !== EndAction.wrap)
|
|
166
|
-
return n;
|
|
167
|
-
const wrapAt = this.endAction.at?.position ?? 0;
|
|
168
|
-
if (wrapAt == 0)
|
|
169
|
-
return n % this._endPosition;
|
|
170
|
-
if (n <= this._endPosition)
|
|
171
|
-
return n;
|
|
172
|
-
const loopStart = wrapAt;
|
|
173
|
-
const segment = this._endPosition - loopStart;
|
|
174
|
-
if (segment <= 0)
|
|
175
|
-
return Math.min(n, this._endPosition);
|
|
176
|
-
const overflow = n - this._endPosition;
|
|
177
|
-
const remainder = overflow % segment;
|
|
178
|
-
return loopStart + remainder;
|
|
179
|
-
}
|
|
180
164
|
seek(to, duration, easer) {
|
|
181
165
|
const durationMs = typeof duration == "object"
|
|
182
166
|
? duration.asMilliseconds
|
|
@@ -216,31 +200,65 @@ export class Timeline {
|
|
|
216
200
|
const fromPosition = this._currentTime;
|
|
217
201
|
if (toPosition === fromPosition)
|
|
218
202
|
return;
|
|
219
|
-
const loopingTo = this.getWrappedPosition(toPosition);
|
|
220
|
-
const loopingFrom = this.getWrappedPosition(fromPosition);
|
|
221
|
-
let virtualFrom = loopingFrom;
|
|
222
|
-
let virtualTo = loopingTo;
|
|
223
203
|
const direction = toPosition > fromPosition ? 1 : -1;
|
|
224
204
|
if (direction !== this.currentSortDirection)
|
|
225
205
|
this.sortEntries(direction);
|
|
226
|
-
if (direction === 1 && loopingTo < loopingFrom) {
|
|
227
|
-
virtualFrom = loopingFrom - this._endPosition;
|
|
228
|
-
}
|
|
229
|
-
else if (direction === -1 && loopingTo > loopingFrom) {
|
|
230
|
-
virtualFrom = loopingFrom + this._endPosition;
|
|
231
|
-
}
|
|
232
206
|
this.seeking = true;
|
|
233
|
-
this._currentTime = virtualFrom;
|
|
234
207
|
try {
|
|
235
|
-
|
|
236
|
-
this.
|
|
208
|
+
// use wrapping logic?
|
|
209
|
+
if (this.endAction.type === EndAction.wrap && (fromPosition > this._endPosition || toPosition > this._endPosition)) {
|
|
210
|
+
this.seekWrapped(toPosition);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
this.seekPoints(toPosition);
|
|
214
|
+
this.seekRanges(toPosition);
|
|
215
|
+
}
|
|
237
216
|
}
|
|
238
217
|
catch (e) {
|
|
239
218
|
this.pause();
|
|
240
219
|
throw e;
|
|
241
220
|
}
|
|
221
|
+
finally {
|
|
222
|
+
this.seeking = false;
|
|
223
|
+
}
|
|
224
|
+
this._currentTime = toPosition;
|
|
225
|
+
}
|
|
226
|
+
seekWrapped(toPosition) {
|
|
227
|
+
const fromPosition = this._currentTime;
|
|
228
|
+
const timelineEnd = this._endPosition;
|
|
229
|
+
const wrapAt = "at" in this.endAction ? this.endAction.at.position : 0;
|
|
230
|
+
const loopLen = timelineEnd - wrapAt;
|
|
231
|
+
const getWrappedPosition = (pos) => ((pos - wrapAt) % loopLen + loopLen) % loopLen + wrapAt;
|
|
232
|
+
const realDelta = toPosition - fromPosition;
|
|
233
|
+
const direction = realDelta >= 0 ? 1 : -1;
|
|
234
|
+
let remaining = Math.abs(realDelta);
|
|
235
|
+
let virtualFrom = getWrappedPosition(fromPosition);
|
|
236
|
+
while (remaining > 0) {
|
|
237
|
+
let virtualTo;
|
|
238
|
+
if (direction > 0) {
|
|
239
|
+
const wrapSize = timelineEnd - virtualFrom;
|
|
240
|
+
virtualTo = remaining <= wrapSize
|
|
241
|
+
? virtualFrom + remaining
|
|
242
|
+
: timelineEnd;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
const wrapSize = virtualFrom - wrapAt;
|
|
246
|
+
virtualTo = remaining <= wrapSize
|
|
247
|
+
? virtualFrom - remaining
|
|
248
|
+
: wrapAt;
|
|
249
|
+
}
|
|
250
|
+
this._currentTime = virtualFrom;
|
|
251
|
+
this.seekPoints(virtualTo);
|
|
252
|
+
remaining -= Math.abs(virtualTo - virtualFrom);
|
|
253
|
+
if (remaining > 0) {
|
|
254
|
+
virtualFrom = direction > 0 ? wrapAt : timelineEnd;
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
virtualFrom = virtualTo;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
this.seekRanges(getWrappedPosition(toPosition));
|
|
242
261
|
this._currentTime = toPosition;
|
|
243
|
-
this.seeking = false;
|
|
244
262
|
}
|
|
245
263
|
seekPoints(to) {
|
|
246
264
|
const from = this._currentTime;
|