75

I am trying to randomly generate a color in hex in javascript.

However the colors generated are almost indistinguishable from eachother.
Is there a way to improve it?


Here is the code I am using:

function randomColor(){
   var allowed = "ABCDEF0123456789", S = "#";
    
   while(S.length < 7){
       S += allowed.charAt(Math.floor((Math.random()*16)+1));
   }
   return S;
}

I heard something about HSL and HSV color model but can't get it to work in my code.

starball
  • 20,030
  • 7
  • 43
  • 238
  • do you have some samples of the codes that were generated? remember that hex codes follow certain conventions – Barry Chapman Apr 04 '12 at 15:33
  • 3
    What exactly does "unrecognizable" mean here? I mean, are the pixels lighting up in ways such that your eyes cannot perceive the radiation? – Pointy Apr 04 '12 at 15:36
  • 1
    @Pointy The goggles, they do nothing! – Snuffleupagus Apr 04 '12 at 15:37
  • @Pointy basically I am using these colors in coloring nodes of a graph. But when displayed on a projector many of the nodes look almost identical. –  Apr 04 '12 at 15:39
  • Maybe you should add more variance between the colors 'allowed'. Maybe allow only the shorthand color elements: #aaa, #bbb, #ccc, #000, #333 etc – Barry Chapman Apr 04 '12 at 15:43
  • 2
    There is a fair bit of study about color differentiation. Especially in HCI research. http://en.wikipedia.org/wiki/Color_difference is a decent introduction. – idbentley Apr 04 '12 at 15:44
  • if you generated #A00000 and #A10000 the colors would be strikingly similar. – Barry Chapman Apr 04 '12 at 15:44
  • Allowing only shorthand colors does the job but this also increases repetition of same color. –  Apr 04 '12 at 15:48
  • @anuragsn7 - Then create an array of 'used' colors that cannot be used again. Check for their existance, if available, use it and stick it in the array. Wash rinse repeat. – Barry Chapman Apr 04 '12 at 15:49

11 Answers11

79

The easiest way to pick maximally different colors would be to to use HSL values instead of RGB and then manipulate Hue, as it has a value from 0 to 360 value and wraps around (0 is red, and so is 360);

if you need 10 distinguishable colors you can divide 360 by 10 and then pick the individual color by multiplying the value by index (zero based). Here's an example function that allows you to pick a color from :

function selectColor(colorNum, colors){
    if (colors < 1) colors = 1; // defaults to one color - avoid divide by zero
    return "hsl(" + (colorNum * (360 / colors) % 360) + ",100%,50%)";
}

This way you can randomize the color selection by randomizing index, but colors will always be in the same palette.

This will select a random color from a palette of 10:

var color = selectColor(Math.floor(Math.random() * 10), 10);

and so will this:

var color = selectColor(Math.floor(Math.random() * 999), 10);

or you can select a specific color from the palette, like 9th color (index 8) out of palette of 13:

var color = selectColor(8, 13);

Here's a fiddle to play with: http://jsfiddle.net/2UE2B/

Update on 2020-02-23:

So, today I needed a solution to this same problem. Googling for this answer here (I know, a very weird way to look for stuff on SO) I ran into the Golden Angle concept. It would make the above example even more trivial, and would not require a predetermined number of colors to be provided:

function selectColor(number) {
  const hue = number * 137.508; // use golden angle approximation
  return `hsl(${hue},50%,75%)`;
}

This answers the @netoperator-wibby's question

goran
  • 1,005
  • 1
  • 7
  • 7
  • I know this is a super late comment, but what if you don't know how many divs you're going to have for random colors? – NetOperator Wibby Apr 10 '17 at 16:46
  • 7
    This doesn't work because, for example, in green hues there is large range that is not easily distinguishable by humans. – Shital Shah Feb 22 '18 at 02:55
  • @ShitalShah I agree that it's not a perfect solution, and there are much better ways of picking differentiable colors. This is a quick-and-dirty way to solve the problem without going into the weeds too much, and such that can be easily updated with a more elaborate and better-suited algorithm if the need arises. A MVP if you will ;) – goran Nov 12 '19 at 15:40
  • 2
    @NetOperatorWibby Here's a super late answer: You could use a predetermined set of colors for your use case, let's say 20, that you optimistically expect never to fully use. If your use case has 200-300+ different divs, I doubt color-coding them individually would be a good approach in the first place. It's more of a heat-map at that point. – goran Nov 12 '19 at 15:43
  • 3
    Golden Angle example is here https://codepen.io/04/pen/gOPzYgv – 井上智文 Jul 08 '20 at 09:08
  • Great recommendation. I needed that for Chart.js, so I created a [CodeSandbox](https://codesandbox.io/s/react-playground-forked-xzm0sx) to display the result on a pie chart, compared to another great solution in [another answer](https://stackoverflow.com/a/71799066/3002584). – OfirD Apr 14 '22 at 19:38
33

Example

I know I'm very late to this party, but I wrote up a more elaborate function to generate a set of contrasting random colors for another project. They are both (at least somewhat) attractive and genuinely random (not based on predefined colors) but my code is a bit more complicated than some of the other responses (so it's not for just getting the basics)

This is for users who want to have more than one random color on their page, and want to make sure no two colors are too similar.

Fiddle

var generateRandomColors=function(number){
/*
This generates colors using the following algorithm:
Each time you create a color:
    Create a random, but attractive, color{
        Red, Green, and Blue are set to random luminosity.
        One random value is reduced significantly to prevent grayscale.
        Another is increased by a random amount up to 100%.
        They are mapped to a random total luminosity in a medium-high range (bright but not white).
    }
    Check for similarity to other colors{
        Check if the colors are very close together in value.
        Check if the colors are of similar hue and saturation.
        Check if the colors are of similar luminosity.
        If the random color is too similar to another,
        and there is still a good opportunity to change it:
            Change the hue of the random color and try again.
    }
    Output array of all colors generated
*/
    //if we've passed preloaded colors and they're in hex format
    if(typeof(arguments[1])!='undefined'&&arguments[1].constructor==Array&&arguments[1][0]&&arguments[1][0].constructor!=Array){
        for(var i=0;i<arguments[1].length;i++){ //for all the passed colors
            var vals = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(arguments[1][i]); //get RGB values
            arguments[1][i]=[parseInt(vals[1], 16),parseInt(vals[2], 16),parseInt(vals[3], 16)]; //and convert them to base 10
        }
    }
    var loadedColors=typeof(arguments[1])=='undefined'?[]:arguments[1],//predefine colors in the set
        number=number+loadedColors.length,//reset number to include the colors already passed
        lastLoadedReduction=Math.floor(Math.random()*3),//set a random value to be the first to decrease
        rgbToHSL=function(rgb){//converts [r,g,b] into [h,s,l]
            var r=rgb[0],g=rgb[1],b=rgb[2],cMax=Math.max(r,g,b),cMin=Math.min(r,g,b),delta=cMax-cMin,l=(cMax+cMin)/2,h=0,s=0;if(delta==0)h=0;else if(cMax==r)h=60*((g-b)/delta%6);else if(cMax==g)h=60*((b-r)/delta+2);else h=60*((r-g)/delta+4);if(delta==0)s=0;else s=delta/(1-Math.abs(2*l-1));return[h,s,l]
        },hslToRGB=function(hsl){//converts [h,s,l] into [r,g,b]
            var h=hsl[0],s=hsl[1],l=hsl[2],c=(1-Math.abs(2*l-1))*s,x=c*(1-Math.abs(h/60%2-1)),m=l-c/2,r,g,b;if(h<60){r=c;g=x;b=0}else if(h<120){r=x;g=c;b=0}else if(h<180){r=0;g=c;b=x}else if(h<240){r=0;g=x;b=c}else if(h<300){r=x;g=0;b=c}else{r=c;g=0;b=x}return[r,g,b]
        },shiftHue=function(rgb,degree){//shifts [r,g,b] by a number of degrees
            var hsl=rgbToHSL(rgb); //convert to hue/saturation/luminosity to modify hue
            hsl[0]+=degree; //increment the hue
            if(hsl[0]>360){ //if it's too high
                hsl[0]-=360 //decrease it mod 360
            }else if(hsl[0]<0){ //if it's too low
                hsl[0]+=360 //increase it mod 360
            }
            return hslToRGB(hsl); //convert back to rgb
        },differenceRecursions={//stores recursion data, so if all else fails we can use one of the hues already generated
            differences:[],//used to calculate the most distant hue
            values:[]//used to store the actual colors
        },fixDifference=function(color){//recursively asserts that the current color is distinctive
            if(differenceRecursions.values.length>23){//first, check if this is the 25th recursion or higher. (can we try any more unique hues?)
                //if so, get the biggest value in differences that we have and its corresponding value
                var ret=differenceRecursions.values[differenceRecursions.differences.indexOf(Math.max.apply(null,differenceRecursions.differences))];
                differenceRecursions={differences:[],values:[]}; //then reset the recursions array, because we're done now
                return ret; //and then return up the recursion chain
            } //okay, so we still have some hues to try.
            var differences=[]; //an array of the "difference" numbers we're going to generate.
            for(var i=0;i<loadedColors.length;i++){ //for all the colors we've generated so far
                var difference=loadedColors[i].map(function(value,index){ //for each value (red,green,blue)
                    return Math.abs(value-color[index]) //replace it with the difference in that value between the two colors
                }),sumFunction=function(sum,value){ //function for adding up arrays
                    return sum+value
                },sumDifference=difference.reduce(sumFunction), //add up the difference array
                loadedColorLuminosity=loadedColors[i].reduce(sumFunction), //get the total luminosity of the already generated color
                currentColorLuminosity=color.reduce(sumFunction), //get the total luminosity of the current color
                lumDifference=Math.abs(loadedColorLuminosity-currentColorLuminosity), //get the difference in luminosity between the two
                //how close are these two colors to being the same luminosity and saturation?
                differenceRange=Math.max.apply(null,difference)-Math.min.apply(null,difference),
                luminosityFactor=50, //how much difference in luminosity the human eye should be able to detect easily
                rangeFactor=75; //how much difference in luminosity and saturation the human eye should be able to dect easily
                if(luminosityFactor/(lumDifference+1)*rangeFactor/(differenceRange+1)>1){ //if there's a problem with range or luminosity
                    //set the biggest difference for these colors to be whatever is most significant
                    differences.push(Math.min(differenceRange+lumDifference,sumDifference));
                }
                differences.push(sumDifference); //otherwise output the raw difference in RGB values
            }
            var breakdownAt=64, //if you're generating this many colors or more, don't try so hard to make unique hues, because you might fail.
            breakdownFactor=25, //how much should additional colors decrease the acceptable difference
            shiftByDegrees=15, //how many degrees of hue should we iterate through if this fails
            acceptableDifference=250, //how much difference is unacceptable between colors
            breakVal=loadedColors.length/number*(number-breakdownAt), //break down progressively (if it's the second color, you can still make it a unique hue)
            totalDifference=Math.min.apply(null,differences); //get the color closest to the current color
            if(totalDifference>acceptableDifference-(breakVal<0?0:breakVal)*breakdownFactor){ //if the current color is acceptable
                differenceRecursions={differences:[],values:[]} //reset the recursions object, because we're done
                return color; //and return that color
            } //otherwise the current color is too much like another
            //start by adding this recursion's data into the recursions object
            differenceRecursions.differences.push(totalDifference);
            differenceRecursions.values.push(color);
            color=shiftHue(color,shiftByDegrees); //then increment the color's hue
            return fixDifference(color); //and try again
        },color=function(){ //generate a random color
            var scale=function(x){ //maps [0,1] to [300,510]
                return x*210+300 //(no brighter than #ff0 or #0ff or #f0f, but still pretty bright)
            },randVal=function(){ //random value between 300 and 510
                return Math.floor(scale(Math.random()))
            },luminosity=randVal(), //random luminosity
                red=randVal(), //random color values
                green=randVal(), //these could be any random integer but we'll use the same function as for luminosity
                blue=randVal(),
                rescale, //we'll define this later
                thisColor=[red,green,blue], //an array of the random values
                /*
                #ff0 and #9e0 are not the same colors, but they are on the same range of the spectrum, namely without blue.
                Try to choose colors such that consecutive colors are on different ranges of the spectrum.
                This shouldn't always happen, but it should happen more often then not.
                Using a factor of 2.3, we'll only get the same range of spectrum 15% of the time.
                */
                valueToReduce=Math.floor(lastLoadedReduction+1+Math.random()*2.3)%3, //which value to reduce
                /*
                Because 300 and 510 are fairly close in reference to zero,
                increase one of the remaining values by some arbitrary percent betweeen 0% and 100%,
                so that our remaining two values can be somewhat different.
                */
                valueToIncrease=Math.floor(valueToIncrease+1+Math.random()*2)%3, //which value to increase (not the one we reduced)
                increaseBy=Math.random()+1; //how much to increase it by
            lastLoadedReduction=valueToReduce; //next time we make a color, try not to reduce the same one
            thisColor[valueToReduce]=Math.floor(thisColor[valueToReduce]/16); //reduce one of the values
            thisColor[valueToIncrease]=Math.ceil(thisColor[valueToIncrease]*increaseBy) //increase one of the values
            rescale=function(x){ //now, rescale the random numbers so that our output color has the luminosity we want
                return x*luminosity/thisColor.reduce(function(a,b){return a+b}) //sum red, green, and blue to get the total luminosity
            };
            thisColor=fixDifference(thisColor.map(function(a){return rescale(a)})); //fix the hue so that our color is recognizable
            if(Math.max.apply(null,thisColor)>255){ //if any values are too large
                rescale=function(x){ //rescale the numbers to legitimate hex values
                    return x*255/Math.max.apply(null,thisColor)
                }
                thisColor=thisColor.map(function(a){return rescale(a)});
            }
            return thisColor;
        };
    for(var i=loadedColors.length;i<number;i++){ //Start with our predefined colors or 0, and generate the correct number of colors.
        loadedColors.push(color().map(function(value){ //for each new color
            return Math.round(value) //round RGB values to integers
        }));
    }
    //then, after you've made all your colors, convert them to hex codes and return them.
    return loadedColors.map(function(color){
        var hx=function(c){ //for each value
            var h=c.toString(16);//then convert it to a hex code
            return h.length<2?'0'+h:h//and assert that it's two digits
        }
        return "#"+hx(color[0])+hx(color[1])+hx(color[2]); //then return the hex code
    });
}

Please note, although I don't do so in my example, that this can also be used to add new distinct, random colors to a set:

generateRandomColors(1,generateRandomColors(10))
Scelesto
  • 775
  • 6
  • 13
32

You could use a fixed set of colors, such as the ones listed in the jquery.color.js plugin.

List of colors from jquery.color.js plugin:

Colors = {};
Colors.names = {
    aqua: "#00ffff",
    azure: "#f0ffff",
    beige: "#f5f5dc",
    black: "#000000",
    blue: "#0000ff",
    brown: "#a52a2a",
    cyan: "#00ffff",
    darkblue: "#00008b",
    darkcyan: "#008b8b",
    darkgrey: "#a9a9a9",
    darkgreen: "#006400",
    darkkhaki: "#bdb76b",
    darkmagenta: "#8b008b",
    darkolivegreen: "#556b2f",
    darkorange: "#ff8c00",
    darkorchid: "#9932cc",
    darkred: "#8b0000",
    darksalmon: "#e9967a",
    darkviolet: "#9400d3",
    fuchsia: "#ff00ff",
    gold: "#ffd700",
    green: "#008000",
    indigo: "#4b0082",
    khaki: "#f0e68c",
    lightblue: "#add8e6",
    lightcyan: "#e0ffff",
    lightgreen: "#90ee90",
    lightgrey: "#d3d3d3",
    lightpink: "#ffb6c1",
    lightyellow: "#ffffe0",
    lime: "#00ff00",
    magenta: "#ff00ff",
    maroon: "#800000",
    navy: "#000080",
    olive: "#808000",
    orange: "#ffa500",
    pink: "#ffc0cb",
    purple: "#800080",
    violet: "#800080",
    red: "#ff0000",
    silver: "#c0c0c0",
    white: "#ffffff",
    yellow: "#ffff00"
};

The rest is simply picking a random property from a Javascript object.

Colors.random = function() {
    var result;
    var count = 0;
    for (var prop in this.names)
        if (Math.random() < 1/++count)
           result = prop;
    return result;
};

Using Colors.random() might get you a human-readable color. I even powered an example below.

(function(){
    Colors = {};
    Colors.names = {
        aqua: "#00ffff",
        azure: "#f0ffff",
        beige: "#f5f5dc",
        black: "#000000",
        blue: "#0000ff",
        brown: "#a52a2a",
        cyan: "#00ffff",
        darkblue: "#00008b",
        darkcyan: "#008b8b",
        darkgrey: "#a9a9a9",
        darkgreen: "#006400",
        darkkhaki: "#bdb76b",
        darkmagenta: "#8b008b",
        darkolivegreen: "#556b2f",
        darkorange: "#ff8c00",
        darkorchid: "#9932cc",
        darkred: "#8b0000",
        darksalmon: "#e9967a",
        darkviolet: "#9400d3",
        fuchsia: "#ff00ff",
        gold: "#ffd700",
        green: "#008000",
        indigo: "#4b0082",
        khaki: "#f0e68c",
        lightblue: "#add8e6",
        lightcyan: "#e0ffff",
        lightgreen: "#90ee90",
        lightgrey: "#d3d3d3",
        lightpink: "#ffb6c1",
        lightyellow: "#ffffe0",
        lime: "#00ff00",
        magenta: "#ff00ff",
        maroon: "#800000",
        navy: "#000080",
        olive: "#808000",
        orange: "#ffa500",
        pink: "#ffc0cb",
        purple: "#800080",
        violet: "#800080",
        red: "#ff0000",
        silver: "#c0c0c0",
        white: "#ffffff",
        yellow: "#ffff00"
    };
    Colors.random = function() {
        var result;
        var count = 0;
        for (var prop in this.names)
            if (Math.random() < 1/++count)
               result = prop;
        return { name: result, rgb: this.names[result]};
    };
    var $placeholder = $(".placeholder");
    $placeholder.click(function(){
        var color = Colors.random();
        $placeholder.css({'background-color': color.rgb});
        $("#color").html("It's " + color.name);
    });
})();
.placeholder {
    width: 150px;
    height: 150px;
    border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="placeholder"></div>
<span id="color">Click the square above.</span>
Alexander
  • 23,432
  • 11
  • 63
  • 73
  • Thanks Alexander, I tried your example and I am getting fairly large range of different colors. Since I am already using jQuery it seems more appropriate also. –  Apr 04 '12 at 16:09
  • I was looking for a method to generate a random vivid readable color based on relative luminance (blue, yellow and green are darker) but this enters my list of "think simple" answers. I realized I just wanted a "random vivid readable color", not necessarily generate one. – Hay Apr 29 '16 at 22:57
  • I want to show different colors in Charts so, is there any possibility of duplicate color? Don't want to show same color for two different entity within Charts. – Parth Akbari Feb 10 '20 at 07:20
  • This solution works only if you have specific predefined colors for different required amounts. If you have too much predefined ones and only need a few there is a chance for similar colors. If you have a few predefined ones you can run out of them if you need a lot. – totymedli Jul 08 '21 at 03:17
  • A hybrid solution is to use predefined colors if you need less than 7 or 8 and use [goran's generator](https://stackoverflow.com/a/20129594/1494454) if you need more. – totymedli Jul 08 '21 at 03:20
10

Try this:

function getRandomColor() {
    var letters = '0123456789ABCDEF'.split('');
    var color = '#';
    for (var i = 0; i < 6; i++ ) {
        color += letters[Math.round(Math.random() * 15)];
    }
    return color;
}

See it in action: http://jsfiddle.net/3wjgG/1/

stealthyninja
  • 10,343
  • 11
  • 51
  • 59
Barry Chapman
  • 6,690
  • 3
  • 36
  • 64
  • 3
    Nice code but isn't this pretty much the same as what the OP has? – Pointy Apr 04 '12 at 15:39
  • No. Did you compare the scripts? – Barry Chapman Apr 04 '12 at 15:40
  • Yes its working. I multiplied 16 with Math.random() which resulted in index 16 which was not correct. But since problem was related to a strong variation in generated colors I will try Alexander's solution. Thanks for answers though. –  Apr 04 '12 at 16:32
9

What you are saying is that you do not want to generate random colors, you are saying that you want to generate different colors.
You can find a good tutorial on how to do it here: http://krazydad.com/tutorials/makecolors.php .

I made this fiddle with the relevant code from the tutorial demonstrating how you would generate non-repeating colors:

http://jsfiddle.net/rGL52/

The only differnce from the tutorial code is that the makegradient() function returns an array of colors that you can later apply at will in your page.

Michal
  • 13,439
  • 3
  • 35
  • 33
7

For randomly generating colors, I tend to go for something simple like this:

​function randomColor () {
    var max = 0xffffff;
    return '#' + Math.round( Math.random() * max ).toString( 16 );
}
​

I'm not sure what you mean by unrecognizable. This method doesn't offer much customization, but at very least makes it easy to keep numbers from being too light or too dark.

If you want to give bigger gaps between the generated colors, you could try reducing the number of allowed characters. I've used a method like that in the past where I only used 0369cf as the pool of characters to pull from. Combining this with a check for duplicates tends to give more distinguishable colors, as well as only utilizing the #fff 3-character syntax.

Here's your original function modified to use this method:

function randomColor(){
    var allowed = "0369cf".split( '' ), s = "#";
    while ( s.length < 4 ) {
       s += allowed.splice( Math.floor( ( Math.random() * allowed.length ) ), 1 );
    }
    return s;
}
Robert Messerle
  • 3,022
  • 14
  • 18
4

Unique color swatches

I needed to solve this problem today for a new course I'm writing, so here is my solution:

function getUniqueColor(n) {
    const rgb = [0, 0, 0];
  
  for (let i = 0; i < 24; i++) {
    rgb[i%3] <<= 1;
    rgb[i%3] |= n & 0x01;
    n >>= 1;
  }
  
  return '#' + rgb.reduce((a, c) => (c > 0x0f ? c.toString(16) : '0' + c.toString(16)) + a, '')
}

It "spreads" the bits from the input number through the RGB values, backwards. It's not perfect, but the code is compact and adjacent colors are distinguishable. Here is the fiddle.

Scott Means
  • 635
  • 6
  • 8
2

I agree with all the answers, we don't really know what you expect here...

This is a possibility that can give you the choice between the rgb(r, g, b) output for css elements, and the hex output...

This is a quick example, you have just to adapt this draft but it works as it on Firefox :

<script type="text/javascript">
    //<![CDATA[
        function RndColor(){
        var maximum = 255;
        var minimum = 100;
        var range = maximum - minimum;
        var red = Math.floor(Math.random()*range)+minimum;
        var green = Math.floor(Math.random()*range)+minimum;
        var blue = Math.floor(Math.random()*range)+minimum;
        var redToHex = red.toString(16);
        var greenToHex = green.toString(16);
        var blueToHex = blue.toString(16);
        this.rgbValue = "rgb(" + red + "," + green + "," + blue + ")";
        this.hexValue = "#" + redToHex + "" + greenToHex + "" + blueToHex;
    }
    RndColor.prototype.getRGB = function(){
        return this.rgbValue;
    }
    RndColor.prototype.getHex = function(){
        return this.hexValue;
    }
    //]]>
</script>

Then you can retrieve the value as here bellow :

<script type="text/javascript">
//<![CDATA[
    rndCol = new RndColor();
    document.write("<div style = width:150px;height:100px;background-color:" + rndCol.getHex() + ">" + rndCol.getHex() + "</div><br /><br />");
    document.write("<div style = width:150px;height:100px;background-color:" + rndCol.getRGB() + ">" + rndCol.getRGB() + "</div>");
//]]>
</script>

I hope this can help you. Best regards.

tatactic
  • 1,379
  • 1
  • 9
  • 18
1

Thanks to goran for providing the main ideas of HSL and using the golden angle. I've copied his jsfiddle to include a new idea to squeeze the regions where the colors are similar. I did a linear interpolation between points in an array of angles. Also, I did the same for lightness, to make all seem equally light.

generated 20 colors

function makeColor(colorNum, lightness){
    let hues = [0, 20, 30, 40, 50, 60, 80, 120, 160, 190, 210, 230, 260, 290, 330, 360];
    //hues = [...Array(37).keys()].map(x=>x*10);
    let lights = [60, 50, 50, 50, 50, 50, 50, 55, 50, 55, 67, 77, 73, 67, 60, 60];
    let goldenFrac = 0.5 * (3 - Math.sqrt(5));
    let x = (colorNum * goldenFrac % 1.0) * (hues.length - 1);
    //x=colorNum%(hues.length-1); // for point visualisation
    let i = Math.floor(x);
    let f = x % 1.0;
    let hue = (1.0 - f) * hues[i] + f * hues[i + 1];
    let light = (1.0 - f) * lights[i] + f * lights[i + 1];
    return "hsl( " + Math.round(hue * 100) / 100 + ", 100%, "+Math.round(light * 100) / 100+"% )";
}

// TEST CODE
var totalDIVs = 20;
var totalColors = totalDIVs;
for (var i = 0; i < totalDIVs; i++){
    var element = document.createElement('div');
    document.body.appendChild(element);
    var color = makeColor(i);
    element.style.backgroundColor = color;
    element.innerHTML = color + " = " + element.style.backgroundColor;
}
user1537366
  • 1,100
  • 1
  • 9
  • 15
0

First of all, why are you building hex values from strings? Just use numbers for the values, then output with something like yourNumber.toString(16).

Then, to make the colours more distinct, don't use the full range of 0 to 255 for each colour component, but maybe go in jumps of 10, or 20, or whatever you need to generate wide enough differences.

Cylindric
  • 5,858
  • 5
  • 46
  • 68
0

I wrote up a small script called SwitchColors.js which can be found here: https://github.com/akulmehta/SwitchColors.js

The script produces more saturated colors and the brightness can be controlled. Although it may not produce visually distinguishable colors, it produces high saturation and bright colors which can also be attractive.

Coola
  • 2,934
  • 2
  • 19
  • 43