|
|
|
|
@ -116,174 +116,6 @@ function css_to_keyframe(css) {
|
|
|
|
|
return keyframe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TickAnimation {
|
|
|
|
|
/** @type {null | (() => void)} */
|
|
|
|
|
onfinish;
|
|
|
|
|
|
|
|
|
|
/** @type {(t: number, u: number) => string} */
|
|
|
|
|
#tick_fn;
|
|
|
|
|
|
|
|
|
|
/** @type {number} */
|
|
|
|
|
#duration;
|
|
|
|
|
|
|
|
|
|
/** @type {number} */
|
|
|
|
|
#current;
|
|
|
|
|
|
|
|
|
|
/** @type {number} */
|
|
|
|
|
#delay;
|
|
|
|
|
|
|
|
|
|
/** @type {number} */
|
|
|
|
|
#previous;
|
|
|
|
|
|
|
|
|
|
/** @type {boolean} */
|
|
|
|
|
paused;
|
|
|
|
|
|
|
|
|
|
/** @type {boolean} */
|
|
|
|
|
#reversed;
|
|
|
|
|
|
|
|
|
|
/** @type {number} */
|
|
|
|
|
#delay_current;
|
|
|
|
|
|
|
|
|
|
/** @type {boolean} */
|
|
|
|
|
#delayed_reverse;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {(t: number, u: number) => string} tick_fn
|
|
|
|
|
* @param {number} duration
|
|
|
|
|
* @param {number} delay
|
|
|
|
|
* @param {boolean} out
|
|
|
|
|
*/
|
|
|
|
|
constructor(tick_fn, duration, delay, out) {
|
|
|
|
|
this.#duration = duration;
|
|
|
|
|
this.#delay = delay;
|
|
|
|
|
this.paused = false;
|
|
|
|
|
this.#tick_fn = tick_fn;
|
|
|
|
|
this.#reversed = out;
|
|
|
|
|
this.#delay_current = delay;
|
|
|
|
|
this.#current = out ? duration : 0;
|
|
|
|
|
this.#previous = 0;
|
|
|
|
|
this.#delayed_reverse = false;
|
|
|
|
|
this.onfinish = null;
|
|
|
|
|
if (this.#delay) {
|
|
|
|
|
if (!out) {
|
|
|
|
|
this.#tick_fn(0, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pause() {
|
|
|
|
|
this.paused = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
play() {
|
|
|
|
|
this.paused = false;
|
|
|
|
|
if (!active_tick_animations.has(this)) {
|
|
|
|
|
this.#previous = raf.now();
|
|
|
|
|
if (active_tick_ref === undefined) {
|
|
|
|
|
active_tick_ref = raf.tick(handle_raf);
|
|
|
|
|
}
|
|
|
|
|
active_tick_animations.add(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#reverse() {
|
|
|
|
|
this.#reversed = !this.#reversed;
|
|
|
|
|
if (this.paused) {
|
|
|
|
|
if (this.#current === 0) {
|
|
|
|
|
this.#current = this.#duration;
|
|
|
|
|
}
|
|
|
|
|
this.play();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reverse() {
|
|
|
|
|
if (this.#delay === 0) {
|
|
|
|
|
this.#reverse();
|
|
|
|
|
} else {
|
|
|
|
|
this.#delay_current = this.#delay;
|
|
|
|
|
this.#delayed_reverse = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cancel() {
|
|
|
|
|
active_tick_animations.delete(this);
|
|
|
|
|
const current = this.#current / this.#duration;
|
|
|
|
|
if (current > 0 && current < 1) {
|
|
|
|
|
const t = this.#reversed ? 1 : 0;
|
|
|
|
|
this.#tick_fn(t, 1 - t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
finish() {
|
|
|
|
|
active_tick_animations.delete(this);
|
|
|
|
|
if (this.onfinish) {
|
|
|
|
|
this.onfinish();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @param {number} time */
|
|
|
|
|
_update(time) {
|
|
|
|
|
let diff = time - this.#previous;
|
|
|
|
|
this.#previous = time;
|
|
|
|
|
if (this.#delay_current !== 0) {
|
|
|
|
|
const is_delayed = this.#delay_current === DELAY_NEXT_TICK;
|
|
|
|
|
let cancel = !this.#delayed_reverse;
|
|
|
|
|
this.#delay_current -= diff;
|
|
|
|
|
if (this.#delay_current < 0 || is_delayed || (this.#delay_current === 0 && this.#reversed)) {
|
|
|
|
|
const delay_diff = is_delayed ? 0 : -this.#delay_current;
|
|
|
|
|
this.#delay_current = 0;
|
|
|
|
|
|
|
|
|
|
if (this.#delayed_reverse) {
|
|
|
|
|
this.#delayed_reverse = false;
|
|
|
|
|
this.#reverse();
|
|
|
|
|
} else if (delay_diff !== 0 || this.#reversed) {
|
|
|
|
|
diff = delay_diff;
|
|
|
|
|
}
|
|
|
|
|
cancel = false;
|
|
|
|
|
} else if (this.#delay_current === 0) {
|
|
|
|
|
this.#delay_current = DELAY_NEXT_TICK;
|
|
|
|
|
}
|
|
|
|
|
if (cancel) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.#current += this.#reversed ? -diff : diff;
|
|
|
|
|
let t = this.#current / this.#duration;
|
|
|
|
|
|
|
|
|
|
if (t < 0) {
|
|
|
|
|
t = 0;
|
|
|
|
|
} else if (t > 1) {
|
|
|
|
|
t = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((this.#reversed && t <= 0) || (!this.#reversed && t >= 1)) {
|
|
|
|
|
t = this.#reversed ? 0 : 1;
|
|
|
|
|
if (this.#delay_current === 0) {
|
|
|
|
|
active_tick_animations.delete(this);
|
|
|
|
|
if (this.onfinish) {
|
|
|
|
|
this.paused = true;
|
|
|
|
|
this.onfinish();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.#tick_fn(t, 1 - t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @param {number} time */
|
|
|
|
|
function handle_raf(time) {
|
|
|
|
|
for (const animation of active_tick_animations) {
|
|
|
|
|
if (!animation.paused) {
|
|
|
|
|
animation._update(time);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (active_tick_animations.size !== 0) {
|
|
|
|
|
active_tick_ref = raf.tick(handle_raf);
|
|
|
|
|
} else {
|
|
|
|
|
active_tick_ref = undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @param {number} t */
|
|
|
|
|
const linear = (t) => t;
|
|
|
|
|
|
|
|
|
|
|