util_color_color.js

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

import Util from "../misc/util.js";

/**
 * @class
 * Color that holds red, green, blue, and alpha values.
 */
class Color {
    static CLEAR = new Color(0, 0, 0, 0);

    static BLACK = new Color(0, 0, 0);
    static WHITE = new Color(255, 255, 255);
    static GRAY = new Color(128, 128, 128);
    static DARK_GRAY = new Color(64, 64, 64);

    static RED = new Color(255, 0, 0);
    static ORANGE = new Color(255, 106, 0);
    static YELLOW = new Color(255, 216, 0);
    static GREEN = new Color(0, 255, 0);
    static AQUA = new Color(0, 255, 255);
    static BLUE = new Color(0, 0, 255);
    static PURPLE = new Color(255, 0, 255);
    static PINK = new Color(255, 75, 175);

    static fromArray(array) {
        let alpha = 1;
        if (array >= 4)
            alpha = array[3];
        return new Color(array[0], array[1], array[2], alpha);
    }

    /**
     * Create a new color.
     * @param {number} red Red value (0-255)
     * @param {number} green Green value (0-255)
     * @param {number} blue Blue value (0-255)
     * @param {number} alpha (Optional) Alpha value (0-1)
     * @constructor
     */
    constructor(red = 0, green = 0, blue = 0, alpha = 1) {
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.alpha = alpha;
    }

    /**
     * Get the color in the form of a string. Useful for CSS styling and drawing
     * colors on canvas.
     * @param {boolean} alpha Whether to include alpha (true by default)
     * @returns {string} Resulting color string
     */
    get(alpha = true) {
        if (alpha)
            return "rgba(" + this.red + ", " + this.green + ", " +
                this.blue + ", " + this.alpha + ")";

        return "rgba(" + this.red + ", " + this.green + ", " +
            this.blue + ")";
    }

    toHex() {
        const hex = (c) => {
            const h = Math.round(c).toString(16);
            return h.length === 1 ? '0' + h : h;
        };

        return `#${hex(this.red)}${hex(this.green)}${hex(this.blue)}`;
    }

    /**
     * Set (replace) the values of the color.
     * @param {number} red Red value (0-255)
     * @param {number} green Green value (0-255)
     * @param {number} blue Blue value (0-255)
     * @param {number} alpha (Optional) Alpha value (0-1)
     */
    set(red, green, blue, alpha = 1) {
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.alpha = alpha;
    }

    /**
     * Get an exact copy of the color.
     * @returns {Color} Cloned color
     */
    copy() {
        return new Color(this.red, this.green, this.blue, this.alpha);
    }

    /**
     * Lighten this color by a specified percentage.
     * @param {number} percent Percentage to lighten by
     */
    lighten(percent) {
        this.red += this.red * percent;
        if (this.red > 255) this.red = 255;
        this.green += this.green * percent;
        if (this.green > 255) this.green = 255;
        this.blue += this.blue * percent;
        if (this.blue > 255) this.blue = 255;
    }

    /**
     * Darken this color by a specified percentage.
     * @param {number} percent Percentage to darken by
     */
    darken(percent) {
        this.red -= this.red * percent;
        if (this.red < 0) this.red = 0;
        this.green -= this.green * percent;
        if (this.green < 0) this.green = 0;
        this.blue -= this.blue * percent;
        if (this.blue < 0) this.blue = 0;
    }

    /**
     * Get a lightened version of the color.
     * @param {number} percent Percentage to lighten by
     * @returns {Color} Resulting color
     */
    getLightened(percent) {
        var c = this.copy();
        c.lighten(percent);
        return c;
    }

    /**
     * Get a darkened version of the color.
     * @param {number} percent Percentage to darken by
     * @returns {Color} Resulting color
     */
    getDarkened(percent) {
        var c = this.copy();
        c.darken(percent);
        return c;
    }

    /**
     * Invert the color.
     */
    invert() {
        this.red = 255 - this.red;
        this.green = 255 - this.green;
        this.blue = 255 - this.blue;
    }

    /**
     * Linear interpolate with another color.
     * @param {Color} other Other color to interpolate with
     * @param {number} point Point (alpha) on the gradient
     * @returns {Color} Resulting interpolated color
     */
    lerp(other, point) {
        let red = Util.lerp(this.red, other.red, point);
        let green = Util.lerp(this.green, other.green, point);
        let blue = Util.lerp(this.blue, other.blue, point);
        let alpha = Util.lerp(this.alpha, other.alpha, point);

        return new Color(red, green, blue, alpha);
    }
}

export default Color;