diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 77555299ec..dd3044145e 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -746,8 +746,7 @@ export default class ElementWrapper extends Wrapper { block.add_variable(transition); - block.chunks.mount.push(b`if (!${transition}) ${transition} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet});`); - block.chunks.hydrate.push(b`if (!${transition}) ${transition} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet});`); + block.chunks.hydrate.push(b`${transition} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet});`); if (intro.expression) { const dirty = block.renderer.dirty([intro.name,...Array.from(intro.expression.dependencies)]); block.chunks.update.push(b`if (${dirty}) ${transition}.u(${fn}, ${snippet});`); diff --git a/src/runtime/internal/loop.ts b/src/runtime/internal/loop.ts index f745b55ee3..8a07a2fca9 100644 --- a/src/runtime/internal/loop.ts +++ b/src/runtime/internal/loop.ts @@ -8,24 +8,6 @@ export const frame = { return n ? this.time : (this.time = now()); }, }; - -// function calc_framerate() { -// raf((t1) => { -// raf((t2) => { -// const delta = t2 - t1; -// raf((t3) => { -// if (Math.abs(t3 - t2 - delta) > 1) { -// calc_framerate(); -// } else { -// const f24 = 1000 / 24; -// const f144 = 1000 / 144; -// frame.rate = delta > f144 ? f144 : delta < f24 ? f24 : delta; -// } -// }); -// }); -// }); -// } -// calc_framerate(); type TaskCallback = (t: number) => boolean; type TaskCanceller = () => void; @@ -111,7 +93,7 @@ export const setTweenTimeout = ( ): TaskCanceller => { let t = 0.0; return loop((now) => { - t = 1 - (end_time - now) / duration; + t = 1.0 - (end_time - now) / duration; if (t >= 1.0) return run(1), stop(now), false; if (t >= 0.0) run(t); return true; diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts index 554704457a..d5a7d616a0 100644 --- a/src/runtime/internal/transitions.ts +++ b/src/runtime/internal/transitions.ts @@ -18,8 +18,8 @@ export interface CssTransitionConfig extends CssAnimationConfig { } export type TimeableConfig = Omit & { duration?: number | ((len: number) => number) }; const enum EasingStrategy { - reversed = "reversed", balanced = "balanced", + reversed = "reversed", mirrored = "mirrored", } const enum TransitionEvent { @@ -109,6 +109,14 @@ const reversed = (fn, is_intro, easing, start = 0, end = 1) => { : (t) => run(start + difference * t); }; +const balanced = (fn, is_intro, easing, start = 0, end = 1) => { + const run = swap(fn, is_intro); + const difference = end - start; + return easing + ? (t) => run(start + difference * easing(t)) + : (t) => run(start + difference * t); +}; + export const run_animation = /*#__PURE__*/ methodify(function (this: HTMLElement, from : Rect, fn: AnimationFn, params: CssTransitionConfig = {}) { let running = true; let cancel_css; @@ -144,10 +152,9 @@ export const run_in = /*#__PURE__*/ methodify(function (this: HTMLElement, fn: C add_measure_callback(() => { config = fn(this, params); return (current_frame_time) => { - let { delay = 0, duration = 300, easing, tick, css, strategy = EasingStrategy.balanced }: CssTransitionConfig = + let { delay = 0, duration = 300, easing, tick, css }: CssTransitionConfig = "function" === typeof config ? (config = config()) : config; - const solver = EasingStrategy.balanced === strategy ? reversed : mirrored; - const runner = (fn) => solver(fn, true, easing); + const runner = (fn) => balanced(fn, true, easing); end_time = current_frame_time + delay + duration; this.dispatchEvent(custom_event(TransitionEvent.introstart)); if (css) cancel_css = animate_css(this, runner(css), duration, delay); @@ -174,10 +181,9 @@ export const run_out = /*#__PURE__*/ methodify(function (this: HTMLElement, fn: add_measure_callback(() => { config = fn(this, params); return (current_frame_time) => { - let { delay = 0, duration = 300, easing, tick, css, strategy = EasingStrategy.balanced }: CssTransitionConfig = + let { delay = 0, duration = 300, easing, tick, css }: CssTransitionConfig = "function" === typeof config ? (config = config()) : config; - const solver = EasingStrategy.balanced === strategy ? reversed : mirrored; - const runner = (fn) => solver(fn, false, easing); + const runner = (fn) => balanced(fn, false, easing); end_time = current_frame_time + delay + duration; current_group.t = Math.max(end_time, current_group.t); if (current_group.s.push(stop) === current_group.r) { @@ -245,14 +251,19 @@ export const create_bidirectional_transition = /*#__PURE__*/ methodify(function( return (current_frame_time) => { let { tick, css, duration = 300.0, delay = 0.0, easing, strategy = EasingStrategy.balanced }: CssTransitionConfig = "function" === typeof config ? (config = config()) : config; - const solver = EasingStrategy.balanced === strategy ? reversed : mirrored; + const solver = EasingStrategy.balanced === strategy ? balanced : EasingStrategy.reversed === strategy ? reversed : mirrored; const runner = (fn) => solver(fn, is_intro, easing, ratio_left, 1); if (delayed_start) delay = 0; if (solver === reversed) duration -= prev_duration_left; + else if(solver === balanced) duration *= (1-ratio_left) else if (solver === mirrored) delay -= prev_duration_left; start_time = current_frame_time + delay; end_time = start_time + duration; - if (cancelled) return; + if (cancelled || duration < 1) return; + this.dispatchEvent(custom_event(is_intro ? TransitionEvent.introstart : TransitionEvent.outrostart)); + if (css) cancel_css = animate_css(this, runner(css), duration, delay); + if (tick) cancel_raf = setTweenTimeout(stop, end_time, runner(tick), duration); + else cancel_raf = setFrameTimeout(stop, end_time); if (!is_intro) { current_group.t = Math.max(end_time, current_group.t); if (current_group.s.push(stop) === current_group.r) { @@ -263,10 +274,6 @@ export const create_bidirectional_transition = /*#__PURE__*/ methodify(function( }, current_group.t); } } - this.dispatchEvent(custom_event(is_intro ? TransitionEvent.introstart : TransitionEvent.outrostart)); - if (css) cancel_css = animate_css(this, runner(css), duration, delay); - if (tick) cancel_raf = setTweenTimeout(is_intro ? stop : noop, end_time, runner(tick), duration); - else if (is_intro) cancel_raf = setFrameTimeout(stop, end_time); }; }; } @@ -277,7 +284,6 @@ export const create_bidirectional_transition = /*#__PURE__*/ methodify(function( cancelled = true; if (cancel_css) cancel_css(); if (cancel_raf) cancel_raf(); - if (1 === t && cancel_previous) cancel_previous(); } if (!config) return; const duration_left = end_time - t; @@ -286,18 +292,15 @@ export const create_bidirectional_transition = /*#__PURE__*/ methodify(function( }; const stop: StopResetReverseFn = (t?: number | -1 | 1) => { + if (t >= end_time) { + if (pending === 1 && (is_intro || t >= current_group.t)) cancel(t); + this.dispatchEvent(custom_event(is_intro ? TransitionEvent.introend : TransitionEvent.outroend)); + } if (running) { running = false; - if (config) { - if (t >= end_time) { - if (!is_intro && "tick" in config) config.tick(0, 1); - if (pending === 1) cancel(t); - this.dispatchEvent(custom_event(is_intro ? TransitionEvent.introend : TransitionEvent.outroend)); - } - if (!is_intro) { - if (!--current_group.r) { - for (let i = 0, { c } = current_group, r = t === 1; i < c.length; i++) c[i](r); - } + if (config && !is_intro && !--current_group.r) { + for (let i = 0, { c } = current_group, r = Math.abs(t) === 1; i < c.length; i++) { + c[i](r); } } } diff --git a/test/runtime/samples/transition-js-events/_config.js b/test/runtime/samples/transition-js-events/_config.js index 00d83cb275..891f8f0382 100644 --- a/test/runtime/samples/transition-js-events/_config.js +++ b/test/runtime/samples/transition-js-events/_config.js @@ -10,7 +10,7 @@ export default {

waiting...

`, - async test({ assert, component, target, raf }) { + test({ assert, component, target, raf }) { component.visible = true; assert.htmlEqual(target.innerHTML, ` @@ -25,7 +25,7 @@ export default { assert.deepEqual(component.intros.sort(), ['a', 'b', 'c', 'd']); assert.equal(component.intro_count, 4); - await raf.tick(100); + raf.tick(100); assert.equal(component.intro_count, 0); assert.htmlEqual(target.innerHTML, ` @@ -55,7 +55,7 @@ export default { component.visible = true; - await raf.tick(250); + raf.tick(250); assert.deepEqual(component.intros.sort(), ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'd']); assert.equal(component.intro_count, 4);