From 92307c8ef9595820af951ab87443592e0746ffc6 Mon Sep 17 00:00:00 2001 From: h_0315 Date: Sun, 8 Feb 2026 16:36:24 +0900 Subject: [PATCH] Add onStop callback for animation completion and cancellation Implements feature request from issue #1044 to add a unified callback that fires when animations either complete naturally or are cancelled/ interrupted by other animations. Changes: - Add onStop callback to Timer class that is called when: * Animation completes naturally (called after onComplete) * Animation is cancelled/interrupted (called without onComplete) - Update type definitions to include onStop in all callback interfaces - Add onStop to default callbacks in globals - Update render logic to call onStop alongside onComplete - Maintain backward compatibility with all existing callbacks This allows developers to reliably track when animations end regardless of whether they complete or are interrupted, solving the use case of managing animation counters and CSS transitions. Fixes #1044 --- src/core/globals.js | 1 + src/core/render.js | 4 ++++ src/timer/timer.js | 5 +++++ src/types/index.js | 2 ++ 4 files changed, 12 insertions(+) diff --git a/src/core/globals.js b/src/core/globals.js index c9199eb33..27fd60980 100644 --- a/src/core/globals.js +++ b/src/core/globals.js @@ -43,6 +43,7 @@ export const defaults = { onLoop: noop, onPause: noop, onComplete: noop, + onStop: noop, onRender: noop, } diff --git a/src/core/render.js b/src/core/render.js index 27a8fb145..44cc34842 100644 --- a/src/core/render.js +++ b/src/core/render.js @@ -299,6 +299,7 @@ export const render = (tickable, time, muteCallbacks, internalRender, tickMode) (isRunningBackwards && tickableAbsoluteTime <= minValue && completed) )) { tickable.onComplete(/** @type {CallbackArgument} */(tickable)); + tickable.onStop(/** @type {CallbackArgument} */(tickable)); tickable.completed = !isRunningBackwards; } // If currentTime is both above 0 and at least equals to duration, handles normal onComplete or infinite loops @@ -314,6 +315,7 @@ export const render = (tickable, time, muteCallbacks, internalRender, tickMode) tickable.completed = true; if (!muteCallbacks && !(parent && (isRunningBackwards || !parent.began))) { tickable.onComplete(/** @type {CallbackArgument} */(tickable)); + tickable.onStop(/** @type {CallbackArgument} */(tickable)); tickable._resolve(/** @type {CallbackArgument} */(tickable)); } } @@ -366,6 +368,7 @@ export const tick = (tickable, time, muteCallbacks, internalRender, tickMode) => // Triggers the onComplete callback on reverse for children on the edges of the timeline if (!muteCallbacks && childDuration <= minValue && (!childStartTime || childEndTime === tlIterationDuration)) { child.onComplete(child); + child.onStop(child); } } }); @@ -390,6 +393,7 @@ export const tick = (tickable, time, muteCallbacks, internalRender, tickMode) => tl.completed = true; if (!muteCallbacks) { tl.onComplete(/** @type {CallbackArgument} */(tl)); + tl.onStop(/** @type {CallbackArgument} */(tl)); tl._resolve(/** @type {CallbackArgument} */(tl)); } } diff --git a/src/timer/timer.js b/src/timer/timer.js index 87fda73f9..547a459d9 100644 --- a/src/timer/timer.js +++ b/src/timer/timer.js @@ -126,6 +126,7 @@ export class Timer extends Clock { onComplete, onLoop, onPause, + onStop, onBegin, onBeforeUpdate, onUpdate, @@ -182,6 +183,8 @@ export class Timer extends Clock { this.onPause = onPause || timerDefaults.onPause; /** @type {Callback} */ this.onComplete = onComplete || timerDefaults.onComplete; + /** @type {Callback} */ + this.onStop = onStop || timerDefaults.onStop; /** @type {Number} */ this.iterationDuration = timerDuration; // Duration of one loop /** @type {Number} */ @@ -445,6 +448,8 @@ export class Timer extends Clock { forEachChildren(this, removeTweenSliblings); } this._cancelled = 1; + // Call onStop callback when animation is cancelled/interrupted + this.onStop(this); // Pausing the timer removes it from the engine return this.pause(); } diff --git a/src/types/index.js b/src/types/index.js index d7c44928a..f73743cbf 100644 --- a/src/types/index.js +++ b/src/types/index.js @@ -46,6 +46,7 @@ export {} * @property {Callback} [onLoop] * @property {Callback} [onPause] * @property {Callback} [onComplete] + * @property {Callback} [onStop] * @property {Callback} [onRender] */ @@ -167,6 +168,7 @@ export {} * @property {Callback} [onLoop] * @property {Callback} [onPause] * @property {Callback} [onComplete] + * @property {Callback} [onStop] */ /**