diff --git a/.changeset/lazy-masks-sit.md b/.changeset/lazy-masks-sit.md new file mode 100644 index 000000000..553bbf4a6 --- /dev/null +++ b/.changeset/lazy-masks-sit.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure transitions properly cancel on completion diff --git a/packages/svelte/src/internal/client/transitions.js b/packages/svelte/src/internal/client/transitions.js index 27db05fdd..d55dbbba5 100644 --- a/packages/svelte/src/internal/client/transitions.js +++ b/packages/svelte/src/internal/client/transitions.js @@ -177,9 +177,12 @@ class TickAnimation { } cancel() { - const t = this.#reversed ? 1 : 0; active_tick_animations.delete(this); - this.#tick_fn(t, 1 - t); + const current = this.#current / this.#duration; + if (current > 0 && current < 1) { + const t = this.#reversed ? 1 : 0; + this.#tick_fn(t, 1 - t); + } } finish() { @@ -322,7 +325,7 @@ function create_transition(dom, init, direction, effect) { animation.onfinish = () => { const is_outro = curr_direction === 'out'; - /** @type {Animation | TickAnimation} */ (animation).pause(); + /** @type {Animation | TickAnimation} */ (animation).cancel(); if (is_outro) { run_all(subs); subs = []; diff --git a/packages/svelte/tests/animation-helpers.js b/packages/svelte/tests/animation-helpers.js index 8855d813b..21635a05b 100644 --- a/packages/svelte/tests/animation-helpers.js +++ b/packages/svelte/tests/animation-helpers.js @@ -102,16 +102,18 @@ class Animation { } finish() { + this.onfinish(); this.currentTime = this.#reversed ? 0 : this.#duration; if (this.#reversed) { raf.animations.delete(this); } - this.onfinish(); } cancel() { - this._applyKeyFrame(this.#reversed ? this.#keyframes.length - 1 : 0); - raf.animations.delete(this); + this.#paused = true; + if (this.currentTime > 0 && this.currentTime < this.#duration) { + this._applyKeyFrame(this.#reversed ? this.#keyframes.length - 1 : 0); + } } pause() {