Skip to content

Commit 00c0004

Browse files
committed
feature: implement group-level onComplete callback, triggering both group and individual tween completion callbacks
1 parent eb07dd2 commit 00c0004

File tree

8 files changed

+124
-0
lines changed

8 files changed

+124
-0
lines changed

dist/tween.amd.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,18 @@ define(['exports'], (function (exports) { 'use strict';
296296
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
297297
}
298298
};
299+
Group.prototype.onComplete = function (callback) {
300+
var group = this.getAll();
301+
group.forEach(function (tween) {
302+
var prevCallback = tween.getCompleteCallback();
303+
tween.onComplete(function () {
304+
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
305+
// Since _isPlaying is updated to false after the onComplete callback finishes, the final tween is omitted from the check to determine if all animations have completed
306+
if (group.slice(0, group.length - 1).every(function (t) { return !t.isPlaying(); }))
307+
callback(group);
308+
});
309+
});
310+
};
299311
return Group;
300312
}());
301313

@@ -442,6 +454,9 @@ define(['exports'], (function (exports) { 'use strict';
442454
Tween.prototype.getId = function () {
443455
return this._id;
444456
};
457+
Tween.prototype.getCompleteCallback = function () {
458+
return this._onCompleteCallback;
459+
};
445460
Tween.prototype.isPlaying = function () {
446461
return this._isPlaying;
447462
};

dist/tween.cjs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,18 @@ var Group = /** @class */ (function () {
298298
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
299299
}
300300
};
301+
Group.prototype.onComplete = function (callback) {
302+
var group = this.getAll();
303+
group.forEach(function (tween) {
304+
var prevCallback = tween.getCompleteCallback();
305+
tween.onComplete(function () {
306+
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
307+
// Since _isPlaying is updated to false after the onComplete callback finishes, the final tween is omitted from the check to determine if all animations have completed
308+
if (group.slice(0, group.length - 1).every(function (t) { return !t.isPlaying(); }))
309+
callback(group);
310+
});
311+
});
312+
};
301313
return Group;
302314
}());
303315

@@ -444,6 +456,9 @@ var Tween = /** @class */ (function () {
444456
Tween.prototype.getId = function () {
445457
return this._id;
446458
};
459+
Tween.prototype.getCompleteCallback = function () {
460+
return this._onCompleteCallback;
461+
};
447462
Tween.prototype.isPlaying = function () {
448463
return this._isPlaying;
449464
};

dist/tween.d.ts

Lines changed: 2 additions & 0 deletions
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,6 +182,7 @@ 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;

dist/tween.esm.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,18 @@ var Group = /** @class */ (function () {
294294
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
295295
}
296296
};
297+
Group.prototype.onComplete = function (callback) {
298+
var group = this.getAll();
299+
group.forEach(function (tween) {
300+
var prevCallback = tween.getCompleteCallback();
301+
tween.onComplete(function () {
302+
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
303+
// Since _isPlaying is updated to false after the onComplete callback finishes, the final tween is omitted from the check to determine if all animations have completed
304+
if (group.slice(0, group.length - 1).every(function (t) { return !t.isPlaying(); }))
305+
callback(group);
306+
});
307+
});
308+
};
297309
return Group;
298310
}());
299311

@@ -440,6 +452,9 @@ var Tween = /** @class */ (function () {
440452
Tween.prototype.getId = function () {
441453
return this._id;
442454
};
455+
Tween.prototype.getCompleteCallback = function () {
456+
return this._onCompleteCallback;
457+
};
443458
Tween.prototype.isPlaying = function () {
444459
return this._isPlaying;
445460
};

dist/tween.umd.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,18 @@
300300
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
301301
}
302302
};
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+
// Since _isPlaying is updated to false after the onComplete callback finishes, the final tween is omitted from the check to determine if all animations have completed
310+
if (group.slice(0, group.length - 1).every(function (t) { return !t.isPlaying(); }))
311+
callback(group);
312+
});
313+
});
314+
};
303315
return Group;
304316
}());
305317

@@ -446,6 +458,9 @@
446458
Tween.prototype.getId = function () {
447459
return this._id;
448460
};
461+
Tween.prototype.getCompleteCallback = function () {
462+
return this._onCompleteCallback;
463+
};
449464
Tween.prototype.isPlaying = function () {
450465
return this._isPlaying;
451466
};

src/Group.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,15 @@ 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+
// Since _isPlaying is updated to false after the onComplete callback finishes, the final tween is omitted from the check to determine if all animations have completed
94+
if (group.slice(0, group.length - 1).every(t => !t.isPlaying())) callback(group)
95+
})
96+
})
97+
}
8798
}

src/Tween.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ export class Tween<T extends UnknownProps = any> {
8383
return this._id
8484
}
8585

86+
getCompleteCallback(): ((object: T) => void) | undefined {
87+
return this._onCompleteCallback
88+
}
89+
8690
isPlaying(): boolean {
8791
return this._isPlaying
8892
}

src/tests.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,53 @@ export const tests = {
20602060
test.ok(group.getAll() instanceof Array)
20612061
test.done()
20622062
},
2063+
'Custom group.onComplete() should be triggered when all Tweens in the group have reached their completion, and the child Tween.onComplete() should also be fired'(
2064+
test: Test,
2065+
): void {
2066+
TWEEN.removeAll()
2067+
2068+
const t = new TWEEN.Tween({x: 1}),
2069+
t2 = new TWEEN.Tween({x: 1}, true),
2070+
group = new TWEEN.Group()
2071+
let groupCounter = 0,
2072+
childCounter = 0,
2073+
childCounter2 = 0
2074+
2075+
group.add(t)
2076+
group.add(t2)
2077+
2078+
t.to({x: 2}, 1000)
2079+
t2.to({x: 2}, 2000)
2080+
2081+
t.onComplete(function (): void {
2082+
childCounter++
2083+
})
2084+
t2.onComplete(function (): void {
2085+
childCounter2++
2086+
})
2087+
group.onComplete(function (): void {
2088+
groupCounter++
2089+
})
2090+
2091+
t.start(0)
2092+
t2.start(0)
2093+
2094+
group.update(0)
2095+
test.deepEqual(groupCounter, 0)
2096+
test.deepEqual(childCounter, 0)
2097+
test.deepEqual(childCounter2, 0)
2098+
2099+
group.update(1000)
2100+
test.deepEqual(groupCounter, 0)
2101+
test.deepEqual(childCounter, 1)
2102+
test.deepEqual(childCounter2, 0)
2103+
2104+
group.update(2000)
2105+
test.deepEqual(childCounter, 1)
2106+
test.deepEqual(groupCounter, 1)
2107+
test.deepEqual(childCounter2, 1)
2108+
test.done()
2109+
},
20632110

20642111
'Custom group stores tweens instead of global TWEEN group'(test: Test): void {
20652112
const group = new TWEEN.Group()

0 commit comments

Comments
 (0)