convert Hsl to rgb and hex

后端 未结 6 2005
时光说笑
时光说笑 2020-11-27 07:47

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 co

相关标签:
6条回答
  • 2020-11-27 08:05

    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
    
    0 讨论(0)
  • 2020-11-27 08:05

    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

    0 讨论(0)
  • 2020-11-27 08:06

    Another way to solve this problem is to leverage the window.getComputedStyle capability of modern browsers:

    1. Create an element on the page (it can be hidden, e.g. with display:none, but that appears to suppress output of the opacity / "A" value)

    2. Set a color-valued property of that element using the representation of your choice, e.g. e.style.color = 'hsla(100, 50%, 75%, 0.8)'; (or even named colors like 'rebeccapurple')

    3. 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).

    Live demo on CodePen

    0 讨论(0)
  • 2020-11-27 08:09

    Shortest

    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 e.g. 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 e.g. #0812fa.
    let rgb2hex = (r,g,b) => "#" + [r,g,b].map(x=>Math.round(x*255).toString(16).padStart(2,0) ).join('');
    
    // hexStr e.g #abcdef, result "rgb(171,205,239)"
    let hexStr2rgb  = (hexStr) => `rgb(${hexStr.substr(1).match(/../g).map(x=>+`0x${x}`)})`;
    
    // rgb - color str e.g."rgb(12,233,43)", result color hex e.g. "#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+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>

    0 讨论(0)
  • 2020-11-27 08:13

    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.

    0 讨论(0)
  • 2020-11-27 08:17

    HSL to 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)];
        }
    


    You can find more information here - HSL to RGB color conversion

    0 讨论(0)
提交回复
热议问题