|
|
@ -33,11 +33,9 @@ function tick(time) {
|
|
|
|
class Animation {
|
|
|
|
class Animation {
|
|
|
|
#keyframes;
|
|
|
|
#keyframes;
|
|
|
|
#duration;
|
|
|
|
#duration;
|
|
|
|
#timeline_offset;
|
|
|
|
|
|
|
|
#reversed;
|
|
|
|
|
|
|
|
#target;
|
|
|
|
#target;
|
|
|
|
#paused;
|
|
|
|
|
|
|
|
#finished;
|
|
|
|
#finished;
|
|
|
|
|
|
|
|
#cancelled;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @param {HTMLElement} target
|
|
|
|
* @param {HTMLElement} target
|
|
|
@ -48,47 +46,39 @@ class Animation {
|
|
|
|
this.#target = target;
|
|
|
|
this.#target = target;
|
|
|
|
this.#keyframes = keyframes;
|
|
|
|
this.#keyframes = keyframes;
|
|
|
|
this.#duration = options.duration || 0;
|
|
|
|
this.#duration = options.duration || 0;
|
|
|
|
this.#timeline_offset = 0;
|
|
|
|
|
|
|
|
this.#reversed = false;
|
|
|
|
|
|
|
|
this.#paused = false;
|
|
|
|
|
|
|
|
this.onfinish = () => {};
|
|
|
|
|
|
|
|
this.pending = true;
|
|
|
|
|
|
|
|
this.currentTime = 0;
|
|
|
|
this.currentTime = 0;
|
|
|
|
this.playState = 'running';
|
|
|
|
|
|
|
|
this.effect = {
|
|
|
|
// Promise-like semantics, but call callbacks immediately on raf.tick
|
|
|
|
setKeyframes: (/** @type {Keyframe[]} */ keyframes) => {
|
|
|
|
this.finished = {
|
|
|
|
this.#keyframes = keyframes;
|
|
|
|
then: (callback) => {
|
|
|
|
|
|
|
|
this.#finished = callback;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
catch: (callback) => {
|
|
|
|
|
|
|
|
this.#cancelled = callback;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.finished = new Promise((fulfil) => {
|
|
|
|
|
|
|
|
this.#finished = fulfil;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
play() {
|
|
|
|
cancel() {
|
|
|
|
this.#paused = false;
|
|
|
|
if (this.currentTime > 0 && this.currentTime < this.#duration) {
|
|
|
|
raf.animations.add(this);
|
|
|
|
this._applyKeyFrame(0);
|
|
|
|
this.playState = 'running';
|
|
|
|
}
|
|
|
|
this._update();
|
|
|
|
|
|
|
|
|
|
|
|
this.#cancelled();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_update() {
|
|
|
|
_update() {
|
|
|
|
if (this.#reversed) {
|
|
|
|
this.currentTime = raf.time;
|
|
|
|
if (this.#timeline_offset === 0) {
|
|
|
|
|
|
|
|
this.currentTime = this.#duration - raf.time;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.currentTime = this.#timeline_offset + (this.#timeline_offset - raf.time);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.currentTime = raf.time - this.#timeline_offset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const target_frame = this.currentTime / this.#duration;
|
|
|
|
const target_frame = this.currentTime / this.#duration;
|
|
|
|
this._applyKeyFrame(target_frame);
|
|
|
|
this._applyKeyFrame(target_frame);
|
|
|
|
|
|
|
|
|
|
|
|
if (this.currentTime >= this.#duration) {
|
|
|
|
if (this.currentTime >= this.#duration) {
|
|
|
|
this.#finished();
|
|
|
|
this.#finished();
|
|
|
|
|
|
|
|
raf.animations.delete(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -103,53 +93,13 @@ class Animation {
|
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
|
this.#target.style[prop] = frame[prop];
|
|
|
|
this.#target.style[prop] = frame[prop];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (this.#reversed) {
|
|
|
|
|
|
|
|
if (this.currentTime <= 0) {
|
|
|
|
|
|
|
|
this.finish();
|
|
|
|
|
|
|
|
for (let prop in frame) {
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
|
|
this.#target.style[prop] = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (this.currentTime >= this.#duration) {
|
|
|
|
|
|
|
|
this.finish();
|
|
|
|
|
|
|
|
for (let prop in frame) {
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
|
|
this.#target.style[prop] = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
finish() {
|
|
|
|
if (this.currentTime >= this.#duration) {
|
|
|
|
this.onfinish();
|
|
|
|
for (let prop in frame) {
|
|
|
|
this.currentTime = this.#reversed ? 0 : this.#duration;
|
|
|
|
// @ts-ignore
|
|
|
|
if (this.#reversed) {
|
|
|
|
this.#target.style[prop] = null;
|
|
|
|
raf.animations.delete(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.playState = 'idle';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cancel() {
|
|
|
|
|
|
|
|
this.#paused = true;
|
|
|
|
|
|
|
|
if (this.currentTime > 0 && this.currentTime < this.#duration) {
|
|
|
|
|
|
|
|
this._applyKeyFrame(this.#reversed ? this.#keyframes.length - 1 : 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pause() {
|
|
|
|
|
|
|
|
this.#paused = true;
|
|
|
|
|
|
|
|
this.playState = 'paused';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reverse() {
|
|
|
|
|
|
|
|
if (this.#paused && !raf.animations.has(this)) {
|
|
|
|
|
|
|
|
raf.animations.add(this);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.#timeline_offset = this.currentTime;
|
|
|
|
|
|
|
|
this.#reversed = !this.#reversed;
|
|
|
|
|
|
|
|
this.playState = 'running';
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -160,6 +110,7 @@ class Animation {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
HTMLElement.prototype.animate = function (keyframes, options) {
|
|
|
|
HTMLElement.prototype.animate = function (keyframes, options) {
|
|
|
|
const animation = new Animation(this, keyframes, options);
|
|
|
|
const animation = new Animation(this, keyframes, options);
|
|
|
|
|
|
|
|
raf.animations.add(animation);
|
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
|
return animation;
|
|
|
|
return animation;
|
|
|
|
};
|
|
|
|
};
|
|
|
|