javascript jquery colors converter color-picker

javascript - convertir Hsl a rgb y hexadecimal



jquery colors (6)

HSL a RGB:

/** * 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)]; }


Puede encontrar más información aquí: conversión de color HSL a RGB

Necesito un convertidor de color para convertir de hsl a rgb y valor hexadecimal. Voy a hacer algo similar a esto . Estoy usando jquery y jquery ui range slider para esto. Aquí está mi código:

$(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; } }); });

Quiero la solución como esta:

la entrada al convertidor puede ser dada por las variables. como hsl_hue hsl_saturation hsl_light .

¿Hay alguna forma de hacer esto?
Si no, ¿qué puedo hacer?


He creado una pequeña biblioteca que puede convertir fácilmente los colores.

Este es mi método HSL a RGB, que utiliza algunos otros métodos de utilidad de la biblioteca:

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 no desea usar npm, la lib también se puede encontrar en GitHub .


Otra forma de resolver este problema es aprovechar la capacidad window.getComputedStyle de los navegadores modernos:

  1. Cree un elemento en la página (se puede ocultar, por ejemplo, con display:none , pero parece que suprime la salida del valor de opacidad / "A")

  2. Establezca una propiedad con valor de color de ese elemento utilizando la representación que elija, por ejemplo, e.style.color = ''hsla(100, 50%, 75%, 0.8)''; (o incluso colores nombrados como ''rebeccapurple'' )

  3. Lea el valor nuevamente usando window.getComputedStyle(e).color . Será una cadena de la forma rgb(r,g,b) o rgba(r,g,b,a) .

Demostración en vivo en CodePen


Pruebe esto ( wiki , analysis errores, más: rgb2hsl , hsv2rgb rgb2hsv y 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)]; }

Para calcular hsl2hex use rgb2hex(...hsl2rgb(30,1,0.5)) . Para convertir cadenas de formato, por ejemplo, rgb(255, 255, 255) a hexadecimal, use rgbStrToHex (que maneja el caso de cadena vacía)

// 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>


Recientemente tuve motivos para resolver este problema y se me ocurrió una solución basada en el lienzo. Lo estoy registrando aquí solo para la posteridad.

En mi caso, también necesitaba tener en cuenta los efectos acumulativos en la conversión, dada una gama de colores de fondo y un canal alfa semitransparente ...

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" } */

Como puede ver en los resultados anteriores, los valores HEX no son particularmente representativos cuando hay un canal alfa en la entrada pero no se especifica el color de fondo, ya que el lienzo básicamente ve un fondo transparente como negro. No obstante, el valor rgba mantuvo coherente.

De todos modos, logré lo que necesitaba, y tal vez esto sea de alguna utilidad para alguien, en algún momento.

BP


Toma degree, percentage, percentage y devuelve el color hex CSS:

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)}`; }

Ejemplo:

hslToHex(360, 100, 50) // "#ff0000" -> red