I'm trying to improve my Color Picker code. It works like Photoshop and I don't want to use a library.

    for(var yColor = 0; yColor < 255; yColor++)
{
var r = 255,
g = 0,
b = 0;
for(var xColor = 0; xColor < 255; xColor++)
{
if(r == 255 && g < 255 && b == 0) g += 6;
else if(r > 0 && g == 255 && b == 0) r -= 6;
else if(r == 0 && g == 255 && b < 255) b += 6;
else if(r == 0 && g > 0 && b == 255) g -= 6;
else if(r < 255 && g == 0 && b == 255) r += 6;
else if(r == 255 && g == 0 && b > 0) b -= 6;

if(r > 255) r = 255;
else if(r < 0) r = 0;
else if(g > 255) g = 255;
else if(g < 0) g = 0;
else if(b > 255) b = 255;
else if(b < 0) b = 0;

var rG = r + yColor > 255 ? 255 : r + yColor;
var gG = g + yColor > 255 ? 255 : g + yColor;
var bG = b + yColor > 255 ? 255 : b + yColor;

GAContext.beginPath();
GAContext.fillStyle = "rgb(" + rG + ", " + gG + ", " + bG + ")";
GAContext.rect(xColor, yColor, 1, 1);
GAContext.fill();
}
}

• Just improve my code. Commented Jul 27, 2014 at 0:29
• If I redraw it, It become a bit laggy. Commented Jul 27, 2014 at 0:30

The way you check the bounds of r, g, b is a bit repetitive:

if(r > 255) r = 255;
else if(r < 0) r = 0;
else if(g > 255) g = 255;
else if(g < 0) g = 0;
else if(b > 255) b = 255;
else if(b < 0) b = 0;


You could use a helper function to simplify a bit:

function ensureBounds(x) {
return Math.min(255, Math.max(0, x));  // Thanks @flambino!
}

r = ensureBounds(r);
g = ensureBounds(g);
b = ensureBounds(b);


And you could reuse it later to simplify setting rG, and the other:

var rG = ensureBounds(r + yColor);
var gG = ensureBounds(g + yColor);
var bG = ensureBounds(b + yColor);


UPDATE

This was my earlier version of the ensureBounds function, before I adopted @flambino's suggestion above:

function ensureBounds(x) {
if (x > 255) return 255;
if (x < 0) return 0;
return x;
}


If I redraw it, It become a bit laggy.

In my tests, using createImageData and putImageData to fill the individual pixels ran about 3x faster than rect and fill.

You can replace this code:

GAContext.beginPath();
GAContext.fillStyle = "rgb(" + rG + ", " + gG + ", " + bG + ")";
GAContext.rect(xColor, yColor, 1, 1);
GAContext.fill();


With this:

pixelData[0] = rG;
pixelData[1] = gG;
pixelData[2] = bG;
GAContext.putImageData(pixel, xColor, yColor);


And before the loop, add this:

var pixel = GAContext.createImageData(1, 1);
var pixelData = pixel.data;
pixelData[3] = 255;


Test it out here. This Stack Overflow question is relevant. You may also be able to figure out a clever way to do this with gradients that would be much faster.