Reputation: 1408
I am trying to create a color slider and have the background color of the slider change dynamically. Here are the color formats I want to have:
I was able to get RGB, HSL, and HS but not V (from HSV) and LAB. How can I get the correct gradient to fill V and LAB?
The code snippet below, the code isn't fully functional. Meaning there isn't all the color converters. So don't expect it to work interactively. I'm working on that part. My question is only about the gradients. So the only part you have to look at is in the setColor
function.
var rInput, gInput, bInput, hInput, sInput, lInput;
window.onload = function() {
rInput = document.getElementById("r");
gInput = document.getElementById("g");
bInput = document.getElementById("b");
hInput = document.getElementById("h");
sInput = document.getElementById("s");
lInput = document.getElementById("l");
hhInput = document.getElementById("hh");
ssInput = document.getElementById("ss");
vInput = document.getElementById("v");
lInput = document.getElementById("l");
aInput = document.getElementById("a");
bbInput = document.getElementById("bb");
setColorFromRgb();
}
function setColor() {
document.getElementById('preview').style.backgroundColor = "rgb(" + rInput.value + "," + gInput.value + "," + bInput.value + ")";
setGradient(rInput, [rgb(0, gInput.value, bInput.value), rgb(255, gInput.value, bInput.value)]);
setGradient(gInput, [rgb(rInput.value, 0, bInput.value), rgb(rInput.value, 255, bInput.value)]);
setGradient(bInput, [rgb(rInput.value, gInput.value, 0), rgb(rInput.value, gInput.value, 255)]);
setGradient(hInput, [hsl(0, sInput.value, lInput.value), hsl(60, sInput.value, lInput.value), hsl(120, sInput.value, lInput.value), hsl(180, sInput.value, lInput.value), hsl(300, sInput.value, lInput.value), hsl(360, sInput.value, lInput.value)]);
setGradient(sInput, [hsl(hInput.value, 0, lInput.value), hsl(hInput.value, 100, lInput.value)]);
setGradient(lInput, [hsl(hInput.value, sInput.value, 0), hsl(hInput.value, sInput.value, 50), hsl(hInput.value, sInput.value, 100)]);
setGradient(hhInput, [hsv(0, ssInput.value, vInput.value), hsv(60, ssInput.value, vInput.value), hsv(120, ssInput.value, vInput.value), hsv(180, ssInput.value, vInput.value), hsl(300, ssInput.value, vInput.value), hsv(360, ssInput.value, vInput.value)]);
setGradient(ssInput, [hsv(hhInput.value, 0, vInput.value), hsv(hhInput.value, 100, vInput.value)]);
}
function setRgbSliders(r, g, b) {
rInput.value = r;
gInput.value = g;
bInput.value = b;
}
function setHslSliders(h, s, l) {
hInput.value = h;
sInput.value = s;
lInput.value = l;
}
function setHsvSliders(h, s, v) {
hhInput.value = h;
ssInput.value = s;
vInput.value = v;
}
function setHsvSliders(l, a, b) {
lInput.value = l;
aInput.value = a;
bbInput.value = b;
}
function setColorFromRgb() {
hslValues = rgbToHsl(rInput.value, gInput.value, bInput.value);
setHslSliders(hslValues[0], hslValues[1], hslValues[2]);
setColor();
}
function setColorFromHsl() {
rgbValues = hslToRgb(hInput.value, sInput.value, lInput.value);
setRgbSliders(rgbValues[0], rgbValues[1], rgbValues[2]);
setColor();
}
function setColorFromHsv() {
hsvValues = hsvToRgb(hhInput.value, ssInput.value, vInput.value);
setRgbSliders(hsvValues[0], hsvValues[1], hsvValues[2]);
setColor();
}
function setColorFromLab() {
hslValues = rgbToLab(lInput.value, aInput.value, bbInput.value);
setHslSliders(labValues[0], labValues[1], labValues[2]);
setColor();
}
function setGradient(el, steps) {
gradientString = "linear-gradient(to right,";
stepSize = 100 / (steps.length - 1);
for (var i = 0; i < steps.length; i++) {
gradientString += (i > 0 ? "," : "") + steps[i] + (i * stepSize) + "%";
}
el.style.backgroundImage = gradientString + ")";
}
/**
* Formats the given RGB values into a string that can be used in CSS
*/
function rgb(r, g, b) {
return "rgb(" + r + "," + g + "," + b + ")";
}
function hsl(h, s, l) {
return "hsl(" + h + "," + s + "%," + l + "%)";
}
function hsv(h, s, v) {
return "hsl(" + h + "," + s + "%," + v + "%)";
}
function lab(l, a, b) {
return "lab(" + l + "," + a + "%," + b + "%)";
}
/**
* Takes HSL values (H between 0 and 360, S and L each between 0 and 100) and returns the corresponding RGB values (each between 0 and 255)
* Based on pseudo-code in the W3 Color Model document (http://www.w3.org/TR/2011/REC-css3-color-20110607/#hsl-color)
*/
function hslToRgb(h, s, l) {
var m1, m2, m3, r, g, b;
h = h / 360;
s = s / 100;
l = l / 100;
m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
m1 = l * 2 - m2;
r = hueToRgb(m1, m2, h + 1 / 3);
g = hueToRgb(m1, m2, h);
b = hueToRgb(m1, m2, h - 1 / 3);
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]
}
function hueToRgb(m1, m2, h) {
if (h < 0) {
h = h + 1;
} else if (h > 1) {
h = h - 1;
}
if (h * 6 < 1) {
return m1 + (m2 - m1) * h * 6;
} else if (h * 2 < 1) {
return m2;
} else if (h * 3 < 2) {
return m1 + (m2 - m1) * (2 / 3 - h) * 6
}
return m1;
}
/**
* Takes RGB values (each between 0 and 255) and returns the corresponding HSL values (H between 0 and 360, S and L each between 0 and 100).
* Based on http://stackoverflow.com/a/9493060
*/
function rgbToHsl(r, g, b) {
var max, min, h, s, l;
r = r / 255;
g = g / 255;
b = b / 255;
max = Math.max(r, g, b);
min = Math.min(r, g, b);
l = (min + max) / 2;
diff = max - min;
if (diff == 0) {
s = 0;
h = 0;
} else {
if (l > 0.5) {
s = (diff) / (2 - min - max)
} else {
s = diff / (max + min)
}
switch (max) {
case r:
h = (g - b) / diff + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / diff + 2;
break;
case b:
h = (r - g) / diff + 4;
break;
}
}
return [Math.round(h * 60), Math.round(s * 100), Math.round(l * 100)];
}
body {
background: #222;
color: #ddd;
font-family: sans-serif;
font-size: 12px;
width: 400px;
}
#preview {
display: inline-block;
float: left;
width: 100%;
height: 100px;
margin-bottom: 5px;
}
input[type=range] {
float: left;
width: 100%;
-webkit-appearance: none;
}
input[type=range],
#preview {
border-radius: 3px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3) inset, 0 1px 0 rgba(255, 255, 255, 0.3);
}
.colourSlider {
width: 400px;
}
.column {
display: inline-block;
width: 190px;
margin-right: 20px;
float: left;
}
.column:nth-child(2n) {
margin-right: 0;
}
.colourSlider input[type=range] {
float: left;
width: 100%;
-webkit-appearance: none;
height: 20px;
}
.colourSlider input[type=range],
.colourSlider #preview {
margin: 0;
border-radius: 3px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3) inset, 0 1px 0 rgba(255, 255, 255, 0.3);
}
.colourSlider input[type="range"]::-moz-range-track {
border: inherit;
background: transparent;
color: transparent;
}
.colourSlider input[type="range"]::-ms-track {
border: inherit;
background: transparent;
color: transparent;
}
<div id="preview"></div>
<div class="row colourSlider">
<div class="column">
R:
<input type="range" id="r" min="0" max="255" oninput="setColorFromRgb()">
<br>G:
<input type="range" id="g" min="0" max="255" oninput="setColorFromRgb()">
<br>B:
<input type="range" id="b" min="0" max="255" oninput="setColorFromRgb()">
</div>
<div class="column">
H:
<input type="range" id="h" min="0" max="360" oninput="setColorFromHsl()">
<br>S:
<input type="range" id="s" min="0" max="100" oninput="setColorFromHsl()">
<br>L:
<input type="range" id="l" min="0" max="100" oninput="setColorFromHsl()">
</div>
<div class="column">
H:
<input type="range" id="hh" min="0" max="360" oninput="setColorFromHsv()">
<br>S:
<input type="range" id="ss" min="0" max="100" oninput="setColorFromHsv()">
<br>V:
<input type="range" id="v" min="0" max="100" oninput="setColorFromHsv()">
</div>
<div class="column">
L:
<input type="range" id="ll" min="0" max="360" oninput="setColorFromLab()">
<br>A:
<input type="range" id="a" min="0" max="100" oninput="setColorFromLab()">
<br>B:
<input type="range" id="bb" min="0" max="100" oninput="setColorFromLab()">
</div>
</div>
Upvotes: 1
Views: 600
Reputation: 2462
I'm sorry if I didn't understand you right.
First of all you have two variables lInput
. I think the second one (for LAB) has to be llInput
(considering your naming technique).
Then you have to add setGradient()
functions. For V in HSV, for instance that should be setGradient(vInput, [hsv(hhInput.value, ssInput.value, 0), hsv(hhInput.value, ssInput.value, 100)]);
. Obviously you have only two function calls here (check yourself this block), they are for 'H' and 'S'.
Also, you have a typo here too, change hsl(300, ssInput.value, vInput.value)
to hsv(300, ssInput.value, vInput.value)
in the setGradient()
for HSV.
For lab it's exactly the same process, if we speak about just gradients, but you have to change the setGradient()
algorithm for this one, because css doesn't support LAB.
I hope this answer will help you :)
Upvotes: 1