diff --git a/randomColor.js b/randomColor.js index dd1fe26..479b5de 100644 --- a/randomColor.js +++ b/randomColor.js @@ -13,43 +13,47 @@ loadColorBounds(); // check if a range is taken var colorRanges = []; -export default function randomColor (options) { +var colorIndex = 0; +export default function randomColor(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)) { + 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') { + // 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 + // 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'); + throw new TypeError("The seed value must be an integer or string"); - // No seed, reset the value outside. + // No seed, reset the value outside. } else { seed = null; } - var H,S,B; + var H, S, B; // Check if we need to generate multiple colors if (options.count !== null && options.count !== undefined) { - var totalColors = options.count, - colors = []; + 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) - } + colorRanges.push(false); + } options.count = null; + options.totalColors = totalColors; while (totalColors > colors.length) { - var color = randomColor(options); if (seed !== null) { @@ -74,40 +78,55 @@ export default function randomColor (options) { B = pickBrightness(H, S, options); // Then we return the HSB color in the desired format - return setFormat([H,S,B], options); -}; + return setFormat([H, S, B], options); +} function pickHue(options) { if (colorRanges.length > 0) { - var hueRange = getRealHueRange(options.hue) + var hueRange = getRealHueRange(options.hue); - var hue = randomWithin(hueRange) + if (typeof options.hue === "object") { + if (options.hueRange === undefined) { + options.hueRange = hueRange; + } else { + hueRange = options.hueRange; + } + var hue = + hueRange[0] + + colorIndex * ((hueRange[1] - hueRange[0]) / options.totalColors); + colorIndex += 1; + } else { + 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 step = (hueRange[1] - hueRange[0]) / colorRanges.length; - var j = parseInt((hue - hueRange[0]) / step) + var j = parseInt((hue - hueRange[0]) / step); //Check if the range j is taken if (colorRanges[j] === true) { - j = (j + 2) % colorRanges.length + j = (j + 2) % colorRanges.length; + } else { + colorRanges[j] = true; } - else { - colorRanges[j] = true - } var min = (hueRange[0] + j * step) % 359, - max = (hueRange[0] + (j + 1) * step) % 359; + max = (hueRange[0] + (j + 1) * step) % 359; - hueRange = [min, max] + hueRange = [min, max]; - hue = randomWithin(hueRange) + hue = randomWithin(hueRange); - if (hue < 0) {hue = 360 + hue;} - return hue - } - else { - var hueRange = getHueRange(options.hue) + if (hue < 0) { + hue = 360 + hue; + } + if (hue > 360) { + hue = hue - 360; + } + return hue; + } else { + var hueRange = getHueRange(options.hue); hue = randomWithin(hueRange); // Instead of storing red as two seperate ranges, @@ -120,56 +139,96 @@ function pickHue(options) { } } -function pickSaturation (hue, options) { +function pickSaturation(hue, options) { + if (typeof options.luminosity === "object") { + // console.log(options.lRange); + if (options.sRange === undefined) { + cOptions = { ...options }; + cOptions.luminosity = options.luminosity[0]; + s1 = pickSaturation(hue, cOptions); + cOptions.luminosity = options.luminosity[1]; + s2 = pickSaturation(hue, cOptions); + options.sRange = [s1, s2]; + // console.log(options.lRange); + } + var sRange = options.sRange; + + // console.log(lRange); + let s = + sRange[0] + colorIndex * ((sRange[1] - sRange[0]) / options.totalColors); + if (typeof options.hue !== "object") { + colorIndex += 1; + } + return s; + } + + if (typeof options.hue === "object") { + if (options.S === undefined) { + cOptions = { ...options }; + cOptions.hue = ""; + options.S = pickSaturation(hue, cOptions); + } + return options.S; + } - if (options.hue === 'monochrome') { + if (options.hue === "monochrome") { return 0; } - if (options.luminosity === 'random') { - return randomWithin([0,100]); + if (options.luminosity === "random") { + return randomWithin([0, 100]); } var saturationRange = getSaturationRange(hue); var sMin = saturationRange[0], - sMax = saturationRange[1]; + sMax = saturationRange[1]; switch (options.luminosity) { - - case 'bright': + case "bright": sMin = 55; break; - case 'dark': + case "dark": sMin = sMax - 10; break; - case 'light': + case "light": sMax = 55; break; - } + } return randomWithin([sMin, sMax]); - } -function pickBrightness (H, S, options) { +function pickBrightness(H, S, options) { + if ( + typeof options.hue === "object" || + typeof options.luminosity === "object" + ) { + console.log(options.B); + if (options.B === undefined) { + cOptions = { ...options }; + cOptions.hue = ""; + cOptions.luminosity = "light"; + options.B = pickBrightness(H, S, cOptions); + } + return options.B; + } var bMin = getMinimumBrightness(H, S), - bMax = 100; + bMax = 100; switch (options.luminosity) { - - case 'dark': + case "dark": bMax = bMin + 20; break; - case 'light': - bMin = (bMax + bMin)/2; + case "light": + bMin = (bMax + bMin) / 2; break; - case 'random': + case "random": bMin = 0; bMax = 100; break; @@ -178,124 +237,126 @@ function pickBrightness (H, S, options) { return randomWithin([bMin, bMax]); } -function setFormat (hsv, options) { - +function setFormat(hsv, options) { switch (options.format) { - - case 'hsvArray': + case "hsvArray": return hsv; - case 'hslArray': + case "hslArray": return HSVtoHSL(hsv); - case 'hsl': + case "hsl": var hsl = HSVtoHSL(hsv); - return 'hsl('+hsl[0]+', '+hsl[1]+'%, '+hsl[2]+'%)'; + return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)"; - case 'hsla': + case "hsla": var hslColor = HSVtoHSL(hsv); var alpha = options.alpha || Math.random(); - return 'hsla('+hslColor[0]+', '+hslColor[1]+'%, '+hslColor[2]+'%, ' + alpha + ')'; - - case 'rgbArray': + return ( + "hsla(" + + hslColor[0] + + ", " + + hslColor[1] + + "%, " + + hslColor[2] + + "%, " + + alpha + + ")" + ); + + case "rgbArray": return HSVtoRGB(hsv); - case 'rgb': + case "rgb": var rgb = HSVtoRGB(hsv); - return 'rgb(' + rgb.join(', ') + ')'; + return "rgb(" + rgb.join(", ") + ")"; - case 'rgba': + case "rgba": var rgbColor = HSVtoRGB(hsv); var alpha = options.alpha || Math.random(); - return 'rgba(' + rgbColor.join(', ') + ', ' + alpha + ')'; + 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]; + v1 = lowerBounds[i][1]; - var s2 = lowerBounds[i+1][0], - v2 = lowerBounds[i+1][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; - var m = (v2 - v1)/(s2 - s1), - b = v1 - m*s1; - - return m*S + b; + return m * S + b; } - } return 0; } -function getHueRange (colorInput) { - - if (typeof parseInt(colorInput) === 'number') { - +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 (typeof colorInput === "string") { if (colorDictionary[colorInput]) { var color = colorDictionary[colorInput]; - if (color.hueRange) {return color.hueRange;} + 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 [hue, hue]; } } - return [0,360]; - + return [0, 360]; } -function getSaturationRange (hue) { +function getSaturationRange(hue) { return getColorInfo(hue).saturationRange; } -function getColorInfo (hue) { - +function getColorInfo(hue) { // Maps red colors to make picking hue easier if (hue >= 334 && hue <= 360) { - 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'; + 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) { +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])); + 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; @@ -303,31 +364,31 @@ function randomWithin (range) { seed = (seed * 9301 + 49297) % 233280; var rnd = seed / 233280.0; return Math.floor(min + rnd * (max - min)); -} + } } -function HSVtoHex (hsv){ - +function HSVtoHex(hsv) { var rgb = HSVtoRGB(hsv); function componentToHex(c) { - var hex = c.toString(16); - return hex.length == 1 ? '0' + hex : hex; + var hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; } - var hex = '#' + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]); + var hex = + "#" + + componentToHex(rgb[0]) + + componentToHex(rgb[1]) + + componentToHex(rgb[2]); return hex; - } -function defineColor (name, hueRange, lowerBounds) { - +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]; + sMax = lowerBounds[lowerBounds.length - 1][0], + bMin = lowerBounds[lowerBounds.length - 1][1], + bMax = lowerBounds[0][1]; colorDictionary[name] = { hueRange: hueRange, @@ -335,156 +396,251 @@ function defineColor (name, hueRange, lowerBounds) { saturationRange: [sMin, sMax], brightnessRange: [bMin, bMax] }; - } -function loadColorBounds () { +function loadColorBounds() { + defineColor("monochrome", null, [ + [0, 0], + [100, 0] + ]); defineColor( - 'monochrome', - null, - [[0,0],[100,0]] + "red", + [-26, 18], + [ + [20, 100], + [30, 92], + [40, 89], + [50, 85], + [60, 78], + [70, 70], + [80, 60], + [90, 55], + [100, 50] + ] ); defineColor( - 'red', - [-26,18], - [[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]] + "orange", + [18, 46], + [ + [20, 100], + [30, 93], + [40, 88], + [50, 86], + [60, 85], + [70, 70], + [100, 70] + ] ); defineColor( - 'orange', - [18,46], - [[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]] + "yellow", + [46, 62], + [ + [25, 100], + [40, 94], + [50, 89], + [60, 86], + [70, 84], + [80, 82], + [90, 80], + [100, 75] + ] ); defineColor( - 'yellow', - [46,62], - [[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]] + "green", + [62, 178], + [ + [30, 100], + [40, 90], + [50, 85], + [60, 81], + [70, 74], + [80, 64], + [90, 50], + [100, 40] + ] ); defineColor( - 'green', - [62,178], - [[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]] - ); - - defineColor( - 'blue', + "blue", [178, 257], - [[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]] + [ + [20, 100], + [30, 86], + [40, 80], + [50, 74], + [60, 60], + [70, 52], + [80, 44], + [90, 39], + [100, 35] + ] ); defineColor( - 'purple', + "purple", [257, 282], - [[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]] + [ + [20, 100], + [30, 87], + [40, 79], + [50, 70], + [60, 65], + [70, 59], + [80, 52], + [90, 45], + [100, 42] + ] ); defineColor( - 'pink', + "pink", [282, 334], - [[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]] + [ + [20, 100], + [30, 90], + [40, 86], + [60, 84], + [80, 80], + [90, 75], + [100, 73] + ] ); - } -function HSVtoRGB (hsv) { - +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;} + 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; + h = h / 360; + var s = hsv[1] / 100, + v = hsv[2] / 100; - var h_i = Math.floor(h*6), + 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), + 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; + 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)]; + 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; +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; + 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; + 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 ]; + 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) { +function HSVtoHSL(hsv) { var h = hsv[0], - s = hsv[1]/100, - v = hsv[2]/100, - k = (2-s)*v; + 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 + Math.round(((s * v) / (k < 1 ? k : 2 - k)) * 10000) / 100, + (k / 2) * 100 ]; } -function stringToInteger (string) { - var total = 0 +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) + total += string.charCodeAt(i); } - return total + return total; } // get The range of given hue when options.count!=0 function getRealHueRange(colorHue) { - if (!isNaN(colorHue)) { + if (typeof colorHue === "object") { + let hue1 = getRealHueRange(colorHue[0]); + let hue2 = getRealHueRange(colorHue[1]); + let h1 = (hue1[0] + hue1[1]) / 2; + let h2 = (hue2[0] + hue2[1]) / 2; + return [h1, h2]; + } else if (!isNaN(colorHue)) { var number = parseInt(colorHue); if (number < 360 && number > 0) { - return getColorInfo(colorHue).hueRange + return getColorInfo(colorHue).hueRange; } - } else if (typeof colorHue === 'string') { - + } else if (typeof colorHue === "string") { if (colorDictionary[colorHue]) { var color = colorDictionary[colorHue]; if (color.hueRange) { - return 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 + var hue = HexToHSB(colorHue)[0]; + return getColorInfo(hue).hueRange; } } }