@tweenjs/tween.js 23.1.0 → 23.1.2

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 CHANGED
@@ -9,7 +9,7 @@ JavaScript (TypeScript) tweening engine for easy animations, incorporating optim
9
9
 
10
10
  More languages: [English](./README.md), [简体中文](./README_zh-CN.md)
11
11
 
12
- ---
12
+ # Example
13
13
 
14
14
  ```html
15
15
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/20.0.0/tween.umd.js"></script>
@@ -48,7 +48,10 @@ More languages: [English](./README.md), [简体中文](./README_zh-CN.md)
48
48
  </script>
49
49
  ```
50
50
 
51
- [Try this example on CodePen](https://codepen.io/trusktr/pen/KKGaBVz?editors=1000)
51
+ [Try the above example on CodePen](https://codepen.io/trusktr/pen/KKGaBVz?editors=1000)
52
+
53
+ Animate numbers in any JavaScript object. For example, [rotate a 3D box made
54
+ with Three.js](https://codepen.io/trusktr/pen/ExJqvgZ):
52
55
 
53
56
  # Installation
54
57
 
package/dist/tween.amd.js CHANGED
@@ -9,13 +9,13 @@ define(['exports'], (function (exports) { 'use strict';
9
9
  return amount;
10
10
  },
11
11
  In: function (amount) {
12
- return this.None(amount);
12
+ return amount;
13
13
  },
14
14
  Out: function (amount) {
15
- return this.None(amount);
15
+ return amount;
16
16
  },
17
17
  InOut: function (amount) {
18
- return this.None(amount);
18
+ return amount;
19
19
  },
20
20
  }),
21
21
  Quadratic: Object.freeze({
@@ -424,12 +424,12 @@ define(['exports'], (function (exports) { 'use strict';
424
424
  throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');
425
425
  this._valuesEnd = target;
426
426
  this._propertiesAreSetUp = false;
427
- this._duration = duration;
427
+ this._duration = duration < 0 ? 0 : duration;
428
428
  return this;
429
429
  };
430
430
  Tween.prototype.duration = function (duration) {
431
431
  if (duration === void 0) { duration = 1000; }
432
- this._duration = duration;
432
+ this._duration = duration < 0 ? 0 : duration;
433
433
  return this;
434
434
  };
435
435
  Tween.prototype.dynamic = function (dynamic) {
@@ -678,13 +678,11 @@ define(['exports'], (function (exports) { 'use strict';
678
678
  * it is still playing, just paused).
679
679
  */
680
680
  Tween.prototype.update = function (time, autoStart) {
681
- var _this = this;
682
681
  var _a;
683
682
  if (time === void 0) { time = now(); }
684
683
  if (autoStart === void 0) { autoStart = true; }
685
684
  if (this._isPaused)
686
685
  return true;
687
- var property;
688
686
  var endTime = this._startTime + this._duration;
689
687
  if (!this._goToEnd && !this._isPlaying) {
690
688
  if (time > endTime)
@@ -711,72 +709,85 @@ define(['exports'], (function (exports) { 'use strict';
711
709
  var elapsedTime = time - this._startTime;
712
710
  var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);
713
711
  var totalTime = this._duration + this._repeat * durationAndDelay;
714
- var calculateElapsedPortion = function () {
715
- if (_this._duration === 0)
716
- return 1;
717
- if (elapsedTime > totalTime) {
718
- return 1;
719
- }
720
- var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);
721
- var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;
722
- // TODO use %?
723
- // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay
724
- var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);
725
- if (portion === 0 && elapsedTime === _this._duration) {
726
- return 1;
727
- }
728
- return portion;
729
- };
730
- var elapsed = calculateElapsedPortion();
712
+ var elapsed = this._calculateElapsedPortion(elapsedTime, durationAndDelay, totalTime);
731
713
  var value = this._easingFunction(elapsed);
732
- // properties transformations
714
+ var status = this._calculateCompletionStatus(elapsedTime, durationAndDelay);
715
+ if (status === 'repeat') {
716
+ // the current update is happening after the instant the tween repeated
717
+ this._processRepetition(elapsedTime, durationAndDelay);
718
+ }
733
719
  this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);
720
+ if (status === 'about-to-repeat') {
721
+ // the current update is happening at the exact instant the tween is going to repeat
722
+ // the values should match the end of the tween, not the beginning,
723
+ // that's why _processRepetition happens after _updateProperties
724
+ this._processRepetition(elapsedTime, durationAndDelay);
725
+ }
734
726
  if (this._onUpdateCallback) {
735
727
  this._onUpdateCallback(this._object, elapsed);
736
728
  }
737
- if (this._duration === 0 || elapsedTime >= this._duration) {
738
- if (this._repeat > 0) {
739
- var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
740
- if (isFinite(this._repeat)) {
741
- this._repeat -= completeCount;
742
- }
743
- // Reassign starting values, restart by making startTime = now
744
- for (property in this._valuesStartRepeat) {
745
- if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {
746
- this._valuesStartRepeat[property] =
747
- // eslint-disable-next-line
748
- // @ts-ignore FIXME?
749
- this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);
750
- }
751
- if (this._yoyo) {
752
- this._swapEndStartRepeatValues(property);
753
- }
754
- this._valuesStart[property] = this._valuesStartRepeat[property];
755
- }
756
- if (this._yoyo) {
757
- this._reversed = !this._reversed;
758
- }
759
- this._startTime += durationAndDelay * completeCount;
760
- if (this._onRepeatCallback) {
761
- this._onRepeatCallback(this._object);
762
- }
763
- this._onEveryStartCallbackFired = false;
764
- return true;
729
+ if (status === 'repeat' || status === 'about-to-repeat') {
730
+ if (this._onRepeatCallback) {
731
+ this._onRepeatCallback(this._object);
765
732
  }
766
- else {
767
- if (this._onCompleteCallback) {
768
- this._onCompleteCallback(this._object);
769
- }
770
- for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
771
- // Make the chained tweens start exactly at the time they should,
772
- // even if the `update()` method was called way past the duration of the tween
773
- this._chainedTweens[i].start(this._startTime + this._duration, false);
774
- }
775
- this._isPlaying = false;
776
- return false;
733
+ this._onEveryStartCallbackFired = false;
734
+ }
735
+ else if (status === 'completed') {
736
+ this._isPlaying = false;
737
+ if (this._onCompleteCallback) {
738
+ this._onCompleteCallback(this._object);
739
+ }
740
+ for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
741
+ // Make the chained tweens start exactly at the time they should,
742
+ // even if the `update()` method was called way past the duration of the tween
743
+ this._chainedTweens[i].start(this._startTime + this._duration, false);
777
744
  }
778
745
  }
779
- return true;
746
+ return status !== 'completed';
747
+ };
748
+ Tween.prototype._calculateElapsedPortion = function (elapsedTime, durationAndDelay, totalTime) {
749
+ if (this._duration === 0 || elapsedTime > totalTime) {
750
+ return 1;
751
+ }
752
+ var timeIntoCurrentRepeat = elapsedTime % durationAndDelay;
753
+ var portion = Math.min(timeIntoCurrentRepeat / this._duration, 1);
754
+ if (portion === 0 && elapsedTime !== 0 && elapsedTime % this._duration === 0) {
755
+ return 1;
756
+ }
757
+ return portion;
758
+ };
759
+ Tween.prototype._calculateCompletionStatus = function (elapsedTime, durationAndDelay) {
760
+ if (this._duration !== 0 && elapsedTime < this._duration) {
761
+ return 'playing';
762
+ }
763
+ if (this._repeat <= 0) {
764
+ return 'completed';
765
+ }
766
+ if (elapsedTime === this._duration) {
767
+ return 'about-to-repeat';
768
+ }
769
+ return 'repeat';
770
+ };
771
+ Tween.prototype._processRepetition = function (elapsedTime, durationAndDelay) {
772
+ var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
773
+ if (isFinite(this._repeat)) {
774
+ this._repeat -= completeCount;
775
+ }
776
+ // Reassign starting values, restart by making startTime = now
777
+ for (var property in this._valuesStartRepeat) {
778
+ var valueEnd = this._valuesEnd[property];
779
+ if (!this._yoyo && typeof valueEnd === 'string') {
780
+ this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(valueEnd);
781
+ }
782
+ if (this._yoyo) {
783
+ this._swapEndStartRepeatValues(property);
784
+ }
785
+ this._valuesStart[property] = this._valuesStartRepeat[property];
786
+ }
787
+ if (this._yoyo) {
788
+ this._reversed = !this._reversed;
789
+ }
790
+ this._startTime += durationAndDelay * completeCount;
780
791
  };
781
792
  Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {
782
793
  for (var property in _valuesEnd) {
@@ -832,7 +843,7 @@ define(['exports'], (function (exports) { 'use strict';
832
843
  return Tween;
833
844
  }());
834
845
 
835
- var VERSION = '23.1.0';
846
+ var VERSION = '23.1.2';
836
847
 
837
848
  /**
838
849
  * Tween.js - Licensed under the MIT license
package/dist/tween.cjs CHANGED
@@ -11,13 +11,13 @@ var Easing = Object.freeze({
11
11
  return amount;
12
12
  },
13
13
  In: function (amount) {
14
- return this.None(amount);
14
+ return amount;
15
15
  },
16
16
  Out: function (amount) {
17
- return this.None(amount);
17
+ return amount;
18
18
  },
19
19
  InOut: function (amount) {
20
- return this.None(amount);
20
+ return amount;
21
21
  },
22
22
  }),
23
23
  Quadratic: Object.freeze({
@@ -426,12 +426,12 @@ var Tween = /** @class */ (function () {
426
426
  throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');
427
427
  this._valuesEnd = target;
428
428
  this._propertiesAreSetUp = false;
429
- this._duration = duration;
429
+ this._duration = duration < 0 ? 0 : duration;
430
430
  return this;
431
431
  };
432
432
  Tween.prototype.duration = function (duration) {
433
433
  if (duration === void 0) { duration = 1000; }
434
- this._duration = duration;
434
+ this._duration = duration < 0 ? 0 : duration;
435
435
  return this;
436
436
  };
437
437
  Tween.prototype.dynamic = function (dynamic) {
@@ -680,13 +680,11 @@ var Tween = /** @class */ (function () {
680
680
  * it is still playing, just paused).
681
681
  */
682
682
  Tween.prototype.update = function (time, autoStart) {
683
- var _this = this;
684
683
  var _a;
685
684
  if (time === void 0) { time = now(); }
686
685
  if (autoStart === void 0) { autoStart = true; }
687
686
  if (this._isPaused)
688
687
  return true;
689
- var property;
690
688
  var endTime = this._startTime + this._duration;
691
689
  if (!this._goToEnd && !this._isPlaying) {
692
690
  if (time > endTime)
@@ -713,72 +711,85 @@ var Tween = /** @class */ (function () {
713
711
  var elapsedTime = time - this._startTime;
714
712
  var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);
715
713
  var totalTime = this._duration + this._repeat * durationAndDelay;
716
- var calculateElapsedPortion = function () {
717
- if (_this._duration === 0)
718
- return 1;
719
- if (elapsedTime > totalTime) {
720
- return 1;
721
- }
722
- var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);
723
- var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;
724
- // TODO use %?
725
- // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay
726
- var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);
727
- if (portion === 0 && elapsedTime === _this._duration) {
728
- return 1;
729
- }
730
- return portion;
731
- };
732
- var elapsed = calculateElapsedPortion();
714
+ var elapsed = this._calculateElapsedPortion(elapsedTime, durationAndDelay, totalTime);
733
715
  var value = this._easingFunction(elapsed);
734
- // properties transformations
716
+ var status = this._calculateCompletionStatus(elapsedTime, durationAndDelay);
717
+ if (status === 'repeat') {
718
+ // the current update is happening after the instant the tween repeated
719
+ this._processRepetition(elapsedTime, durationAndDelay);
720
+ }
735
721
  this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);
722
+ if (status === 'about-to-repeat') {
723
+ // the current update is happening at the exact instant the tween is going to repeat
724
+ // the values should match the end of the tween, not the beginning,
725
+ // that's why _processRepetition happens after _updateProperties
726
+ this._processRepetition(elapsedTime, durationAndDelay);
727
+ }
736
728
  if (this._onUpdateCallback) {
737
729
  this._onUpdateCallback(this._object, elapsed);
738
730
  }
739
- if (this._duration === 0 || elapsedTime >= this._duration) {
740
- if (this._repeat > 0) {
741
- var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
742
- if (isFinite(this._repeat)) {
743
- this._repeat -= completeCount;
744
- }
745
- // Reassign starting values, restart by making startTime = now
746
- for (property in this._valuesStartRepeat) {
747
- if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {
748
- this._valuesStartRepeat[property] =
749
- // eslint-disable-next-line
750
- // @ts-ignore FIXME?
751
- this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);
752
- }
753
- if (this._yoyo) {
754
- this._swapEndStartRepeatValues(property);
755
- }
756
- this._valuesStart[property] = this._valuesStartRepeat[property];
757
- }
758
- if (this._yoyo) {
759
- this._reversed = !this._reversed;
760
- }
761
- this._startTime += durationAndDelay * completeCount;
762
- if (this._onRepeatCallback) {
763
- this._onRepeatCallback(this._object);
764
- }
765
- this._onEveryStartCallbackFired = false;
766
- return true;
731
+ if (status === 'repeat' || status === 'about-to-repeat') {
732
+ if (this._onRepeatCallback) {
733
+ this._onRepeatCallback(this._object);
767
734
  }
768
- else {
769
- if (this._onCompleteCallback) {
770
- this._onCompleteCallback(this._object);
771
- }
772
- for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
773
- // Make the chained tweens start exactly at the time they should,
774
- // even if the `update()` method was called way past the duration of the tween
775
- this._chainedTweens[i].start(this._startTime + this._duration, false);
776
- }
777
- this._isPlaying = false;
778
- return false;
735
+ this._onEveryStartCallbackFired = false;
736
+ }
737
+ else if (status === 'completed') {
738
+ this._isPlaying = false;
739
+ if (this._onCompleteCallback) {
740
+ this._onCompleteCallback(this._object);
741
+ }
742
+ for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
743
+ // Make the chained tweens start exactly at the time they should,
744
+ // even if the `update()` method was called way past the duration of the tween
745
+ this._chainedTweens[i].start(this._startTime + this._duration, false);
779
746
  }
780
747
  }
781
- return true;
748
+ return status !== 'completed';
749
+ };
750
+ Tween.prototype._calculateElapsedPortion = function (elapsedTime, durationAndDelay, totalTime) {
751
+ if (this._duration === 0 || elapsedTime > totalTime) {
752
+ return 1;
753
+ }
754
+ var timeIntoCurrentRepeat = elapsedTime % durationAndDelay;
755
+ var portion = Math.min(timeIntoCurrentRepeat / this._duration, 1);
756
+ if (portion === 0 && elapsedTime !== 0 && elapsedTime % this._duration === 0) {
757
+ return 1;
758
+ }
759
+ return portion;
760
+ };
761
+ Tween.prototype._calculateCompletionStatus = function (elapsedTime, durationAndDelay) {
762
+ if (this._duration !== 0 && elapsedTime < this._duration) {
763
+ return 'playing';
764
+ }
765
+ if (this._repeat <= 0) {
766
+ return 'completed';
767
+ }
768
+ if (elapsedTime === this._duration) {
769
+ return 'about-to-repeat';
770
+ }
771
+ return 'repeat';
772
+ };
773
+ Tween.prototype._processRepetition = function (elapsedTime, durationAndDelay) {
774
+ var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
775
+ if (isFinite(this._repeat)) {
776
+ this._repeat -= completeCount;
777
+ }
778
+ // Reassign starting values, restart by making startTime = now
779
+ for (var property in this._valuesStartRepeat) {
780
+ var valueEnd = this._valuesEnd[property];
781
+ if (!this._yoyo && typeof valueEnd === 'string') {
782
+ this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(valueEnd);
783
+ }
784
+ if (this._yoyo) {
785
+ this._swapEndStartRepeatValues(property);
786
+ }
787
+ this._valuesStart[property] = this._valuesStartRepeat[property];
788
+ }
789
+ if (this._yoyo) {
790
+ this._reversed = !this._reversed;
791
+ }
792
+ this._startTime += durationAndDelay * completeCount;
782
793
  };
783
794
  Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {
784
795
  for (var property in _valuesEnd) {
@@ -834,7 +845,7 @@ var Tween = /** @class */ (function () {
834
845
  return Tween;
835
846
  }());
836
847
 
837
- var VERSION = '23.1.0';
848
+ var VERSION = '23.1.2';
838
849
 
839
850
  /**
840
851
  * Tween.js - Licensed under the MIT license
package/dist/tween.d.ts CHANGED
@@ -137,6 +137,9 @@ declare class Tween<T extends UnknownProps> {
137
137
  * it is still playing, just paused).
138
138
  */
139
139
  update(time?: number, autoStart?: boolean): boolean;
140
+ private _calculateElapsedPortion;
141
+ private _calculateCompletionStatus;
142
+ private _processRepetition;
140
143
  private _updateProperties;
141
144
  private _handleRelativeValue;
142
145
  private _swapEndStartRepeatValues;
@@ -153,7 +156,7 @@ declare class Sequence {
153
156
  static nextId(): number;
154
157
  }
155
158
 
156
- declare const VERSION = "23.1.0";
159
+ declare const VERSION = "23.1.2";
157
160
 
158
161
  declare const nextId: typeof Sequence.nextId;
159
162
  declare const getAll: () => Tween<UnknownProps>[];
package/dist/tween.esm.js CHANGED
@@ -7,13 +7,13 @@ var Easing = Object.freeze({
7
7
  return amount;
8
8
  },
9
9
  In: function (amount) {
10
- return this.None(amount);
10
+ return amount;
11
11
  },
12
12
  Out: function (amount) {
13
- return this.None(amount);
13
+ return amount;
14
14
  },
15
15
  InOut: function (amount) {
16
- return this.None(amount);
16
+ return amount;
17
17
  },
18
18
  }),
19
19
  Quadratic: Object.freeze({
@@ -422,12 +422,12 @@ var Tween = /** @class */ (function () {
422
422
  throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');
423
423
  this._valuesEnd = target;
424
424
  this._propertiesAreSetUp = false;
425
- this._duration = duration;
425
+ this._duration = duration < 0 ? 0 : duration;
426
426
  return this;
427
427
  };
428
428
  Tween.prototype.duration = function (duration) {
429
429
  if (duration === void 0) { duration = 1000; }
430
- this._duration = duration;
430
+ this._duration = duration < 0 ? 0 : duration;
431
431
  return this;
432
432
  };
433
433
  Tween.prototype.dynamic = function (dynamic) {
@@ -676,13 +676,11 @@ var Tween = /** @class */ (function () {
676
676
  * it is still playing, just paused).
677
677
  */
678
678
  Tween.prototype.update = function (time, autoStart) {
679
- var _this = this;
680
679
  var _a;
681
680
  if (time === void 0) { time = now(); }
682
681
  if (autoStart === void 0) { autoStart = true; }
683
682
  if (this._isPaused)
684
683
  return true;
685
- var property;
686
684
  var endTime = this._startTime + this._duration;
687
685
  if (!this._goToEnd && !this._isPlaying) {
688
686
  if (time > endTime)
@@ -709,72 +707,85 @@ var Tween = /** @class */ (function () {
709
707
  var elapsedTime = time - this._startTime;
710
708
  var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);
711
709
  var totalTime = this._duration + this._repeat * durationAndDelay;
712
- var calculateElapsedPortion = function () {
713
- if (_this._duration === 0)
714
- return 1;
715
- if (elapsedTime > totalTime) {
716
- return 1;
717
- }
718
- var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);
719
- var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;
720
- // TODO use %?
721
- // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay
722
- var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);
723
- if (portion === 0 && elapsedTime === _this._duration) {
724
- return 1;
725
- }
726
- return portion;
727
- };
728
- var elapsed = calculateElapsedPortion();
710
+ var elapsed = this._calculateElapsedPortion(elapsedTime, durationAndDelay, totalTime);
729
711
  var value = this._easingFunction(elapsed);
730
- // properties transformations
712
+ var status = this._calculateCompletionStatus(elapsedTime, durationAndDelay);
713
+ if (status === 'repeat') {
714
+ // the current update is happening after the instant the tween repeated
715
+ this._processRepetition(elapsedTime, durationAndDelay);
716
+ }
731
717
  this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);
718
+ if (status === 'about-to-repeat') {
719
+ // the current update is happening at the exact instant the tween is going to repeat
720
+ // the values should match the end of the tween, not the beginning,
721
+ // that's why _processRepetition happens after _updateProperties
722
+ this._processRepetition(elapsedTime, durationAndDelay);
723
+ }
732
724
  if (this._onUpdateCallback) {
733
725
  this._onUpdateCallback(this._object, elapsed);
734
726
  }
735
- if (this._duration === 0 || elapsedTime >= this._duration) {
736
- if (this._repeat > 0) {
737
- var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
738
- if (isFinite(this._repeat)) {
739
- this._repeat -= completeCount;
740
- }
741
- // Reassign starting values, restart by making startTime = now
742
- for (property in this._valuesStartRepeat) {
743
- if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {
744
- this._valuesStartRepeat[property] =
745
- // eslint-disable-next-line
746
- // @ts-ignore FIXME?
747
- this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);
748
- }
749
- if (this._yoyo) {
750
- this._swapEndStartRepeatValues(property);
751
- }
752
- this._valuesStart[property] = this._valuesStartRepeat[property];
753
- }
754
- if (this._yoyo) {
755
- this._reversed = !this._reversed;
756
- }
757
- this._startTime += durationAndDelay * completeCount;
758
- if (this._onRepeatCallback) {
759
- this._onRepeatCallback(this._object);
760
- }
761
- this._onEveryStartCallbackFired = false;
762
- return true;
727
+ if (status === 'repeat' || status === 'about-to-repeat') {
728
+ if (this._onRepeatCallback) {
729
+ this._onRepeatCallback(this._object);
763
730
  }
764
- else {
765
- if (this._onCompleteCallback) {
766
- this._onCompleteCallback(this._object);
767
- }
768
- for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
769
- // Make the chained tweens start exactly at the time they should,
770
- // even if the `update()` method was called way past the duration of the tween
771
- this._chainedTweens[i].start(this._startTime + this._duration, false);
772
- }
773
- this._isPlaying = false;
774
- return false;
731
+ this._onEveryStartCallbackFired = false;
732
+ }
733
+ else if (status === 'completed') {
734
+ this._isPlaying = false;
735
+ if (this._onCompleteCallback) {
736
+ this._onCompleteCallback(this._object);
737
+ }
738
+ for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
739
+ // Make the chained tweens start exactly at the time they should,
740
+ // even if the `update()` method was called way past the duration of the tween
741
+ this._chainedTweens[i].start(this._startTime + this._duration, false);
775
742
  }
776
743
  }
777
- return true;
744
+ return status !== 'completed';
745
+ };
746
+ Tween.prototype._calculateElapsedPortion = function (elapsedTime, durationAndDelay, totalTime) {
747
+ if (this._duration === 0 || elapsedTime > totalTime) {
748
+ return 1;
749
+ }
750
+ var timeIntoCurrentRepeat = elapsedTime % durationAndDelay;
751
+ var portion = Math.min(timeIntoCurrentRepeat / this._duration, 1);
752
+ if (portion === 0 && elapsedTime !== 0 && elapsedTime % this._duration === 0) {
753
+ return 1;
754
+ }
755
+ return portion;
756
+ };
757
+ Tween.prototype._calculateCompletionStatus = function (elapsedTime, durationAndDelay) {
758
+ if (this._duration !== 0 && elapsedTime < this._duration) {
759
+ return 'playing';
760
+ }
761
+ if (this._repeat <= 0) {
762
+ return 'completed';
763
+ }
764
+ if (elapsedTime === this._duration) {
765
+ return 'about-to-repeat';
766
+ }
767
+ return 'repeat';
768
+ };
769
+ Tween.prototype._processRepetition = function (elapsedTime, durationAndDelay) {
770
+ var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
771
+ if (isFinite(this._repeat)) {
772
+ this._repeat -= completeCount;
773
+ }
774
+ // Reassign starting values, restart by making startTime = now
775
+ for (var property in this._valuesStartRepeat) {
776
+ var valueEnd = this._valuesEnd[property];
777
+ if (!this._yoyo && typeof valueEnd === 'string') {
778
+ this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(valueEnd);
779
+ }
780
+ if (this._yoyo) {
781
+ this._swapEndStartRepeatValues(property);
782
+ }
783
+ this._valuesStart[property] = this._valuesStartRepeat[property];
784
+ }
785
+ if (this._yoyo) {
786
+ this._reversed = !this._reversed;
787
+ }
788
+ this._startTime += durationAndDelay * completeCount;
778
789
  };
779
790
  Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {
780
791
  for (var property in _valuesEnd) {
@@ -830,7 +841,7 @@ var Tween = /** @class */ (function () {
830
841
  return Tween;
831
842
  }());
832
843
 
833
- var VERSION = '23.1.0';
844
+ var VERSION = '23.1.2';
834
845
 
835
846
  /**
836
847
  * Tween.js - Licensed under the MIT license
package/dist/tween.umd.js CHANGED
@@ -13,13 +13,13 @@
13
13
  return amount;
14
14
  },
15
15
  In: function (amount) {
16
- return this.None(amount);
16
+ return amount;
17
17
  },
18
18
  Out: function (amount) {
19
- return this.None(amount);
19
+ return amount;
20
20
  },
21
21
  InOut: function (amount) {
22
- return this.None(amount);
22
+ return amount;
23
23
  },
24
24
  }),
25
25
  Quadratic: Object.freeze({
@@ -428,12 +428,12 @@
428
428
  throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');
429
429
  this._valuesEnd = target;
430
430
  this._propertiesAreSetUp = false;
431
- this._duration = duration;
431
+ this._duration = duration < 0 ? 0 : duration;
432
432
  return this;
433
433
  };
434
434
  Tween.prototype.duration = function (duration) {
435
435
  if (duration === void 0) { duration = 1000; }
436
- this._duration = duration;
436
+ this._duration = duration < 0 ? 0 : duration;
437
437
  return this;
438
438
  };
439
439
  Tween.prototype.dynamic = function (dynamic) {
@@ -682,13 +682,11 @@
682
682
  * it is still playing, just paused).
683
683
  */
684
684
  Tween.prototype.update = function (time, autoStart) {
685
- var _this = this;
686
685
  var _a;
687
686
  if (time === void 0) { time = now(); }
688
687
  if (autoStart === void 0) { autoStart = true; }
689
688
  if (this._isPaused)
690
689
  return true;
691
- var property;
692
690
  var endTime = this._startTime + this._duration;
693
691
  if (!this._goToEnd && !this._isPlaying) {
694
692
  if (time > endTime)
@@ -715,72 +713,85 @@
715
713
  var elapsedTime = time - this._startTime;
716
714
  var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);
717
715
  var totalTime = this._duration + this._repeat * durationAndDelay;
718
- var calculateElapsedPortion = function () {
719
- if (_this._duration === 0)
720
- return 1;
721
- if (elapsedTime > totalTime) {
722
- return 1;
723
- }
724
- var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);
725
- var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;
726
- // TODO use %?
727
- // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay
728
- var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);
729
- if (portion === 0 && elapsedTime === _this._duration) {
730
- return 1;
731
- }
732
- return portion;
733
- };
734
- var elapsed = calculateElapsedPortion();
716
+ var elapsed = this._calculateElapsedPortion(elapsedTime, durationAndDelay, totalTime);
735
717
  var value = this._easingFunction(elapsed);
736
- // properties transformations
718
+ var status = this._calculateCompletionStatus(elapsedTime, durationAndDelay);
719
+ if (status === 'repeat') {
720
+ // the current update is happening after the instant the tween repeated
721
+ this._processRepetition(elapsedTime, durationAndDelay);
722
+ }
737
723
  this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);
724
+ if (status === 'about-to-repeat') {
725
+ // the current update is happening at the exact instant the tween is going to repeat
726
+ // the values should match the end of the tween, not the beginning,
727
+ // that's why _processRepetition happens after _updateProperties
728
+ this._processRepetition(elapsedTime, durationAndDelay);
729
+ }
738
730
  if (this._onUpdateCallback) {
739
731
  this._onUpdateCallback(this._object, elapsed);
740
732
  }
741
- if (this._duration === 0 || elapsedTime >= this._duration) {
742
- if (this._repeat > 0) {
743
- var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
744
- if (isFinite(this._repeat)) {
745
- this._repeat -= completeCount;
746
- }
747
- // Reassign starting values, restart by making startTime = now
748
- for (property in this._valuesStartRepeat) {
749
- if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {
750
- this._valuesStartRepeat[property] =
751
- // eslint-disable-next-line
752
- // @ts-ignore FIXME?
753
- this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);
754
- }
755
- if (this._yoyo) {
756
- this._swapEndStartRepeatValues(property);
757
- }
758
- this._valuesStart[property] = this._valuesStartRepeat[property];
759
- }
760
- if (this._yoyo) {
761
- this._reversed = !this._reversed;
762
- }
763
- this._startTime += durationAndDelay * completeCount;
764
- if (this._onRepeatCallback) {
765
- this._onRepeatCallback(this._object);
766
- }
767
- this._onEveryStartCallbackFired = false;
768
- return true;
733
+ if (status === 'repeat' || status === 'about-to-repeat') {
734
+ if (this._onRepeatCallback) {
735
+ this._onRepeatCallback(this._object);
769
736
  }
770
- else {
771
- if (this._onCompleteCallback) {
772
- this._onCompleteCallback(this._object);
773
- }
774
- for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
775
- // Make the chained tweens start exactly at the time they should,
776
- // even if the `update()` method was called way past the duration of the tween
777
- this._chainedTweens[i].start(this._startTime + this._duration, false);
778
- }
779
- this._isPlaying = false;
780
- return false;
737
+ this._onEveryStartCallbackFired = false;
738
+ }
739
+ else if (status === 'completed') {
740
+ this._isPlaying = false;
741
+ if (this._onCompleteCallback) {
742
+ this._onCompleteCallback(this._object);
743
+ }
744
+ for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
745
+ // Make the chained tweens start exactly at the time they should,
746
+ // even if the `update()` method was called way past the duration of the tween
747
+ this._chainedTweens[i].start(this._startTime + this._duration, false);
781
748
  }
782
749
  }
783
- return true;
750
+ return status !== 'completed';
751
+ };
752
+ Tween.prototype._calculateElapsedPortion = function (elapsedTime, durationAndDelay, totalTime) {
753
+ if (this._duration === 0 || elapsedTime > totalTime) {
754
+ return 1;
755
+ }
756
+ var timeIntoCurrentRepeat = elapsedTime % durationAndDelay;
757
+ var portion = Math.min(timeIntoCurrentRepeat / this._duration, 1);
758
+ if (portion === 0 && elapsedTime !== 0 && elapsedTime % this._duration === 0) {
759
+ return 1;
760
+ }
761
+ return portion;
762
+ };
763
+ Tween.prototype._calculateCompletionStatus = function (elapsedTime, durationAndDelay) {
764
+ if (this._duration !== 0 && elapsedTime < this._duration) {
765
+ return 'playing';
766
+ }
767
+ if (this._repeat <= 0) {
768
+ return 'completed';
769
+ }
770
+ if (elapsedTime === this._duration) {
771
+ return 'about-to-repeat';
772
+ }
773
+ return 'repeat';
774
+ };
775
+ Tween.prototype._processRepetition = function (elapsedTime, durationAndDelay) {
776
+ var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
777
+ if (isFinite(this._repeat)) {
778
+ this._repeat -= completeCount;
779
+ }
780
+ // Reassign starting values, restart by making startTime = now
781
+ for (var property in this._valuesStartRepeat) {
782
+ var valueEnd = this._valuesEnd[property];
783
+ if (!this._yoyo && typeof valueEnd === 'string') {
784
+ this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(valueEnd);
785
+ }
786
+ if (this._yoyo) {
787
+ this._swapEndStartRepeatValues(property);
788
+ }
789
+ this._valuesStart[property] = this._valuesStartRepeat[property];
790
+ }
791
+ if (this._yoyo) {
792
+ this._reversed = !this._reversed;
793
+ }
794
+ this._startTime += durationAndDelay * completeCount;
784
795
  };
785
796
  Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {
786
797
  for (var property in _valuesEnd) {
@@ -836,7 +847,7 @@
836
847
  return Tween;
837
848
  }());
838
849
 
839
- var VERSION = '23.1.0';
850
+ var VERSION = '23.1.2';
840
851
 
841
852
  /**
842
853
  * Tween.js - Licensed under the MIT license
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tweenjs/tween.js",
3
3
  "description": "Simple and fast tweening engine with optimised Robert Penner's equations.",
4
- "version": "23.1.0",
4
+ "version": "23.1.2",
5
5
  "type": "module",
6
6
  "main": "dist/tween.cjs",
7
7
  "types": "dist/tween.d.ts",
@@ -39,10 +39,10 @@
39
39
  "tsc": "tsc",
40
40
  "tsc-watch": "tsc --watch",
41
41
  "examples": "npx serve .",
42
- "test": "npm run build && npm run test-lint && npm run test-unit",
42
+ "test": "npm run build && npm run format-check && npm run test-unit",
43
43
  "test-unit": "nodeunit test/unit/nodeunitheadless.cjs",
44
- "test-lint": "npm run prettier -- --check",
45
- "lint": "npm run prettier -- --write",
44
+ "format-check": "npm run prettier -- --check",
45
+ "format": "npm run prettier -- --write",
46
46
  "prettier": "prettier .",
47
47
  "prepare": "npm run build",
48
48
  "version": "npm test && git add .",