Search code examples
javascriptc#colors

How can I generate a list of random shades of a particular color? (e.g. random shade of orange)


Has anyone come across a way to choose a random shade of a particular color? Sounds silly at first, but what I'm trying to do is come up with an automated way to generate chart series colors, and those colors need to be branded. So it seems reasonable that there is a way to maybe generate a range of color values for a particular color range; I've some examples on the web but not the logic.

So I'm looking for a way to say: generate a list of shades of Red, or Orange, or Green, etc. "Well, what constitutes a 'green' ?" Ok well maybe if I provide a hex value, the library/class could determine that it is a green and then generate a list of other greens, etc. So that way, before rendering the chart, I could say "This brand uses a color scheme that uses lots of blues, so randomly choose series colors that are types of blues." Does that make sense? This is in either C# or Javascript would be helpful.

I'd rather understand how to build one myself, but if any libraries already exist out there, it would be helpful.


Solution

  • The simplest way I can think of is to:

    use hsl (Hue, Saturation, Lightness) colors.
    The range is expressed like:

    hsl([0-360], [0-100]%, [0-100]%)
          HUE     SATUR.    LIGHT.
    

    Think of Hue as a 360° clockwise wheel, where 0 and 360 are Red, in between you have all the other ones:

    enter image description here

    Now you can retrieve from that wheel 12 basic colors moving by steps of 30° :

    0%  : RED
    30% : ORANGE
    60% : YELLOW
    90% : CHARTREUSE GREEN
    120%: GREEN
    150%: TURQUOISE
    180%: CYAN
    210%: AZURE
    240%: BLUE
    270%: VIOLET
    300%: MAGENTA
    330%: ROSE
    

    You can than generate some steps of lightness and saturation at random or by (i.e.) 20% steps.

    Saturation: Having lightness at 50% and setting Saturation at 0% you'll get the exact equivalent of Pure Gray (HEX: #808080 RGB: rgb(128,128,128) *Wiki: Middle Gray) so think of saturation as a gray-to-full-color unit.

    Lightness, range from 0% being black to 100% as white - applied to a selected color.

    (Logically from the above you can conclude that lightness affects Saturation also.)


    Let's put the above together!

    // DOM Utils
    const el = (sel, par = document) => par.querySelector(sel);
    const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
    
    // Utils
    const rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
    
    // TASK: Random colors shades generator
    const numOfShades = 20; // Set here the Desired number of Shades
    const elSelect = el("#color");
    const elResult = el("#result");
    const elGenerate = el("#generate");
    
    const createShadeElement = (hsl) => {
      const elShade = elNew("span");
      elShade.style.backgroundColor = hsl;
      elResult.appendChild(elShade);
    };
    
    const generateShades = () => {
      elResult.innerHTML = "";      // Empty current results
      const hue = elSelect.value;   // The Select Value: 0->360
    
      createShadeElement(`hsl(${hue}, 100%, 50%)`); // Create The main color
    
      for(var i=0; i<numOfShades; i++){ // and create all the other shades
        const hsl = `hsl(${hue}, ${rand(10,90)}%, ${rand(10, 90)}%)`;
        createShadeElement(hsl);
      }
    };
    
    elGenerate.addEventListener("click", generateShades);
    generateShades();
    #result > span{
      display: inline-block;
      margin: 0.2em;
      width: 40px;
      height: 40px;
      border-radius: 5px;
    }
    <select id="color">
      <option value="0"> RED</option>
      <option value="30">ORANGE</option>
      <option value="60">YELLOW</option>
      <option value="90">CHARTREUSE GREEN</option>
      <option value="120">GREEN</option>
      <option value="150">TURQUOISE</option>
      <option value="180">CYAN</option>
      <option value="210">AZURE</option>
      <option value="240">BLUE</option>
      <option value="270">VIOLET</option>
      <option value="300">MAGENTA</option>
      <option value="330">ROSE</option>
    </select>
    <button id="generate" type="button">Regenerate</button>
    
    <div id="result"></div>


    As a final thought, instead of having a <select> dropdown, you could instead use a color-wheel image (like the one I've provided above), track the click coordinates and using some simple trigonometry retrieve the correspondent degree that you can than use as hsl color.