J'ai besoin d'un convertisseur de couleurs pour convertir des valeurs hsl en rgb et hex. Je vais faire des choses similaires comme this . J'utilise jquery et jquery ui range slider pour cela. Voici mon 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;
}
});
});
Je veux la solution comme ça:
l'entrée au convertisseur peut être donnée par les variables. comme hsl_hue
hsl_saturation
hsl_light
.
Y a-t-il un moyen de faire ça?
sinon, que puis-je faire?
/**
* 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)];
}
Vous pouvez trouver plus d'informations ici - conversion de couleurs HSL en RVB
Prend degree, percentage, percentage
et renvoie css hex
couleur:
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)}`;
}
Exemple:
hslToHex(360, 100, 50) // "#ff0000" -> red
J'ai récemment eu des raisons de résoudre ce problème et j'ai trouvé une solution basée sur un canevas. Je l'enregistre ici uniquement pour la postérité.
Dans mon cas, je devais également tenir compte des effets cumulatifs sur la conversion, étant donné une gamme de couleurs de fond et un canal alpha semi-transparent ...
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"
}
*/
Comme vous pouvez le voir sur les résultats ci-dessus, les valeurs HEX ne sont pas particulièrement représentatives lorsqu'il y a un canal alpha en entrée mais aucune couleur d'arrière-plan spécifiée - car le canevas voit essentiellement un arrière-plan transparent comme noir. Néanmoins, la valeur rgba
est restée cohérente.
Quoi qu'il en soit, j'ai réalisé ce dont j'avais besoin, et peut-être que cela sera utile à quelqu'un, parfois.
BP
Essayez ceci ( wiki , erreur analyse , plus: rgb2hsl , hsv2rgbrgb2hsv et sl22sv )
// 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)];
}
Pour calculer hsl2hex, utilisez rgb2hex(...hsl2rgb(30,1,0.5))
. Pour convertir une chaîne à partir d'un format, par exemple rgb(255, 255, 255)
en hexadécimal utilise rgbStrToHex
(qui gère la casse de chaîne vide)
// r,g,b are in [0-1], result e.g. #0812fa.
let rgb2hex = (r,g,b) => "#"+[r,g,b].map(x=>Math.round(x*255).toString(16).padStart(2,0)).join('');
// rgbStr e.g. "rgb(255, 255,255)", result e.g. #ffffff.
let rgbStrToHex = (rgbStr) => rgbStr && '#'+rgbStr.slice(4,-1).split(', ').map(x => (+x).toString(16).padStart(2, '0')).join('');
// 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)];
let rgb2hex = (r,g,b) => "#" + [r,g,b].map(x=>Math.round(x*255).toString(16).padStart(2,0) ).join('');
let rgbStrToHex = (rgbStr) => rgbStr && '#'+rgbStr.slice(4,-1).split(',').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(`str: "rgb(255,100, 123)" --> 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+a-n-1));
let h= n && ((a==r) ? (g-b)/n : ((a==g) ? 2+(b-r)/n : 4+(r-g)/n));
return [60*(h<0?h+6:h), f ? n/f : 0, (a+a-n)/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>
J'ai créé une petite bibliothèque qui peut facilement convertir les couleurs.
Voici ma méthode HSL vers RGB, qui utilise quelques autres méthodes utilitaires de la bibliothèque:
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);
};
Si vous ne voulez pas utiliser npm, la lib peut également être trouvée sur GitHub .
Une autre façon de résoudre ce problème consiste à tirer parti de la capacité window.getComputedStyle
des navigateurs modernes:
Créez un élément sur la page (il peut être masqué, par exemple avec display:none
, Mais cela semble supprimer la sortie de la valeur d'opacité/"A")
Définissez une propriété de couleur de cet élément en utilisant la représentation de votre choix, par ex. e.style.color = 'hsla(100, 50%, 75%, 0.8)';
(ou même des couleurs nommées comme 'rebeccapurple'
)
Relisez la valeur à l'aide de window.getComputedStyle(e).color
. Ce sera une chaîne de la forme rgb(r,g,b)
ou rgba(r,g,b,a)
.