Skip to content

Commit 6be3b9d

Browse files
committed
Merge branch 'main' into fix-yoyo-wrong-by-calculateElapsedPortion
* main: code formatting update tests.yml: use npm ci instead of npm i for reproducible builds Update tests.yml: update setup-node action version Update tests.yml to use the latest LTS version of Node.js #697: Added a section in the user-guide regarding the new "setNow" functionality. #697: Added the ability to override the internal "now" function using the "setNow" function. fix: Fixed error when registered tweens are not completed in order fix: Fixed error when registered tweens are not completed in order test: add test tween unit feature: implement group-level onComplete callback, triggering both group and individual tween completion callbacks
2 parents a1e04c4 + 20079e6 commit 6be3b9d

File tree

13 files changed

+224
-15
lines changed

13 files changed

+224
-15
lines changed

.github/workflows/tests.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
22
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
33

4-
name: build and tests
4+
name: build and test
55

66
on: [push]
77

88
jobs:
9-
build:
9+
build-and-test:
1010
runs-on: ubuntu-latest
1111

1212
strategy:
1313
matrix:
14-
node-version: [16.x, 18.x, 20.x]
14+
node-version: [lts/*]
1515

1616
steps:
1717
- uses: actions/checkout@v2
1818
- name: Use Node.js ${{ matrix.node-version }}
19-
uses: actions/setup-node@v1
19+
uses: actions/setup-node@v4
2020
with:
2121
node-version: ${{ matrix.node-version }}
22-
- run: npm install
22+
- run: npm clean-install
2323
- run: npm test

dist/tween.amd.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,13 @@ define(['exports'], (function (exports) { 'use strict';
215215
},
216216
});
217217

218-
var now = function () { return performance.now(); };
218+
var _nowFunc = function () { return performance.now(); };
219+
var now = function () {
220+
return _nowFunc();
221+
};
222+
function setNow(nowFunction) {
223+
_nowFunc = nowFunction;
224+
}
219225

220226
/**
221227
* Controlling groups of tweens
@@ -296,6 +302,19 @@ define(['exports'], (function (exports) { 'use strict';
296302
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
297303
}
298304
};
305+
Group.prototype.onComplete = function (callback) {
306+
var group = this.getAll();
307+
group.forEach(function (tween) {
308+
var prevCallback = tween.getCompleteCallback();
309+
tween.onComplete(function () {
310+
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
311+
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
312+
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
313+
if (completedGroup.length === group.length - 1)
314+
callback(group);
315+
});
316+
});
317+
};
299318
return Group;
300319
}());
301320

@@ -442,6 +461,9 @@ define(['exports'], (function (exports) { 'use strict';
442461
Tween.prototype.getId = function () {
443462
return this._id;
444463
};
464+
Tween.prototype.getCompleteCallback = function () {
465+
return this._onCompleteCallback;
466+
};
445467
Tween.prototype.isPlaying = function () {
446468
return this._isPlaying;
447469
};
@@ -1132,6 +1154,7 @@ define(['exports'], (function (exports) { 'use strict';
11321154
Group: Group,
11331155
Interpolation: Interpolation,
11341156
now: now,
1157+
setNow: setNow,
11351158
Sequence: Sequence,
11361159
nextId: nextId,
11371160
Tween: Tween,
@@ -1391,6 +1414,7 @@ define(['exports'], (function (exports) { 'use strict';
13911414
exports.now = now;
13921415
exports.remove = remove;
13931416
exports.removeAll = removeAll;
1417+
exports.setNow = setNow;
13941418
exports.update = update;
13951419

13961420
Object.defineProperty(exports, '__esModule', { value: true });

dist/tween.cjs

+25-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,13 @@ var Easing = Object.freeze({
217217
},
218218
});
219219

220-
var now = function () { return performance.now(); };
220+
var _nowFunc = function () { return performance.now(); };
221+
var now = function () {
222+
return _nowFunc();
223+
};
224+
function setNow(nowFunction) {
225+
_nowFunc = nowFunction;
226+
}
221227

222228
/**
223229
* Controlling groups of tweens
@@ -298,6 +304,19 @@ var Group = /** @class */ (function () {
298304
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
299305
}
300306
};
307+
Group.prototype.onComplete = function (callback) {
308+
var group = this.getAll();
309+
group.forEach(function (tween) {
310+
var prevCallback = tween.getCompleteCallback();
311+
tween.onComplete(function () {
312+
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
313+
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
314+
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
315+
if (completedGroup.length === group.length - 1)
316+
callback(group);
317+
});
318+
});
319+
};
301320
return Group;
302321
}());
303322

@@ -444,6 +463,9 @@ var Tween = /** @class */ (function () {
444463
Tween.prototype.getId = function () {
445464
return this._id;
446465
};
466+
Tween.prototype.getCompleteCallback = function () {
467+
return this._onCompleteCallback;
468+
};
447469
Tween.prototype.isPlaying = function () {
448470
return this._isPlaying;
449471
};
@@ -1134,6 +1156,7 @@ var exports$1 = {
11341156
Group: Group,
11351157
Interpolation: Interpolation,
11361158
now: now,
1159+
setNow: setNow,
11371160
Sequence: Sequence,
11381161
nextId: nextId,
11391162
Tween: Tween,
@@ -1393,4 +1416,5 @@ exports.nextId = nextId;
13931416
exports.now = now;
13941417
exports.remove = remove;
13951418
exports.removeAll = removeAll;
1419+
exports.setNow = setNow;
13961420
exports.update = update;

dist/tween.d.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ declare class Tween<T extends UnknownProps = any> {
9898
*/
9999
constructor(object: T, group: true);
100100
getId(): number;
101+
getCompleteCallback(): ((object: T) => void) | undefined;
101102
isPlaying(): boolean;
102103
isPaused(): boolean;
103104
getDuration(): number;
@@ -181,9 +182,11 @@ declare class Group {
181182
* tweens, and do not rely on tweens being automatically added or removed.
182183
*/
183184
update(time?: number, preserve?: boolean): void;
185+
onComplete(callback: (object: Tween[]) => void): void;
184186
}
185187

186188
declare const now: () => number;
189+
declare function setNow(nowFunction: Function): void;
187190

188191
/**
189192
* Utils
@@ -470,6 +473,7 @@ declare const exports: {
470473
};
471474
};
472475
now: () => number;
476+
setNow: typeof setNow;
473477
Sequence: typeof Sequence;
474478
nextId: typeof Sequence.nextId;
475479
Tween: typeof Tween;
@@ -719,4 +723,4 @@ declare const exports: {
719723
};
720724
};
721725

722-
export { Easing, Group, Interpolation, Sequence, Tween, VERSION, add, exports as default, getAll, nextId, now, remove, removeAll, update };
726+
export { Easing, Group, Interpolation, Sequence, Tween, VERSION, add, exports as default, getAll, nextId, now, remove, removeAll, setNow, update };

dist/tween.esm.js

+25-2
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,13 @@ var Easing = Object.freeze({
213213
},
214214
});
215215

216-
var now = function () { return performance.now(); };
216+
var _nowFunc = function () { return performance.now(); };
217+
var now = function () {
218+
return _nowFunc();
219+
};
220+
function setNow(nowFunction) {
221+
_nowFunc = nowFunction;
222+
}
217223

218224
/**
219225
* Controlling groups of tweens
@@ -294,6 +300,19 @@ var Group = /** @class */ (function () {
294300
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
295301
}
296302
};
303+
Group.prototype.onComplete = function (callback) {
304+
var group = this.getAll();
305+
group.forEach(function (tween) {
306+
var prevCallback = tween.getCompleteCallback();
307+
tween.onComplete(function () {
308+
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
309+
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
310+
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
311+
if (completedGroup.length === group.length - 1)
312+
callback(group);
313+
});
314+
});
315+
};
297316
return Group;
298317
}());
299318

@@ -440,6 +459,9 @@ var Tween = /** @class */ (function () {
440459
Tween.prototype.getId = function () {
441460
return this._id;
442461
};
462+
Tween.prototype.getCompleteCallback = function () {
463+
return this._onCompleteCallback;
464+
};
443465
Tween.prototype.isPlaying = function () {
444466
return this._isPlaying;
445467
};
@@ -1130,6 +1152,7 @@ var exports = {
11301152
Group: Group,
11311153
Interpolation: Interpolation,
11321154
now: now,
1155+
setNow: setNow,
11331156
Sequence: Sequence,
11341157
nextId: nextId,
11351158
Tween: Tween,
@@ -1376,4 +1399,4 @@ var exports = {
13761399
update: update,
13771400
};
13781401

1379-
export { Easing, Group, Interpolation, Sequence, Tween, VERSION, add, exports as default, getAll, nextId, now, remove, removeAll, update };
1402+
export { Easing, Group, Interpolation, Sequence, Tween, VERSION, add, exports as default, getAll, nextId, now, remove, removeAll, setNow, update };

dist/tween.umd.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,13 @@
219219
},
220220
});
221221

222-
var now = function () { return performance.now(); };
222+
var _nowFunc = function () { return performance.now(); };
223+
var now = function () {
224+
return _nowFunc();
225+
};
226+
function setNow(nowFunction) {
227+
_nowFunc = nowFunction;
228+
}
223229

224230
/**
225231
* Controlling groups of tweens
@@ -300,6 +306,19 @@
300306
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
301307
}
302308
};
309+
Group.prototype.onComplete = function (callback) {
310+
var group = this.getAll();
311+
group.forEach(function (tween) {
312+
var prevCallback = tween.getCompleteCallback();
313+
tween.onComplete(function () {
314+
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
315+
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
316+
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
317+
if (completedGroup.length === group.length - 1)
318+
callback(group);
319+
});
320+
});
321+
};
303322
return Group;
304323
}());
305324

@@ -446,6 +465,9 @@
446465
Tween.prototype.getId = function () {
447466
return this._id;
448467
};
468+
Tween.prototype.getCompleteCallback = function () {
469+
return this._onCompleteCallback;
470+
};
449471
Tween.prototype.isPlaying = function () {
450472
return this._isPlaying;
451473
};
@@ -1136,6 +1158,7 @@
11361158
Group: Group,
11371159
Interpolation: Interpolation,
11381160
now: now,
1161+
setNow: setNow,
11391162
Sequence: Sequence,
11401163
nextId: nextId,
11411164
Tween: Tween,
@@ -1395,6 +1418,7 @@
13951418
exports.now = now;
13961419
exports.remove = remove;
13971420
exports.removeAll = removeAll;
1421+
exports.setNow = setNow;
13981422
exports.update = update;
13991423

14001424
Object.defineProperty(exports, '__esModule', { value: true });

docs/user_guide.md

+6
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,12 @@ Note that the interpolation function is global to all properties that are tweene
642642

643643
Check [06_array_interpolation](../examples/06_array_interpolation.html) for an example.
644644

645+
## Changing the Definition of "Now"
646+
647+
When working with tweening, you inevitably rely on a definition of what "now" is. By default, Tween.js uses performance.now, which is a reliable and precise approach. However, if you need to adjust the flow of time—for instance, to slow it down or manipulate it for a custom purpose—you may encounter discrepancies between your internal definition of "now" and what Tween.js considers "now."
648+
649+
To address this, a new function, setNow, has been introduced. This function allows you to redefine the internal "now" used by Tween.js. You can pass a custom function to setNow, which will replace the default definition. This provides greater flexibility and enables synchronization with your specific requirements for time control.
650+
645651
## Getting the best performance
646652

647653
While Tween.js tries to be performant on its own, nothing prevents you from using it in a way that is counterperformant. Here are some of the ways you can avoid slowing down your projects when using Tween.js (or when animating in the web, in general).

scripts/write-version.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import fs from 'fs'
2-
import pkg from '../package.json' assert {type: 'json'}
2+
import pkg from '../package.json' with {type: 'json'}
33

44
const {version} = pkg
55

src/Group.ts

+12
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,16 @@ export default class Group {
8484
tweenIds = Object.keys(this._tweensAddedDuringUpdate)
8585
}
8686
}
87+
onComplete(callback: (object: Tween[]) => void) {
88+
const group = this.getAll()
89+
group.forEach(tween => {
90+
const prevCallback = tween.getCompleteCallback()
91+
tween.onComplete(() => {
92+
prevCallback?.(tween)
93+
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
94+
const completedGroup = group.filter(tween => !tween.isPlaying())
95+
if (completedGroup.length === group.length - 1) callback(group)
96+
})
97+
})
98+
}
8799
}

src/Index.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import Easing from './Easing'
1111
import Group from './Group'
1212
import Interpolation from './Interpolation'
13-
import now from './Now'
13+
import now, {setNow} from './Now'
1414
import Sequence from './Sequence'
1515
import Tween from './Tween'
1616
import VERSION from './Version'
@@ -273,13 +273,29 @@ const update = TWEEN.update.bind(TWEEN)
273273

274274
// NOTE! Make sure both lists of exports below are kept in sync:
275275

276-
export {Easing, Group, Interpolation, now, Sequence, nextId, Tween, VERSION, getAll, removeAll, add, remove, update}
276+
export {
277+
Easing,
278+
Group,
279+
Interpolation,
280+
now,
281+
setNow,
282+
Sequence,
283+
nextId,
284+
Tween,
285+
VERSION,
286+
getAll,
287+
removeAll,
288+
add,
289+
remove,
290+
update,
291+
}
277292

278293
const exports = {
279294
Easing,
280295
Group,
281296
Interpolation,
282297
now,
298+
setNow,
283299
Sequence,
284300
nextId,
285301
Tween,

src/Now.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1-
const now = (): number => performance.now()
1+
let _nowFunc: Function = () => performance.now()
2+
3+
const now = (): number => {
4+
return _nowFunc()
5+
}
6+
7+
export function setNow(nowFunction: Function) {
8+
_nowFunc = nowFunction
9+
}
210

311
export default now

0 commit comments

Comments
 (0)