Search code examples
javascriptcolorscolor-scheme

Javascript vibrant color chooser


I am looking for a vanilla Javascript method to choose either hexadecimal or RGB color values for a blocky-but-continuous spectrum of colors. The method should be able to specify a number of divisions/blocks and return, in any way, colors that fit the following criteria:

  • Vibrant: Not too dark or too light. I don't want to have black or white in there. The colors should be pretty bright in saturation, but just middling in lightness. Also, avoiding gray would be awesome but optional.
  • Continuous: Each range/block's color should approximately match the past and future colors. The colors should "flow" in a way, not clash with each other. Colors should not repeat (it's a spectrum).
  • Reproducible: If the method is given the same number of blocks but is run on a different machine at a different time, the colors chosen should be the same. If more divisions are added, the colors should only "shift", making the spectrum smoother, and decreasing the difference between consecutive colors.

This example was styled as randomly-sized HTML divs. I don't even have the HTML code for this.

Example

Any help or pointers would be awesome!


Solution

  • Here's a quick and dirty solution that I believe meets the requirements you've specified. Specifically -

    • Vibrant - Eye of the beholder in my opinion, but it seems vibrant.
    • Continuous - Created by modifying the hue value of an hsla color, which is by definition, around the color wheel.
    • Reproducible - Output will match in any JavaScript engine.

    colorSpectrum = function(count) {
        if (count <= 0) { 
            throw new Error('Count must be atleast 1'); 
        }
        
        var h = 0,
            s = '75%', 
            l = '50%',
            a = 1,
            current = 0,
            colors = [],
            tohsla = function(h,s,l,a) {
                return 'hsla(' + h + ',' + s + ',' + l + ',' + a + ')';
            }
        
        while (current < count) {
            colors.push({
                h:h, 
                s:s, 
                l:l, 
                a:a
            });
            h += 360 / count; 
            current++; 
        }
        
        return {
            colors:colors.map(function(el) {
                return tohsla(el.h, el.s, el.l, el.a); 
            })
        }
    };
    
    var colors = colorSpectrum(24); 
    
    colors.colors.forEach(function(color) { 
        var span = document.createElement('span'), 
            bodyWidth = parseInt(getComputedStyle(document.body).width, 10); 
        console.log(colors.colors.length);
        span.classList.add('color');
        span.style.backgroundColor = color; 
        span.style.width = bodyWidth / colors.colors.length + 'px'; 
        document.body.appendChild(span); 
    }); 
    .color {
        height:12px;
        display:inline-block;
    }