// @ts-nocheck const TICK = Symbol('tick'); const TICK_HANDLER = Symbol('tick-handler'); const ANIMATIONS = Symbol('animations'); const START_TIMES = Symbol('start-times'); const PAUSE_START = Symbol('pause-start'); const PAUSE_TIME = Symbol('pause-time'); const _raf = typeof requestAnimationFrame !== 'undefined' ? requestAnimationFrame : function(cb: Function) {return setTimeout(cb, 1000/60)} const _caf = typeof cancelAnimationFrame !== 'undefined' ? cancelAnimationFrame: function(id: any) {clearTimeout(id)} // const TICK = 'tick'; // const TICK_HANDLER = 'tick-handler'; // const ANIMATIONS = 'animations'; // const START_TIMES = 'start-times'; // const PAUSE_START = 'pause-start'; // const PAUSE_TIME = 'pause-time'; // const _raf = function(callback):number|null {return setTimeout(callback, 1000/60)} // const _caf = function(id: number):void {clearTimeout(id)} export class Timeline { state: string constructor() { this.state = 'Initiated'; this[ANIMATIONS] = new Set(); this[START_TIMES] = new Map(); } start() { if (!(this.state === 'Initiated')) return; this.state = 'Started'; let startTime = Date.now(); this[PAUSE_TIME] = 0; this[TICK] = () => { let now = Date.now(); this[ANIMATIONS].forEach((animation) => { let t: number; if (this[START_TIMES].get(animation) < startTime) { t = now - startTime - animation.delay - this[PAUSE_TIME]; } else { t = now - this[START_TIMES].get(animation) - animation.delay - this[PAUSE_TIME]; } if (t > animation.duration) { this[ANIMATIONS].delete(animation); t = animation.duration; } if (t > 0) animation.run(t); }) // for (let animation of this[ANIMATIONS]) { // let t: number; // console.log('animation', animation) // if (this[START_TIMES].get(animation) < startTime) { // t = now - startTime - animation.delay - this[PAUSE_TIME]; // } else { // t = now - this[START_TIMES].get(animation) - animation.delay - this[PAUSE_TIME]; // } // if (t > animation.duration) { // this[ANIMATIONS].delete(animation); // t = animation.duration; // } // if (t > 0) animation.run(t); // } this[TICK_HANDLER] = _raf(this[TICK]); }; this[TICK](); } pause() { if (!(this.state === 'Started')) return; this.state = 'Paused'; this[PAUSE_START] = Date.now(); _caf(this[TICK_HANDLER]); } resume() { if (!(this.state === 'Paused')) return; this.state = 'Started'; this[PAUSE_TIME] += Date.now() - this[PAUSE_START]; this[TICK](); } reset() { this.pause(); this.state = 'Initiated'; this[PAUSE_TIME] = 0; this[PAUSE_START] = 0; this[ANIMATIONS] = new Set(); this[START_TIMES] = new Map(); this[TICK_HANDLER] = null; } add(animation: any, startTime?: number) { if (arguments.length < 2) startTime = Date.now(); this[ANIMATIONS].add(animation); this[START_TIMES].set(animation, startTime); } } export class Animation { startValue: number endValue: number duration: number timingFunction: (t: number) => number delay: number template: (t: number) => void constructor(startValue: number, endValue: number, duration: number, delay: number, timingFunction: (t: number) => number, template: (v: number) => void) { timingFunction = timingFunction || (v => v); template = template || (v => v); this.startValue = startValue; this.endValue = endValue; this.duration = duration; this.timingFunction = timingFunction; this.delay = delay; this.template = template; } run(time: number) { let range = this.endValue - this.startValue; let progress = time / this.duration if(progress != 1) progress = this.timingFunction(progress) this.template(this.startValue + range * progress) } }