绘制饱和度/亮度渐变

aki*_*uri 3 javascript canvas color-picker linear-gradients pixel-manipulation

我正在尝试在画布上绘制以下渐变图像,但是右下角存在问题。

所需效果:

在此处输入图片说明

电流输出:

在此处输入图片说明

我可能在这里错过了一些非常简单的事情。

function color(r, g, b) {
  var args = Array.prototype.slice.call(arguments);
  if (args.length == 1) {
    args.push(args[0]);
    args.push(args[0]);
  } else if (args.length != 3 && args.length != 4) {
    return;
  }
  return "rgb(" + args.join() + ")";
}

function drawPixel(x, y, fill) {
  var fill = fill || "black";
  context.beginPath();
  context.rect(x, y, 1, 1);
  context.fillStyle = fill;
  context.fill();
  context.closePath();
}

var canvas = document.getElementById("primary");
var context = canvas.getContext("2d");

canvas.width = 256;
canvas.height = 256;

for (var x = 0; x < canvas.width; x++) {
  for (var y = 0; y < canvas.height; y++) {
    var r = 255 - y;
    var g = 255 - x - y;
    var b = 255 - x - y;
    drawPixel(x, y, color(r, g, b));
  }
}
Run Code Online (Sandbox Code Playgroud)
#primary {
    display: block;
    border: 1px solid gray;
}
Run Code Online (Sandbox Code Playgroud)
<canvas id="primary"></canvas>
Run Code Online (Sandbox Code Playgroud)

JSFiddle

Bli*_*n67 5

使用渐变。

您可以让GPU为您完成大部分处理.2D合成运算可multiply有效地将每个像素的两种颜色相乘。因此,对于每个通道和每个像素colChanDest = Math.floor(colChanDest * (colChanSrc / 255)),都是通过GPU的大规模并行处理能力完成的,而不是通过在单个内核(JavaScript执行上下文)上运行的共享程度较低的线程来完成的。

两个渐变

  1. 一是背景从上到下从白到黑

    var gradB = ctx.createLinearGradient(0,0,0,255); gradB.addColorStop(0,"white"); gradB.addColorStop(1,"black");

  2. 另一个是从左到右从透明到不透明的色相

    var swatchHue var col = "rgba(0,0,0,0)" var gradC = ctx.createLinearGradient(0,0,255,0); gradC.addColorStop(0,``hsla(${hueValue},100%,50%,0)``); gradC.addColorStop(1,``hsla(${hueValue},100%,50%,1)``);

请注意,上述字符串引号在SO上无法正确呈现,因此我将它们加倍显示,使用演示代码段中的单引号。

渲染图

然后将两者叠加,首先是背景(灰度),然后使用合成操作“相乘”

ctx.fillStyle = gradB;
ctx.fillRect(0,0,255,255);
ctx.fillStyle = gradC;
ctx.globalCompositeOperation = "multiply";
ctx.fillRect(0,0,255,255);
ctx.globalCompositeOperation = "source-over";
Run Code Online (Sandbox Code Playgroud)

仅适用于顺化

颜色(色相)是纯色值很重要,不能使用随机的rgb值。如果选择了rgb值,则需要从rgb中提取色相值。

以下函数会将RGB值转换为HSL颜色

function rgbToLSH(red, green, blue, result = {}){
    value hue, sat, lum, min, max, dif, r, g, b;
    r = red/255;
    g = green/255;
    b = blue/255;
    min = Math.min(r,g,b);
    max = Math.max(r,g,b);
    lum = (min+max)/2;
    if(min === max){
        hue = 0;
        sat = 0;
    }else{
        dif = max - min;
        sat = lum > 0.5 ? dif / (2 - max - min) : dif / (max + min);
        switch (max) {
        case r:
            hue = (g - b) / dif;
            break;
        case g:
            hue = 2 + ((b - r) / dif);
            break;
        case b:
            hue = 4 + ((r - g) / dif);
            break;
        }
        hue *= 60;
        if (hue < 0) {
            hue += 360;
        }        
    }
    result.lum = lum * 255;
    result.sat = sat * 255;
    result.hue = hue;
    return result;
}
Run Code Online (Sandbox Code Playgroud)

放在一起

该示例每3秒呈现一个随机的红色,绿色,蓝色值的色板。

请注意,此示例使用Balel,以便它将在IE上运行

ctx.fillStyle = gradB;
ctx.fillRect(0,0,255,255);
ctx.fillStyle = gradC;
ctx.globalCompositeOperation = "multiply";
ctx.fillRect(0,0,255,255);
ctx.globalCompositeOperation = "source-over";
Run Code Online (Sandbox Code Playgroud)

要从x和y坐标计算颜色,您需要计算出的色相,然后是饱和度和值才能获得hsv颜色(注意hsl和hsv是不同的颜色模型)

// saturation and value are clamped to prevent rounding errors creating wrong colour
var rgbArray = hsv_to_rgb(
    hue, // as used to create the swatch
    Math.max(0, Math.min(1, x / 255)),   
    Math.max(0, Math.min(1, 1 - y / 255))
);
Run Code Online (Sandbox Code Playgroud)

用于获取h,s,v颜色的r,g,b值的函数。

function rgbToLSH(red, green, blue, result = {}){
    value hue, sat, lum, min, max, dif, r, g, b;
    r = red/255;
    g = green/255;
    b = blue/255;
    min = Math.min(r,g,b);
    max = Math.max(r,g,b);
    lum = (min+max)/2;
    if(min === max){
        hue = 0;
        sat = 0;
    }else{
        dif = max - min;
        sat = lum > 0.5 ? dif / (2 - max - min) : dif / (max + min);
        switch (max) {
        case r:
            hue = (g - b) / dif;
            break;
        case g:
            hue = 2 + ((b - r) / dif);
            break;
        case b:
            hue = 4 + ((r - g) / dif);
            break;
        }
        hue *= 60;
        if (hue < 0) {
            hue += 360;
        }        
    }
    result.lum = lum * 255;
    result.sat = sat * 255;
    result.hue = hue;
    return result;
}
Run Code Online (Sandbox Code Playgroud)