util_gradient_vec2_gradient.js

import Vec2 from "../../game/vector/vec2.js";

/**
 * @module Vec2Gradient
 * @fileoverview Contains Vec2Gradient class.
 */

/**
 * @class
 * Gradient for two-dimensional vectors.
 */
class Vec2Gradient {
    /**
     * Create a new Vec2 gradient.
     * @param {Object.<number, number|Vec2>} values Values at time intervals
     * @param {boolean} smooth Whether the track should start and end smoothly/gradually
     * @constructor
     */
    constructor(values = {}, smooth = false) {
        const keys = Object.keys(values).map(Number).sort((a, b) => a - b);

        this._points = [];
        this._values = [];

        for (const key of keys) {
            this._points.push(key);
            this._values.push(Vec2.from(values[key.toString()]));
        }

        this.smooth = smooth;
    }


    //
    // Calculations
    //

    /**
     * Get the vector a specified point.
     * @param {number} progress Overall animation progress (0 - 1)
     * @returns {Vec2} Vector at current point
     */
    get(progress) {
        if (this._points.length === 0)
            return new Vec2();
        if (this._points.length === 1 || progress <= this._points[0])
            return this._values[0].copy();
        if (progress >= this._points[this._points.length - 1])
            return this._values[this._points.length - 1].copy();

        let i = 0;
        while (progress > this._points[i]) i++;

        const pointA = this._points[i - 1];
        const pointB = this._points[i];

        const posA = this._values[i - 1];
        const posB = this._values[i];

        const alpha = (progress - pointA) / (pointB - pointA);

        if (this.smooth)
            return posA.smoothLerp(posB, alpha);
        else
            return posA.lerp(posB, alpha);
    }
}

export default Vec2Gradient;