Javascript - Sort rgb values

前端 未结 2 2045
攒了一身酷
攒了一身酷 2020-12-13 16:22

Using javascript/jquery, I want to sort an array of rgba values to the colours of the visible spectrum. By doing this, like shades should be bunched together. Is there a plu

相关标签:
2条回答
  • 2020-12-13 17:01

    Disclosure: I'm the author of the library recommended below.

    If you don't mind using a library, here's a much more concise version of Oriol's detailed response. It uses the sc-color library:

    var sorted = colorArray.sort(function(colorA, colorB) {
        return sc_color(colorA).hue() - sc_color(colorB).hue();
    });
    
    0 讨论(0)
  • 2020-12-13 17:19

    If your array of colors is like this:

    var rgbArr = [c1, c2, c3, ...]
    

    where each color ci is an array of three numbers between 0 and 255

    ci = [red, green, blue]
    

    then, you can use this function to convert the colors to HSL

    function rgbToHsl(c) {
      var r = c[0]/255, g = c[1]/255, b = c[2]/255;
      var max = Math.max(r, g, b), min = Math.min(r, g, b);
      var h, s, l = (max + min) / 2;
    
      if(max == min) {
        h = s = 0; // achromatic
      } else {
        var d = max - min;
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
        switch(max){
          case r: h = (g - b) / d + (g < b ? 6 : 0); break;
          case g: h = (b - r) / d + 2; break;
          case b: h = (r - g) / d + 4; break;
        }
        h /= 6;
      }
      return new Array(h * 360, s * 100, l * 100);
    }
    

    and sort them by hue

    var sortedRgbArr = rgbArr.map(function(c, i) {
      // Convert to HSL and keep track of original indices
      return {color: rgbToHsl(c), index: i};
    }).sort(function(c1, c2) {
      // Sort by hue
      return c1.color[0] - c2.color[0];
    }).map(function(data) {
      // Retrieve original RGB color
      return rgbArr[data.index];
    });
    

    Here is a runnable example (thanks Ionică Bizău):

    function display(container, arr) {
      container = document.querySelector(container);
      arr.forEach(function(c) {
        var el = document.createElement("div");
        el.style.backgroundColor = "rgb(" + c.join(", ") + ")";
        container.appendChild(el);
      })
    }
    function rgbToHsl(c) {
      var r = c[0] / 255,
          g = c[1] / 255,
          b = c[2] / 255;
      var max = Math.max(r, g, b),
          min = Math.min(r, g, b);
      var h, s, l = (max + min) / 2;
    
      if (max == min) {
        h = s = 0; // achromatic
      } else {
        var d = max - min;
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
        switch (max) {
          case r:
            h = (g - b) / d + (g < b ? 6 : 0);
            break;
          case g:
            h = (b - r) / d + 2;
            break;
          case b:
            h = (r - g) / d + 4;
            break;
        }
        h /= 6;
      }
      return new Array(h * 360, s * 100, l * 100);
    }
    
    var rgbArr = [];
    for (var i = 0; i < 100; ++i) {
      rgbArr.push([
        Math.floor(Math.random() * 256),
        Math.floor(Math.random() * 256),
        Math.floor(Math.random() * 256)
      ]);
    }
    display("#before", rgbArr);
    
    var sortedRgbArr = rgbArr.map(function(c, i) {
      // Convert to HSL and keep track of original indices
      return {color: rgbToHsl(c), index: i};
    }).sort(function(c1, c2) {
      // Sort by hue
      return c1.color[0] - c2.color[0];
    }).map(function(data) {
      // Retrieve original RGB color
      return rgbArr[data.index];
    });
    display("#after", sortedRgbArr);
    #before > div,
    #after > div {
      width: 1%;
      height: 20px;
      display: inline-block;
    }
    Random colors: <div id="before"></div>
    Same colors, sorted by hue: <div id="after"></div>

    sortedRgbArr will contain the rgb colors of rgbArr sorted more or less like the colors of the visible spectrum.

    The problem is that the HSL spectrum looks like this:

    HSL spectrum

    Your spectrum is weird because it doesn't have all colors, such as pink.

    I guess that's because pink doesn't exist in the nature, it's a combination of the colors of the opposite extremes of light's spectrum. But we have it in rgb, so you have to decide where do you want it.

    Moreover, it seems that your spectrum goes from lower to higher wavelength, not frequency. But then your spectrum is a reverse of HSL's spectrum.

    Replace c1.color[0] - c2.color[0] with c2.color[0] - c1.color[0] if you want it like your spectrum.

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