Source: view/tween.js

import { EventEmitter } from "../event_emitter.js";
import { v4 as uuid } from '../../node_modules/uuid/dist/esm-browser/index.js';

/** Tween */
class Tween extends EventEmitter {

    /**
     * @param {number} lengthMs
     * @param {function} callback
     * @param {function} easingFn
     * @param {number} [steps = 0]
     */

    constructor(lengthMs, callback, easingFn, steps = 0) {
        super();
        this.id = uuid();
        // this.name = name
        this.stepCount = 0;
        this.startTime = new Date().getTime();
        this.easingFn = easingFn;
        this.callback = callback;
        this.lengthMs = lengthMs;
        this.steps = steps;
        this.timeStep = lengthMs / steps;
        this.canceled = false;
        this.lastFraction = 0;
        this.update()
    }

    canceled;

    stepCount;

    lastFraction;

    update() {

        if (this.stopped !== false) {
            return;
        }

        const tween = this;

        const now = new Date().getTime();
        const fractionAlong = Math.max(0, Math.min(1, (now - this.startTime) / this.lengthMs));
        const easedFraction = this.easingFn(fractionAlong);
        this.callback(easedFraction, easedFraction - this.lastFraction, fractionAlong);
        this.stepCount += 1;
        this.lastFraction = easedFraction;

        if (fractionAlong === 1) {
            this.emit('complete');
            this.stop();
            return;
        }
        else if (this.steps > 0) {

            const timeout = this.startTime + this.stepCount * this.timeStep - now;

            // console.log(this.stepCount, 'next timeout in', timeout)

            setTimeout(
                tween.update.bind(tween),
                timeout
            );

        }
    }

    stop() {
        this.stopped = true;
        this.emit('stop');
    }



    // no easing, no acceleration
    static linear = t => t;

    // accelerating from zero velocity
    static easeInQuad = t => t;

    // decelerating to zero velocity
    static easeOutQuad = t => t * (2 - t);

    // acceleration until halfway, then deceleration
    static easeInOutQuad = x => x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;;

    // accelerating from zero velocity
    static easeInCubic = t => t * t * t;

    // decelerating to zero velocity
    static easeOutCubic = t => -t * t * t + 1;

    // acceleration until halfway, then deceleration
    static easeInOutCubic = t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;

    // accelerating from zero velocity
    static easeInQuart = t => t * t * t * t;

    // decelerating to zero velocity
    static easeOutQuart = t => 1 - --t * t * t * t;

    // acceleration until halfway, then deceleration
    static easeInOutQuart = t => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;

    // accelerating from zero velocity
    static easeInQuint = t => t * t * t * t * t;

    // decelerating to zero velocity
    static easeOutQuint = t => 1 + --t * t * t * t * t;

    // acceleration until halfway, then deceleration
    static staticeaseInOutQuint = t => t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
}

export { Tween };