mixer.js

/**
 * A Mixer is an object which can hold different [spices]{@link Spice} or [recipes]{@link Recipe} that will be animated at the same time.
 * <br><br>
 * Note that a Mixer instance does not play the animation by itself. Its method [frame()]{@linkcode Mixer#frame}
 * must be called in order to execute the interpolations of each animatable object, with methods like
 * [requestAnimationFrame()]{@link https://developer.mozilla.org/en/docs/Web/API/Window/requestAnimationFrame}
 * or an instance of the {@link Mortar} class.
 * @example
import { Mixer, Spice } from 'paprika-tween';
const spice = new Spice({
    duration: 1000,
    from: { x: 0, y: 42 },
    to: { x: 200, y: 120 },
    render: (props, interpolation) => {
       console.log(props.x, props.y, interpolation);
    }
});
const mixer = new Mixer();
mixer.add(spice)
     .start();
function loop(timestamp) {
    mixer.frame(timestamp);
    requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
 * @since 1.0.0
 */
export class Mixer {
    /**
     * Creates a new Mixer instance.
     * @constructor
     * @since 1.0.0
     */
    constructor() {
        this.spices = [];
    }
    /**
     * Adds one or more [spices]{@link Spice} or [recipes]{@link Recipe} (this is, animatable objects with properties to interpolate).
     * @param {...(Spice|Recipe)} rest - Instances of Paprika animatable objects.
     * @returns {Mixer} - The current instance of the Mixer.
     * @since 1.0.0
    * @example
import { Mixer, Spice } from 'paprika-tween';
const spice1 = new Spice({ ... });
const spice2 = new Spice({ ... });
const mixer = new Mixer();
mixer.add(spice1, spice2);
     */
    add(...rest) {
        for (let i = 0; i < rest.length; i++) {
            this.spices.push(rest[i]);
        }
        return this;
    }
    /**
     * Starts all the animations in the mixer by setting the starting time of each animatable objects at the given
     * <code>time</code> argument.<br>
     * If <code>time</code> is not provided, the timestamp from
     * [performance.now()]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance/now}
     * will be used instead.
     * @param {(DOMHighResTimeStamp|number)} [time] - The initial number from where to start the animation.
     * @returns {Mixer} - The current instance of the Mixer.
     * @since 1.0.0
    * @example
import { Mixer } from 'paprika-tween';
const mixer = new Mixer();
mixer.start(0);
     */
    start(time) {
        for (let i = 0; i < this.spices.length; i++) {
            this.spices[i].start(time);
        }
        return this;
    }
    /**
     * Stops all animations and clears the stack of animatable objects.
     * @since 1.0.0
     */
    dispose() {
        for (let i = this.spices.length - 1; i !== -1; i--) {
            this.spices[i].dispose();
        }
        this.spices.length = 0;
    }
    /**
     * Moves the interpolation of the properties of the animatable objects in the mixer by the given time, which is
     * relative to the starting time.<br>
     * If <code>time</code> is not provided, the timestamp from
     * [performance.now()]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance/now}
     * will be used instead.
     * @param {(DOMHighResTimeStamp|number)} [time] - The amount of time to interpolate since the animations started.
     * @since 1.0.0
    * @example
import { Mixer, Spice } from 'paprika-tween';
const spice = new Spice({
    duration: 10,
    from: { width: 100 },
    to: { width: 550 },
    render: (props) => { ... }
});
const mixer = new Mixer(0);
mixer.add(spice)
     .start();
mixer.frame(1);
     */
    frame(time) {
        for (let i = 0; i < this.spices.length; i++) {
            this.spices[i].frame(time);
        }
    }
}