sd动画框架中的颜色系统

为什么要设立颜色系统?

因为作者不想每次染色的时候都去查颜色的 RGB 表示或者 16 进制表示了。

API 列表

type HexColor = string;
type PacketColor = { fill: HexColor; stroke: HexColor };
type SDColor = HexColor | PacketColor;

class Color {
    static red: HexColor;
    static blue: HexColor;
    static cyan: HexColor;
    static grey: HexColor;
    static pink: HexColor;

    /**
     * 雪白色
     */
    static snow: HexColor;

    static azure: HexColor;
    static black: HexColor;

    /**
     * 珊瑚红
     */
    static coral: HexColor;

    static green: HexColor;
    static white: HexColor;
    static orange: HexColor;
    static purple: HexColor;

    /**
     * 紫罗兰色
     */
    static violet: HexColor;

    static yellow: HexColor;
    static darkRed: HexColor;
    static pureRed: HexColor;
    static darkBlue: HexColor;
    static darkGrey: HexColor;
    static darkPink: HexColor;
    static pureBlue: HexColor;

    /**
     * 文本蓝
     */
    static textBlue: HexColor;

    static aliceBlue: HexColor;
    static chocolate: HexColor;
    static darkGreen: HexColor;
    static paleGreen: HexColor;

    /**
     * 粉红桃色
     */
    static peachPuff: HexColor;
    static pureGreen: HexColor;
    static buttonGrey: HexColor;
    static darkOrange: HexColor;
    static darkPurple: HexColor;

    /**
     * 幽灵白
     */
    static ghostWhite: HexColor;

    /**
     * 天空蓝
     */
    static deepSkyBlue: HexColor;

    /**
     * 柠檬绸色
     */
    static lemonChiffon: HexColor;
    static darkButtonGrey: HexColor;

    static RED: PacketColor;
    static BLUE: PacketColor;
    static GREY: PacketColor;
    static GREEN: PacketColor;
    static ORANGE: PacketColor;
    static PURPLE: PacketColor;
    static DEFAULT: PacketColor;
    static BUTTON_GREY: PacketColor;

    static random: () => HexColor;
    static equal(a: SDColor, b: SDColor): boolean;
    static gradient: (start: HexColor, end: HexColor, l: number, r: number) => (grad: number) => HexColor;
}

function color(): typeof Color;

颜色类别

在本框架内,可以按照颜色数据存在形式,将颜色划分为单独色打包色。单独色就是一个 16 进制字符串。打包色则是两个单独色的混合:

type PacketColor = {
    fill: HexColor;
    stroke: HexColor;
};

以下例子直观地展示了单独色和打包色在染色时的区别:

const svg = sd.svg();
const C = sd.color(); // 获取颜色模块
const r1 = new sd.Rect(svg).strokeWidth(3);
const r2 = new sd.Rect(svg).strokeWidth(3).x(100);
sd.main(async () => {
    await sd.pause();
    r1.startAnimate().color(C.red).endAnimate(); // 通常用小写字母命名来表示一个单独色
    r2.startAnimate().color(C.RED).endAnimate(); // 通常用大写字母命名来表示一个打包色
});

试一试,可以发现左侧的矩形仅将自己的内部全部染红,而右侧的矩形不仅将矩形内部全部染红,还将矩形的边框也染红了。单独色和打包色的区别正是在此。打包色额外考虑了物体的边框/描边(stroke)要被染成什么颜色。

random

这是用于随机生成颜色的方法。

const svg = sd.svg();
const C = sd.color();
const rect = new sd.Rect(svg);
sd.main(async () => {
    while (true) {
        await sd.pause();
        rect.startAnimate().color(C.random()).endAnimate();
    }
});

试一试,不断为矩形染上随机的颜色。

gradient

class Color {
    static gradient: (start: HexColor, end: HexColor, l: number, r: number) => (grad: number) => HexColor;
}

这个方法用于生成一个颜色梯度函数,把数值映射到颜色上去。l 数值对应 start 这种颜色,r 数值对应 end 这种颜色,中间的数值进行线性插值。

const svg = sd.svg();
const C = sd.color();
const n = 10;
const arr = new sd.Array(svg).resize(n);
const grad = C.gradient(C.white, C.pureBlue, 0, n - 1);
sd.main(async () => {
    await sd.pause();
    arr.startAnimate();
    for (let i = 0; i < n; i++) arr.color(i, grad(i));
    arr.endAnimate();
});

试一试,从白色到纯蓝色的渐变。