I need a color converter to convert from hsl to rgb and hex value. I am going to do similar like this . I am using jquery and jquery ui range slider for this. Here is my code:
$(function() {
$( "#hsl_hue_range" ).slider({
min: 0,
max: 100,
value: 0,
range: false,
animate:"slow",
orientation: "horizontal",
slide: function( event, ui ) {
var hsl_hue = ui.value;
}
});
});
$(function() {
$( "#hsl_saturation_range" ).slider({
min: 0,
max: 100,
value: 0,
range: false,
animate:"slow",
orientation: "horizontal",
slide: function( event, ui ) {
var hsl_saturation = ui.value;
}
});
});
$(function() {
$( "#hsl_light_range" ).slider({
min: 0,
max: 100,
value: 0,
range: false,
animate:"slow",
orientation: "horizontal",
slide: function( event, ui ) {
var hsl_light = ui.value;
}
});
});
I want the solution like this:
the input to converter can be given by the variables. like hsl_hue
hsl_saturation
hsl_light
.
Is there any way to do this?
if no way, what can I do?
New approach (inspired by @Kamil-Kiełczewski solution )
Takes degree, percentage, percentage
and returns css hex
color:
function hslToHex(h, s, l) {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0'); // convert to Hex and prefix "0" if needed
};
return `#${f(0)}${f(8)}${f(4)}`;
}
Example:
hslToHex(360, 100, 50) // "#ff0000" -> red
Takes degree, percentage, percentage
and returns css hex
color:
function hslToHex(h, s, l) {
h /= 360;
s /= 100;
l /= 100;
let r, g, b;
if (s === 0) {
r = g = b = l; // achromatic
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
const toHex = x => {
const hex = Math.round(x * 255).toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
Example:
hslToHex(360, 100, 50) // "#ff0000" -> red
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param {number} h The hue
* @param {number} s The saturation
* @param {number} l The lightness
* @return {Array} The RGB representation
*/
function hslToRgb(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
var hue2rgb = function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
You can find more information here - HSL to RGB color conversion
Try this ( wiki , error analysis , more: rgb2hsl , hsv2rgb rgb2hsv and hsl2hsv )
// input: h in [0,360] and s,v in [0,1] - output: r,g,b in [0,1]
function hsl2rgb(h,s,l)
{
let a= s*Math.min(l,1-l);
let f= (n,k=(n+h/30)%12) => l - a*Math.max(Math.min(k-3,9-k,1),-1);
return [f(0),f(8),f(4)];
}
To calc hsl2hex use rgb2hex(...hsl2rgb(30,1,0.5))
. To convert string from format eg rgb(255, 255, 255)
to hex use rgbStrToHex
(which handle empty string case) as follows
// oneliner version let hsl2rgb = (h,s,l, a=s*Math.min(l,1-l), f= (n,k=(n+h/30)%12) => l - a*Math.max(Math.min(k-3,9-k,1),-1)) => [f(0),f(8),f(4)]; // r,g,b are in [0-1], result eg #0812fa. let rgb2hex = (r,g,b) => "#" + [r,g,b].map(x=>Math.round(x*255).toString(16).padStart(2,0) ).join(''); // hexStr eg #abcdef, result "rgb(171,205,239)" let hexStr2rgb = (hexStr) => `rgb(${hexStr.substr(1).match(/../g).map(x=>+`0x${x}`)})`; // rgb - color str eg"rgb(12,233,43)", result color hex eg "#0ce92b" let rgbStrToHex= rgb=> '#'+rgb.match(/\\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join`` console.log(`hsl: (30,0.2,0.3) --> rgb: (${hsl2rgb(30,0.2,0.3)}) --> hex: ${rgb2hex(...hsl2rgb(30,0.2,0.3))}`); console.log(`rgb: ${hexStr2rgb("#ff647b")} --> hex: ${rgbStrToHex("rgb(255,100, 123)")}`) // --------------- // UX // --------------- rgb= [0,0,0]; hs= [0,0,0]; let $ = x => document.querySelector(x); function changeRGB(i,e) { rgb[i]=e.target.value/255; hs = rgb2hsl(...rgb); refresh(); } function changeHS(i,e) { hs[i]=e.target.value/(i?255:1); rgb= hsl2rgb(...hs); refresh(); } function refresh() { rr = rgb.map(x=>x*255|0).join(', ') hh = rgb2hex(...rgb); tr = `RGB: ${rr}` th = `HSL: ${hs.map((x,i)=>i? (x*100).toFixed(2)+'%':x|0).join(', ')}` thh= `HEX: ${hh}` $('.box').style.backgroundColor=`rgb(${rr})`; $('.infoRGB').innerHTML=`${tr}`; $('.infoHS').innerHTML =`${th}\\n${thh}`; $('#r').value=rgb[0]*255; $('#g').value=rgb[1]*255; $('#b').value=rgb[2]*255; $('#h').value=hs[0]; $('#s').value=hs[1]*255; $('#l').value=hs[2]*255; } function rgb2hsl(r,g,b) { let a=Math.max(r,g,b), n=a-Math.min(r,g,b), f=(1-Math.abs(a+an-1)); let h= n && ((a==r) ? (gb)/n : ((a==g) ? 2+(br)/n : 4+(rg)/n)); return [60*(h<0?h+6:h), f ? n/f : 0, (a+an)/2]; } refresh();
.box { width: 50px; height: 50px; margin: 20px; } body { display: flex; }
<div> <input id="r" type="range" min="0" max="255" oninput="changeRGB(0,event)">R<br> <input id="g" type="range" min="0" max="255" oninput="changeRGB(1,event)">G<br> <input id="b" type="range" min="0" max="255" oninput="changeRGB(2,event)">B<br> <pre class="infoRGB"></pre> </div> <div> <div class="box hsl"></div> </div> <div> <input id="h" type="range" min="0" max="360" oninput="changeHS(0,event)">H<br> <input id="s" type="range" min="0" max="255" oninput="changeHS(1,event)">S<br> <input id="l" type="range" min="0" max="255" oninput="changeHS(2,event)">L<br> <pre class="infoHS"></pre><br> </div>
Another way to solve this problem is to leverage the window.getComputedStyle
capability of modern browsers:
Create an element on the page (it can be hidden, eg with display:none
, but that appears to suppress output of the opacity / "A" value)
Set a color-valued property of that element using the representation of your choice, eg e.style.color = 'hsla(100, 50%, 75%, 0.8)';
(or even named colors like 'rebeccapurple'
)
Read the value back using window.getComputedStyle(e).color
. It will be a string of the form rgb(r,g,b)
or rgba(r,g,b,a)
.
I've made a small library that can easily convert colors.
This is my HSL to RGB method, which uses a few other utility methods from the library:
Color.hslToRgb = function(hsl, formatted) {
var a, b, g, h, l, p, q, r, ref, s;
if (isString(hsl)) {
if (!hsl.match(Color.HSL_REGEX)) {
return;
}
ref = hsl.match(/hsla?\((.+?)\)/)[1].split(',').map(function(value) {
value.trim();
return parseFloat(value);
}), h = ref[0], s = ref[1], l = ref[2], a = ref[3];
} else if ((isObject(hsl)) && (hasKeys(hsl, ['h', 's', 'l']))) {
h = hsl.h, s = hsl.s, l = hsl.l, a = hsl.a;
} else {
return;
}
h /= 360;
s /= 100;
l /= 100;
if (s === 0) {
r = g = b = l;
} else {
q = l < 0.5 ? l * (1 + s) : l + s - l * s;
p = 2 * l - q;
r = Color.hueToRgb(p, q, h + 1 / 3);
g = Color.hueToRgb(p, q, h);
b = Color.hueToRgb(p, q, h - 1 / 3);
}
return getRgb(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a, formatted);
};
If you don't want to use npm, the lib can also be found on GitHub .
I recently had cause to solve this problem and came up with a canvas-based solution. I'm logging it here for posterity only.
In my case I also needed to account for the cumulative effects on the conversion given a range of background colors and a semi-transparent alpha channel...
var HSL2COLOR = function () {
return function (hsl, bg) {
function checkHex(v) {
return 1 === v.length ? '0'+v : v;
}
var data, r, g, b, a,
cnv = document.createElement('canvas'),
ctx = cnv.getContext('2d'),
alpha = /a\(/.test(hsl),
output = {};
return cnv.width = cnv.height = 1,
bg && (ctx.fillStyle = bg, ctx.fillRect(0, 0, 1, 1)),
ctx.fillStyle = hsl,
ctx.fillRect(0, 0, 1, 1),
data = ctx.getImageData(0, 0, 1, 1).data,
r = data[0],
g = data[1],
b = data[2],
a = (data[3] / 255).toFixed(2),
alpha ? (output.hsla = hsl, bg ? output.rgb = 'rgb('+r+','+g+','+b+')' : output.rgba = 'rgb('+r+','+g+','+b+','+a+')') : (output.hsl = hsl, output.rgb = 'rgb('+r+','+g+','+b+')'),
output.hex = '#'+checkHex(r.toString(16))+checkHex(g.toString(16))+checkHex(b.toString(16)),
output;
};
}();
// hsl: no alpha-channel + no background color
console.log(HSL2COLOR('hsl(170, 60%, 45%)'));
/*=> {
hsl: "hsl(170, 60%, 45%)",
rgb: "rgb(45,183,160)",
hex: "#2db7a0"
}
*/
// hsla: alpha-channel + no background color
console.log(HSL2COLOR('hsla(170, 60%, 45%, 0.35)'));
/*=> {
hsla: "hsla(170, 60%, 45%, 0.35)",
rgba: "rgb(42,183,160,0.35)",
hex: "#2ab7a0"
}
*/
// hsla: alpha-channel + background color
console.log(HSL2COLOR('hsla(170, 60%, 45%, 0.35)','#f00'));
/*=> {
hsla: "hsla(170, 60%, 45%, 0.35)",
rgb: "rgb(181,64,56)",
hex: "#b54038"
}
*/
As you can see from the results above, HEX values are not particularly representative when there is an alpha-channel in the input but no background color specified - as the canvas basically sees a transparent background as black. Nonetheless, the rgba
value remained coherent.
Anyway, I achieved what I needed to, and perhaps this will be of some use to someone, sometime.
BP
Or you could npm install color-convert
and not re-invent the wheel.
const convert = require('color-convert')
const hex = '#' + convert.hsl.hex(96, 48, 59) // convert hsl to hex
const rgb = convert.hsl.rgb(96, 48, 59) // convert hsl to rgb
Life can be simple at times.
from @icl7126 's answer,
you can add another function param to include alpha
function hsl2hex(h,s,l,alpha) {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0');
// convert to Hex and prefix "0" if needed
};
//alpha conversion
alpha = Math.round(alpha * 255).toString(16).padStart(2, '0');
return `#${f(0)}${f(8)}${f(4)}${alpha}`;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.