123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- // randomColor by David Merfield under the CC0 license
- // https://github.com/davidmerfield/randomColor/
- ;(function(root, factory) {
- // Support CommonJS
- if (typeof exports === 'object') {
- var randomColor = factory();
- // Support NodeJS & Component, which allow module.exports to be a function
- if (typeof module === 'object' && module && module.exports) {
- exports = module.exports = randomColor;
- }
- // Support CommonJS 1.1.1 spec
- exports.randomColor = randomColor;
- // Support AMD
- } else if (typeof define === 'function' && define.amd) {
- define([], factory);
- // Support vanilla script loading
- } else {
- root.randomColor = factory();
- }
- }(this, function() {
- // Seed to get repeatable colors
- var seed = null;
- // Shared color dictionary
- var colorDictionary = {};
- // Populate the color dictionary
- loadColorBounds();
- // check if a range is taken
- var colorRanges = [];
- var randomColor = function (options) {
- options = options || {};
- // Check if there is a seed and ensure it's an
- // integer. Otherwise, reset the seed value.
- if (options.seed !== undefined && options.seed !== null && options.seed === parseInt(options.seed, 10)) {
- seed = options.seed;
- // A string was passed as a seed
- } else if (typeof options.seed === 'string') {
- seed = stringToInteger(options.seed);
- // Something was passed as a seed but it wasn't an integer or string
- } else if (options.seed !== undefined && options.seed !== null) {
- throw new TypeError('The seed value must be an integer or string');
- // No seed, reset the value outside.
- } else {
- seed = null;
- }
- var H,S,B;
- // Check if we need to generate multiple colors
- if (options.count !== null && options.count !== undefined) {
- var totalColors = options.count,
- colors = [];
- // Value false at index i means the range i is not taken yet.
- for (var i = 0; i < options.count; i++) {
- colorRanges.push(false)
- }
- options.count = null;
- while (totalColors > colors.length) {
- var color = randomColor(options);
- if (seed !== null) {
- options.seed = seed;
- }
- colors.push(color);
- }
- options.count = totalColors;
- return colors;
- }
- // First we pick a hue (H)
- H = pickHue(options);
- // Then use H to determine saturation (S)
- S = pickSaturation(H, options);
- // Then use S and H to determine brightness (B).
- B = pickBrightness(H, S, options);
- // Then we return the HSB color in the desired format
- return setFormat([H,S,B], options);
- };
- function pickHue(options) {
- if (colorRanges.length > 0) {
- var hueRange = getRealHueRange(options.hue)
- var hue = randomWithin(hueRange)
- //Each of colorRanges.length ranges has a length equal approximatelly one step
- var step = (hueRange[1] - hueRange[0]) / colorRanges.length
- var j = parseInt((hue - hueRange[0]) / step)
- //Check if the range j is taken
- if (colorRanges[j] === true) {
- j = (j + 2) % colorRanges.length
- }
- else {
- colorRanges[j] = true
- }
- var min = (hueRange[0] + j * step) % 359,
- max = (hueRange[0] + (j + 1) * step) % 359;
- hueRange = [min, max]
- hue = randomWithin(hueRange)
- if (hue < 0) {hue = 360 + hue;}
- return hue
- }
- else {
- var hueRange = getHueRange(options.hue)
- hue = randomWithin(hueRange);
- // Instead of storing red as two seperate ranges,
- // we group them, using negative numbers
- if (hue < 0) {
- hue = 360 + hue;
- }
- return hue;
- }
- }
- function pickSaturation (hue, options) {
- if (options.hue === 'monochrome') {
- return 0;
- }
- if (options.luminosity === 'random') {
- return randomWithin([0,100]);
- }
- var saturationRange = getSaturationRange(hue);
- var sMin = saturationRange[0],
- sMax = saturationRange[1];
- switch (options.luminosity) {
- case 'bright':
- sMin = 55;
- break;
- case 'dark':
- sMin = sMax - 10;
- break;
- case 'light':
- sMax = 55;
- break;
- }
- return randomWithin([sMin, sMax]);
- }
- function pickBrightness (H, S, options) {
- var bMin = getMinimumBrightness(H, S),
- bMax = 100;
- switch (options.luminosity) {
- case 'dark':
- bMax = bMin + 20;
- break;
- case 'light':
- bMin = (bMax + bMin)/2;
- break;
- case 'random':
- bMin = 0;
- bMax = 100;
- break;
- }
- return randomWithin([bMin, bMax]);
- }
- function setFormat (hsv, options) {
- switch (options.format) {
- case 'hsvArray':
- return hsv;
- case 'hslArray':
- return HSVtoHSL(hsv);
- case 'hsl':
- var hsl = HSVtoHSL(hsv);
- return 'hsl('+hsl[0]+', '+hsl[1]+'%, '+hsl[2]+'%)';
- case 'hsla':
- var hslColor = HSVtoHSL(hsv);
- var alpha = options.alpha || Math.random();
- return 'hsla('+hslColor[0]+', '+hslColor[1]+'%, '+hslColor[2]+'%, ' + alpha + ')';
- case 'rgbArray':
- return HSVtoRGB(hsv);
- case 'rgb':
- var rgb = HSVtoRGB(hsv);
- return 'rgb(' + rgb.join(', ') + ')';
- case 'rgba':
- var rgbColor = HSVtoRGB(hsv);
- var alpha = options.alpha || Math.random();
- return 'rgba(' + rgbColor.join(', ') + ', ' + alpha + ')';
- default:
- return HSVtoHex(hsv);
- }
- }
- function getMinimumBrightness(H, S) {
- var lowerBounds = getColorInfo(H).lowerBounds;
- for (var i = 0; i < lowerBounds.length - 1; i++) {
- var s1 = lowerBounds[i][0],
- v1 = lowerBounds[i][1];
- var s2 = lowerBounds[i+1][0],
- v2 = lowerBounds[i+1][1];
- if (S >= s1 && S <= s2) {
- var m = (v2 - v1)/(s2 - s1),
- b = v1 - m*s1;
- return m*S + b;
- }
- }
- return 0;
- }
- function getHueRange (colorInput) {
- if (typeof parseInt(colorInput) === 'number') {
- var number = parseInt(colorInput);
- if (number < 360 && number > 0) {
- return [number, number];
- }
- }
- if (typeof colorInput === 'string') {
- if (colorDictionary[colorInput]) {
- var color = colorDictionary[colorInput];
- if (color.hueRange) {return color.hueRange;}
- } else if (colorInput.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)) {
- var hue = HexToHSB(colorInput)[0];
- return [ hue, hue ];
- }
- }
- return [0,360];
- }
- function getSaturationRange (hue) {
- return getColorInfo(hue).saturationRange;
- }
- function getColorInfo (hue) {
- // Maps red colors to make picking hue easier
- if (hue >= 334 && hue <= 360) {
- hue-= 360;
- }
- for (var colorName in colorDictionary) {
- var color = colorDictionary[colorName];
- if (color.hueRange &&
- hue >= color.hueRange[0] &&
- hue <= color.hueRange[1]) {
- return colorDictionary[colorName];
- }
- } return 'Color not found';
- }
- function randomWithin (range) {
- if (seed === null) {
- //generate random evenly destinct number from : https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
- var golden_ratio = 0.618033988749895
- var r=Math.random()
- r += golden_ratio
- r %= 1
- return Math.floor(range[0] + r*(range[1] + 1 - range[0]));
- } else {
- //Seeded random algorithm from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
- var max = range[1] || 1;
- var min = range[0] || 0;
- seed = (seed * 9301 + 49297) % 233280;
- var rnd = seed / 233280.0;
- return Math.floor(min + rnd * (max - min));
- }
- }
- function HSVtoHex (hsv){
- var rgb = HSVtoRGB(hsv);
- function componentToHex(c) {
- var hex = c.toString(16);
- return hex.length == 1 ? '0' + hex : hex;
- }
- var hex = '#' + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
- return hex;
- }
- function defineColor (name, hueRange, lowerBounds) {
- var sMin = lowerBounds[0][0],
- sMax = lowerBounds[lowerBounds.length - 1][0],
- bMin = lowerBounds[lowerBounds.length - 1][1],
- bMax = lowerBounds[0][1];
- colorDictionary[name] = {
- hueRange: hueRange,
- lowerBounds: lowerBounds,
- saturationRange: [sMin, sMax],
- brightnessRange: [bMin, bMax]
- };
- }
- function loadColorBounds () {
- defineColor(
- 'monochrome',
- null,
- [[0,0],[100,0]]
- );
- defineColor(
- 'red',
- [-26,18],
- [[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]
- );
- defineColor(
- 'orange',
- [18,46],
- [[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]
- );
- defineColor(
- 'yellow',
- [46,62],
- [[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]
- );
- defineColor(
- 'green',
- [62,178],
- [[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]
- );
- defineColor(
- 'blue',
- [178, 257],
- [[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]
- );
- defineColor(
- 'purple',
- [257, 282],
- [[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]
- );
- defineColor(
- 'pink',
- [282, 334],
- [[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]]
- );
- }
- function HSVtoRGB (hsv) {
- // this doesn't work for the values of 0 and 360
- // here's the hacky fix
- var h = hsv[0];
- if (h === 0) {h = 1;}
- if (h === 360) {h = 359;}
- // Rebase the h,s,v values
- h = h/360;
- var s = hsv[1]/100,
- v = hsv[2]/100;
- var h_i = Math.floor(h*6),
- f = h * 6 - h_i,
- p = v * (1 - s),
- q = v * (1 - f*s),
- t = v * (1 - (1 - f)*s),
- r = 256,
- g = 256,
- b = 256;
- switch(h_i) {
- case 0: r = v; g = t; b = p; break;
- case 1: r = q; g = v; b = p; break;
- case 2: r = p; g = v; b = t; break;
- case 3: r = p; g = q; b = v; break;
- case 4: r = t; g = p; b = v; break;
- case 5: r = v; g = p; b = q; break;
- }
- var result = [Math.floor(r*255), Math.floor(g*255), Math.floor(b*255)];
- return result;
- }
- function HexToHSB (hex) {
- hex = hex.replace(/^#/, '');
- hex = hex.length === 3 ? hex.replace(/(.)/g, '$1$1') : hex;
- var red = parseInt(hex.substr(0, 2), 16) / 255,
- green = parseInt(hex.substr(2, 2), 16) / 255,
- blue = parseInt(hex.substr(4, 2), 16) / 255;
- var cMax = Math.max(red, green, blue),
- delta = cMax - Math.min(red, green, blue),
- saturation = cMax ? (delta / cMax) : 0;
- switch (cMax) {
- case red: return [ 60 * (((green - blue) / delta) % 6) || 0, saturation, cMax ];
- case green: return [ 60 * (((blue - red) / delta) + 2) || 0, saturation, cMax ];
- case blue: return [ 60 * (((red - green) / delta) + 4) || 0, saturation, cMax ];
- }
- }
- function HSVtoHSL (hsv) {
- var h = hsv[0],
- s = hsv[1]/100,
- v = hsv[2]/100,
- k = (2-s)*v;
- return [
- h,
- Math.round(s*v / (k<1 ? k : 2-k) * 10000) / 100,
- k/2 * 100
- ];
- }
- function stringToInteger (string) {
- var total = 0
- for (var i = 0; i !== string.length; i++) {
- if (total >= Number.MAX_SAFE_INTEGER) break;
- total += string.charCodeAt(i)
- }
- return total
- }
- // get The range of given hue when options.count!=0
- function getRealHueRange(colorHue)
- { if (!isNaN(colorHue)) {
- var number = parseInt(colorHue);
- if (number < 360 && number > 0) {
- return getColorInfo(colorHue).hueRange
- }
- }
- else if (typeof colorHue === 'string') {
- if (colorDictionary[colorHue]) {
- var color = colorDictionary[colorHue];
- if (color.hueRange) {
- return color.hueRange
- }
- } else if (colorHue.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)) {
- var hue = HexToHSB(colorHue)[0]
- return getColorInfo(hue).hueRange
- }
- }
- return [0,360]
- }
- return randomColor;
- }));
|