@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.
@@ -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) when the Timeline's internal
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
- * Creates an observable range from position 0 to the Timeline's **current** final position
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;
@@ -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) when the Timeline's internal
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
- this.seekPoints(virtualTo);
236
- this.seekRanges(virtualTo);
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtia/timeline",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "repository": {
5
5
  "url": "https://github.com/tiadrop/timeline",
6
6
  "type": "github"