|
|
|
@ -256,6 +256,44 @@ function handle_raf(time) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {{(t: number): number;(t: number): number;(arg0: number): any;}} easing_fn
|
|
|
|
|
* @param {((t: number, u: number) => string)} css_fn
|
|
|
|
|
* @param {number} duration
|
|
|
|
|
* @param {string} direction
|
|
|
|
|
* @param {boolean} reverse
|
|
|
|
|
*/
|
|
|
|
|
function create_keyframes(easing_fn, css_fn, duration, direction, reverse) {
|
|
|
|
|
/** @type {Keyframe[]} */
|
|
|
|
|
const keyframes = [];
|
|
|
|
|
// We need at least two frames
|
|
|
|
|
const frame_time = 16.666;
|
|
|
|
|
const max_duration = Math.max(duration, frame_time);
|
|
|
|
|
// Have a keyframe every fame for 60 FPS
|
|
|
|
|
for (let i = 0; i <= max_duration; i += frame_time) {
|
|
|
|
|
let time;
|
|
|
|
|
if (i + frame_time > max_duration) {
|
|
|
|
|
time = 1;
|
|
|
|
|
} else if (i === 0) {
|
|
|
|
|
time = 0;
|
|
|
|
|
} else {
|
|
|
|
|
time = i / max_duration;
|
|
|
|
|
}
|
|
|
|
|
let t = easing_fn(time);
|
|
|
|
|
if (reverse) {
|
|
|
|
|
t = 1 - t;
|
|
|
|
|
}
|
|
|
|
|
keyframes.push(css_to_keyframe(css_fn(t, 1 - t)));
|
|
|
|
|
}
|
|
|
|
|
if (direction === 'out' || reverse) {
|
|
|
|
|
keyframes.reverse();
|
|
|
|
|
}
|
|
|
|
|
return keyframes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @param {number} t */
|
|
|
|
|
const linear = (t) => t;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {HTMLElement} dom
|
|
|
|
|
* @param {() => import('./types.js').TransitionPayload} init
|
|
|
|
@ -286,38 +324,15 @@ function create_transition(dom, init, direction, effect) {
|
|
|
|
|
const delay = payload.delay ?? 0;
|
|
|
|
|
const css_fn = payload.css;
|
|
|
|
|
const tick_fn = payload.tick;
|
|
|
|
|
|
|
|
|
|
/** @param {number} t */
|
|
|
|
|
const linear = (t) => t;
|
|
|
|
|
const easing_fn = payload.easing || linear;
|
|
|
|
|
|
|
|
|
|
/** @type {Keyframe[]} */
|
|
|
|
|
const keyframes = [];
|
|
|
|
|
|
|
|
|
|
if (typeof tick_fn === 'function') {
|
|
|
|
|
animation = new TickAnimation(tick_fn, duration, delay, direction === 'out');
|
|
|
|
|
} else {
|
|
|
|
|
if (typeof css_fn === 'function') {
|
|
|
|
|
// We need at least two frames
|
|
|
|
|
const frame_time = 16.666;
|
|
|
|
|
const max_duration = Math.max(duration, frame_time);
|
|
|
|
|
// Have a keyframe every fame for 60 FPS
|
|
|
|
|
for (let i = 0; i <= max_duration; i += frame_time) {
|
|
|
|
|
let time;
|
|
|
|
|
if (i + frame_time > max_duration) {
|
|
|
|
|
time = 1;
|
|
|
|
|
} else if (i === 0) {
|
|
|
|
|
time = 0;
|
|
|
|
|
} else {
|
|
|
|
|
time = i / max_duration;
|
|
|
|
|
}
|
|
|
|
|
const t = easing_fn(time);
|
|
|
|
|
keyframes.push(css_to_keyframe(css_fn(t, 1 - t)));
|
|
|
|
|
}
|
|
|
|
|
if (direction === 'out') {
|
|
|
|
|
keyframes.reverse();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const keyframes =
|
|
|
|
|
typeof css_fn === 'function'
|
|
|
|
|
? create_keyframes(easing_fn, css_fn, duration, direction, false)
|
|
|
|
|
: [];
|
|
|
|
|
animation = dom.animate(keyframes, {
|
|
|
|
|
duration,
|
|
|
|
|
endDelay: delay,
|
|
|
|
@ -421,6 +436,26 @@ function create_transition(dom, init, direction, effect) {
|
|
|
|
|
} else {
|
|
|
|
|
dispatch_event(dom, 'outrostart');
|
|
|
|
|
if (needs_reverse) {
|
|
|
|
|
const payload = transition.p;
|
|
|
|
|
const current_animation = /** @type {Animation} */ (animation);
|
|
|
|
|
// If we are working with CSS animations, then before we call reverse, we also need to ensure
|
|
|
|
|
// that we reverse the easing logic. To do this we need to re-create the keyframes so they're
|
|
|
|
|
// in reverse with easing properly reversed too.
|
|
|
|
|
if (
|
|
|
|
|
payload !== null &&
|
|
|
|
|
payload.css !== undefined &&
|
|
|
|
|
current_animation.playState === 'idle'
|
|
|
|
|
) {
|
|
|
|
|
const duration = payload.duration ?? 300;
|
|
|
|
|
const css_fn = payload.css;
|
|
|
|
|
const easing_fn = payload.easing || linear;
|
|
|
|
|
const keyframes = create_keyframes(easing_fn, css_fn, duration, direction, true);
|
|
|
|
|
const effect = current_animation.effect;
|
|
|
|
|
if (effect !== null) {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
effect.setKeyframes(keyframes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/** @type {Animation | TickAnimation} */ (animation).reverse();
|
|
|
|
|
} else {
|
|
|
|
|
/** @type {Animation | TickAnimation} */ (animation).play();
|
|
|
|
|