If you have an array of colors structured like this:
var rgbArr = [c1, c2, c3, ...]
where each color ci
consists of three numbers between 0 and 255
ci = [red, green, blue]
you can utilize the following function to convert these colors to HSL format
function rgbToHsl(c) {
var r = c[0]/255, g = c[1]/255, b = c[2]/255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return new Array(h * 360, s * 100, l * 100);
}
and arrange them based on hue
var sortedRgbArr = rgbArr.map(function(c, i) {
// Convert to HSL and store original indices
return {color: rgbToHsl(c), index: i};
}).sort(function(c1, c2) {
// Sort by hue
return c1.color[0] - c2.color[0];
}).map(function(data) {
// Retrieve original RGB color
return rgbArr[data.index];
});
Here is a practical example (credits to Ionică Bizău):
function display(container, arr) {
container = document.querySelector(container);
arr.forEach(function(c) {
var el = document.createElement("div");
el.style.backgroundColor = "rgb(" + c.join(", ") + ")";
container.appendChild(el);
})
}
function rgbToHsl(c) {
var r = c[0] / 255,
g = c[1] / 255,
b = c[2] / 255;
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return new Array(h * 360, s * 100, l * 100);
}
var rgbArr = [];
for (var i = 0; i < 100; ++i) {
rgbArr.push([
Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256)
]);
}
display("#before", rgbArr);
var sortedRgbArr = rgbArr.map(function(c, i) {
// Convert to HSL and store original indices
return {color: rgbToHsl(c), index: i};
}).sort(function(c1, c2) {
// Sort by hue
return c1.color[0] - c2.color[0];
}).map(function(data) {
// Retrieve original RGB color
return rgbArr[data.index];
});
display("#after", sortedRgbArr);
#before > div,
#after > div {
width: 1%;
height: 20px;
display: inline-block;
}
Random colors: <div id="before"></div>
Same colors, sorted by hue: <div id="after"></div>
sortedRgbArr
will store the rgb colors from rgbArr
arranged in a manner similar to the visible spectrum.
The issue arises when comparing your created spectrum with the HSL spectrum which does not consist of all colors, such as pink.
This lack of certain colors might be due to the fact that pink is not naturally occurring and is derived from blending opposite ends of the light's spectrum in RGB. Hence, a decision needs to be made regarding its placement.
Furthermore, it appears that your spectrum progresses from lower to higher wavelength but not frequency, making it a reverse of the HSL spectrum.
To align with your spectrum, replace c1.color[0] - c2.color[0]
with c2.color[0] - c1.color[0]
.