使用HTML5画布创建渐变颜色选择(所有可能的RGB颜色)

iri*_*rie 0 gradient canvas colors color-space html5-canvas

是否可以为线性颜色选择器增加包含所有可能的RGB颜色(仅红色,绿色,蓝色 - 无alpha值)的线性渐变.

到目前为止,我有以下梯度尝试过,但它不会包含所有的值rgb(0,0,0)rgb(255,255,255):

var grd = ctx.createLinearGradient(0, 0, width, 0);
grd.addColorStop(0,     'red');
grd.addColorStop(1 / 6, 'orange');
grd.addColorStop(2 / 6, 'yellow');
grd.addColorStop(3 / 6, 'green')
grd.addColorStop(4 / 6, 'aqua');
grd.addColorStop(5 / 6, 'blue');
grd.addColorStop(1,     'purple');
Run Code Online (Sandbox Code Playgroud)

任何帮助都非常感谢.

小智 13

不幸的是没有你不能.

主要原因是24位RGB包含16,777,216种颜色(256 3).只是为了得到一个估计,你将需要4096 x 4096像素的屏幕分辨率(当然没有这样的方形屏幕,但相当于实际显示器的大约16:9格式).

简单地说:没有空间将所有像素放在普通屏幕上.

另外,使用渐变会产生问题,因为这只会在画布的一个方向上出现.您需要在两个方向上绘制颜色,您需要手动直接操作位图.

我的建议是拍摄现有这样的调色板的屏幕快照,并将该图像绘制到画布上.这将量化颜色(这也发生在所有可用的颜色选择器中),但会使您接近所需的颜色.

此外,您可以添加滑块来微调值以及文本框(后者在纯画布中有点复杂,但您可以组合使用html和canvas来实现此目的).

表示"所有"颜色的近似值可能是这样的(下面的演示快照):

下面演示的快照

更新

好的,我答应回复你关于从RGB值计算位置的问题.从图像中的调色板开始,您可以通过将颜色转换为HSV颜色空间轻松计算位置.

执行RGB到HSV的功能如下所示:

function rgb2hsv() {

    var rr, gg, bb,

    r = arguments[0] / 255,
    g = arguments[1] / 255,
    b = arguments[2] / 255,
    h, s,

    v = Math.max(r, g, b),
    diff = v - Math.min(r, g, b),
    diffc = function (c) {
        return (v - c) / 6 / diff + 1 / 2;
    };

    if (diff === 0) {
        h = s = 0;

    } else {
        s = diff / v;

        rr = diffc(r);
        gg = diffc(g);
        bb = diffc(b);

        if (r === v) {h = bb - gg}
        else if (g === v) {h = (1 / 3) + rr - bb} 
        else if (b === v) {h = (2 / 3) + gg - rr};
        if (h < 0) {h += 1}
        else if (h > 1) {h -= 1}
    }

    return {
        h: (h * 360 + 0.5) |0,
        s: (s * 100 + 0.5) |0,
        v: (v * 100 + 0.5) |0
    }
};
Run Code Online (Sandbox Code Playgroud)

现在颜色以度(0-359),饱和度(0-100)和亮度(0-100)表示.

要获得水平位置,您需要做的就是将调色板的宽度除以360并乘以h(色调).要获得垂直位置,您可以在上部和下部分割调色板.如果饱和度<100那么你就在上部,如果V <100那么你就在下部:

function getPos(canvas, h, s, v) {

var m = canvas.height / 2,
    x = canvas.width / 360 * h,
    y;

if (s === 100 && v === 100) {
    y = m;

} else if (v === 100 && s < 100) {
    y = m / 100 * s;

} else if (s === 100 && v < 100) {
    y = m / 100 * (100 - v) + m;
}

x = (x + 0.5) |0; //convert to integer
y = (y + 0.5) |0;

};
Run Code Online (Sandbox Code Playgroud)

这当然要求您生成的调色板非常准确.

演示

请注意,光标不是基于鼠标位置设置的,而是基于RGB(HSV)值设置的.它首先从鼠标位置选择一个颜色RGB,然后将其转换为HSV并从中计算位置.

调色板是根据窗口大小动态生成的.

对于简单的颜色选择也值得一提的是,渐变的问题似乎是平滑的,因为它们是抖动的.这意味着您可以获得一个显然不在您选择的范围内的像素值.

要在执行颜色选择时减少此问题,您需要平均从鼠标获得的x和y位置周围的区域.