Given this function, I want to replace the color with a random color generator.
document.overlay = GPolyline.fromEncoded({
color: "#0000FF",
weight: 10,
points: encoded_points,
zoomFactor: 32,
levels: encoded_levels,
numLevels: 4
});
How can I do it?
Use getRandomColor()
in place of "#0000FF"
:
function getRandomColor() { var letters = '0123456789ABCDEF'; var color = '#'; for (var i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; } function setRandomColor() { $("#colorpad").css("background-color", getRandomColor()); }
I doubt anything will be faster or shorter than this one:
"#" + ((1<<24)*Math.random() | 0).toString(16)
Challenge!
'#'+(Math.random()*0xFFFFFF<<0).toString(16);
('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6)
will always return a length of 6. though this method will still (rarely) return small numbers that give results like 000cf4
or 0000a7
which is a bit hacky i think. in these cases the red component does not contribute to the random color.
Here is another take on this problem.
My goal was to create vibrant and distinct colors. To ensure the colors are distinct I avoid using a random generator and select "evenly spaced" colors from the rainbow.
This is perfect for creating pop-out markers in Google Maps that have optimal "uniqueness" (that is, no two markers will have similar colors).
/**
* @param numOfSteps: Total number steps to get color, means total colors
* @param step: The step number, means the order of the color
*/
function rainbow(numOfSteps, step) {
// This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distinguishable vibrant markers in Google Maps and other apps.
// Adam Cole, 2011-Sept-14
// HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
var r, g, b;
var h = step / numOfSteps;
var i = ~~(h * 6);
var f = h * 6 - i;
var q = 1 - f;
switch(i % 6){
case 0: r = 1; g = f; b = 0; break;
case 1: r = q; g = 1; b = 0; break;
case 2: r = 0; g = 1; b = f; break;
case 3: r = 0; g = q; b = 1; break;
case 4: r = f; g = 0; b = 1; break;
case 5: r = 1; g = 0; b = q; break;
}
var c = "#" + ("00" + (~ ~(r * 255)).toString(16)).slice(-2) + ("00" + (~ ~(g * 255)).toString(16)).slice(-2) + ("00" + (~ ~(b * 255)).toString(16)).slice(-2);
return (c);
}
If you wish to see what this looks like in action see Simple JavaScript Rainbow Color Generator for Google Map Markers.
Who can beat it?
'#' + Math.random().toString(16).substr(-6);
It is guaranteed to work all the time: http://jsbin.com/OjELIfo/2/edit
Based on eterps's comment, the code above can still generate shorter strings if the hexadecimal representation of the random color is very short (0.730224609375
=> 0.baf
).
This code should work in all cases:
function makeRandomColor(){
var c = '';
while (c.length < 7) {
c += (Math.random()).toString(16).substr(-6).substr(-1)
}
return '#' + c;
}
0.125
the result is "#0.2"
(invalid)
0
is a valid return value of Math.random
and '#' + (0).toString(16).substr(-6)
is "#0"
. If you don't mind I'd strike-though the it is guaranteed to work all the time to avoid confusing others?
You can also use HSL available on every good browser (http://caniuse.com/#feat=css3-colors)
function randomHsl() {
return 'hsla(' + (Math.random() * 360) + ', 100%, 50%, 1)';
}
This will give you only bright colors, you can play around with the brightness, saturation and alpha.
// es6
const randomHsl = () => `hsla(${Math.random() * 360}, 100%, 50%, 1)`
'hsla(' + (Math.floor(Math.random()*360) + ', 100%, 70%, 1)'
There is no need for a hash of hexadecimal letters. JavaScript can do this by itself:
function get_random_color() {
function c() {
var hex = Math.floor(Math.random()*256).toString(16);
return ("0"+String(hex)).substr(-2); // pad with zero
}
return "#"+c()+c()+c();
}
I like this one: '#' + (Math.random().toString(16) + "000000").substring(2,8)
'#' + Math.floor(Math.random()*16777215).toString(16);
'#' + (0.125).toString(16).substring(2, 8) === '#2'
. It is dangerous because the probability is low (1 in 4096 I think) so a bug is likely to get through testing. You should ('#' + Math.random().toString(16) + "000000").substring(2, 8)
'#' + (Math.random().toString(16) + "000000").substring(2,8)
Random color generation with brightness control:
function getRandColor(brightness){
// Six levels of brightness from 0 to 5, 0 being the darkest
var rgb = [Math.random() * 256, Math.random() * 256, Math.random() * 256];
var mix = [brightness*51, brightness*51, brightness*51]; //51 => 255/5
var mixedrgb = [rgb[0] + mix[0], rgb[1] + mix[1], rgb[2] + mix[2]].map(function(x){ return Math.round(x/2.0)})
return "rgb(" + mixedrgb.join(",") + ")";
}
The article written by Paul Irish, Random Hex Color Code Generator in JavaScript, is absolutely amazing. Use:
'#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0');
Thanks to Haytam for sharing the padStart
to solve the hexadecimal code length issue.
0.00001
then result is #a7
(invalid color)
'#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0')
If you're a noob like me, clueless about hexadecimals and such, this might be more intuitive.
function r() { return Math.floor(Math.random() * 255) }
var color = 'rgb(' + r() + "," + r() + "," + r() + ')';
You just need to end up with a string such as 'rgb(255, 123, 220)'
'#'+Math.random().toString(16).slice(-3) // three-numbers format aka #f3c
'#'+Math.random().toString(16).slice(-6) // six-number format aka #abc123
Math.random()
return 0.125
then result will be #0.2
(invalid color) (you need to add some padding instead slice)
Here's a twist on the solution provided by @Anatoliy.
I needed to generate only light colours (for backgrounds), so I went with three letter (#AAA) format:
function get_random_color() {
var letters = 'ABCDE'.split('');
var color = '#';
for (var i=0; i<3; i++ ) {
color += letters[Math.floor(Math.random() * letters.length)];
}
return color;
}
Use:
function random_color(format)
{
var rint = Math.round(0xffffff * Math.random());
switch(format)
{
case 'hex':
return ('#0' + rint.toString(16)).replace(/^#0([0-9a-f]{6})$/i, '#$1');
break;
case 'rgb':
return 'rgb(' + (rint >> 16) + ',' + (rint >> 8 & 255) + ',' + (rint & 255) + ')';
break;
default:
return rint;
break;
}
}
Updated version:
function random_color( format ){
var rint = Math.floor( 0x100000000 * Math.random());
switch( format ){
case 'hex':
return '#' + ('00000' + rint.toString(16)).slice(-6).toUpperCase();
case 'hexa':
return '#' + ('0000000' + rint.toString(16)).slice(-8).toUpperCase();
case 'rgb':
return 'rgb(' + (rint & 255) + ',' + (rint >> 8 & 255) + ',' + (rint >> 16 & 255) + ')';
case 'rgba':
return 'rgba(' + (rint & 255) + ',' + (rint >> 8 & 255) + ',' + (rint >> 16 & 255) + ',' + (rint >> 24 & 255)/255 + ')';
default:
return rint;
}
}
There are so many ways you can accomplish this. Here's some I did:
Short one-liner, guaranteed valid colors
'#'+(Math.random().toString(16)+'00000').slice(2,8)
Generates six random hex digits (0-F)
function randColor() {
for (var i=0, col=''; i<6; i++) {
col += (Math.random()*16|0).toString(16);
}
return '#'+col;
}
// ES6 one-liner version
[..."000000"].map(()=>Math.random().toString(16)[2]).join("")
Generates individual HEX components (00-FF)
function randColor2() {
var r = ('0'+(Math.random()*256|0).toString(16)).slice(-2),
g = ('0'+(Math.random()*256|0).toString(16)).slice(-2),
b = ('0'+(Math.random()*256|0).toString(16)).slice(-2);
return '#' +r+g+b;
}
Over-engineered hex string (XORs 3 outputs together to form color)
function randColor3() {
var str = Math.random().toString(16) + Math.random().toString(16),
sg = str.replace(/0./g,'').match(/.{1,6}/g),
col = parseInt(sg[0], 16) ^
parseInt(sg[1], 16) ^
parseInt(sg[2], 16);
return '#' + ("000000" + col.toString(16)).slice(-6);
}
0.125
then result is #0.2
(invalid color)
0.125
= 3FC0000000000000
in IEEE hex. 3 hex digits are exponent, 13 are mantissa. There's a 1 in 4.5 quadrillion chance that mantissa is completely empty like that. I tested 100m times in both Firefox/Chrome. You are just trying to break it ;). Math.random
should never give you 0.125. And if it does, there is a problem with the PRNG, which is not my problem. Fractions like 0.5, 0.25, 0.0625 etc. are useless, they contain no randomness. Perhaps you have a solution to this extreme edge case, hm? ;)
'#'+Math.random().toString(16).split('.')[1].slice(-6).padStart(6,0)
but I prefer this
Math.random()
never gives such numbers (which in hex representation have less digits than 6 after dot) ? Can you explain what do you mean that 0.5 is less random that any other number? You say It is not your problem - yes, you are right - the problem have programmes which use your code unless you can provide proof (however in that case this will mean that there is something wrong with Math.random() because it exclude some 'special' numbers...)
map
always returns a valid RGB color:
`rgb(${[1,2,3].map(x=>Math.random()*256|0)})`
let c= `rgb(${[1,2,3].map(x=>Math.random()*256|0)})` console.log(c); document.body.style.background=c
The top voted comment of the top answer suggests that Martin Ankerl's approach is better than random hex numbers, and although I haven't improved on Ankerl's methodology, I have successfully translated it to JavaScript.
I figured I'd post an additional answer to this already mega-sized Stack Overflow question because the top answer has another comment linking to a Gist with the JavaScript implementation of Ankerl's logic and that link is broken (404). If I had the reputation, I would have simply commented the jsbin link I created.
// Adapted from
// http://jsfiddle.net/Mottie/xcqpF/1/light/
const rgb2hex = (rgb) => {
return (rgb && rgb.length === 3) ? "#" +
("0" + parseInt(rgb[0],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) : '';
}
// The next two methods are converted from Ruby to JavaScript.
// It is sourced from http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
// # HSV values in [0..1[
// # returns [r, g, b] values from 0 to 255
const hsv_to_rgb = (h, s, v) => {
const h_i = Math.floor(h*6)
const f = h*6 - h_i
const p = v * (1 - s)
const q = v * (1 - (f * s))
const t = v * (1 - (1 - f) * s)
let r, g, b
switch(h_i) {
case(0):
[r, g, b] = [v, t, p]
break
case(1):
[r, g, b] = [q, v, p]
break
case(2):
[r, g, b] = [p, v, t]
break
case(3):
[r, g, b] = [p, q, v]
break
case(4):
[r, g, b] = [t, p, v]
break
case(5):
[r, g, b] = [v, p, q]
break
}
return [Math.floor(r * 256), Math.floor(g * 256), Math.floor(b * 256)]
}
// # Use the golden ratio
const golden_ratio_conjugate = 0.618033988749895
let h = Math.random() // # Use a random start value
const gen_hex = (numberOfColors) => {
const colorArray = []
while (numberOfColors > 0) {
h += golden_ratio_conjugate
h %= 1
colorArray.push(rgb2hex(hsv_to_rgb(h, 0.99, 0.99)))
numberOfColors -= 1
}
console.log(colorArray)
return colorArray
}
gen_hex(100)
https://jsbin.com/qeyevoj/edit?js,console
regexp
always returns a valid hex 6-digit color
"#xxxxxx".replace(/x/g, y=>(Math.random()*16|0).toString(16))
let c= "#xxxxxx".replace(/x/g, y=>(Math.random()*16|0).toString(16)); console.log(c); document.body.style.background=c
var color = "#";
for (k = 0; k < 3; k++) {
color += ("0" + (Math.random()*256|0).toString(16)).substr(-2);
}
A breakdown of how this works:
Math.random()*256
gets a random (floating point) number from 0 to 256 (0 to 255 inclusive)
Example result: 116.15200161933899
Adding the |0
strips off everything after the decimal point.
Ex: 116.15200161933899 -> 116
Using .toString(16)
converts this number to hexadecimal (base 16).
Ex: 116 -> 74
Another ex: 228 -> e4
Adding "0"
pads it with a zero. This will be important when we get the substring, since our final result must have two characters for each color.
Ex: 74 -> 074
Another ex: 8 -> 08
.substr(-2)
gets just the last two characters.
Ex: 074 -> 74
Another ex: 08 -> 08 (if we hadn't added the "0"
, this would have produced "8" instead of "08")
The for
loop runs this loop three times, adding each result to the color string, producing something like this:
#7408e4
A short answer with padding to the exact size:
'#' + ((1<<24)*(Math.random()+1)|0).toString(16).substr(1)
So whilst all the answers here are good I wanted a bit more control over the output. For instance I'd like to prevent any near white shades, whilst ensuring I get bright vibrant colours not washed out shades.
function generateColor(ranges) {
if (!ranges) {
ranges = [
[150,256],
[0, 190],
[0, 30]
];
}
var g = function() {
//select random range and remove
var range = ranges.splice(Math.floor(Math.random()*ranges.length), 1)[0];
//pick a random number from within the range
return Math.floor(Math.random() * (range[1] - range[0])) + range[0];
}
return "rgb(" + g() + "," + g() + "," + g() +")";
};
So now I can specify 3 arbitrary ranges to pick rgb values from. You can call it with no arguments and get my default set which will usually generate a quite vibrant colour with once obvious dominant shade, or you can supply your own array of ranges.
You could use this simple function
function getRandomColor(){
var color = "#" + (Math.random() * 0xFFFFFF << 0).toString(16);
return color;
}
0.001
the result is "#4189"
(invalid color 4 digits)
For decent randomness.
Random color
`#${crypto.getRandomValues(new Uint32Array(1))[0].toString(16).padStart(8, 0).slice(-6)}`
Random alpha, random color.
`#${crypto.getRandomValues(new Uint32Array(1))[0].toString(16).padStart(8, 0)}`
Yet another random color generator:
var randomColor;
randomColor = Math.random() * 0x1000000; // 0 < randomColor < 0x1000000 (randomColor is a float)
randomColor = Math.floor(randomColor); // 0 < randomColor <= 0xFFFFFF (randomColor is an integer)
randomColor = randomColor.toString(16); // hex representation randomColor
randomColor = ("000000" + randomColor).slice(-6); // leading zeros added
randomColor = "#" + randomColor; // # added
Use distinct-colors.
It generates a palette of visually distinct colors.
distinct-colors is highly configurable:
Choose how many colors are in the palette
Restrict the hue to a specific range
Restrict the chroma (saturation) to a specific range
Restrict the lightness to a specific range
Configure general quality of the palette
Array.prototype.reduce
makes it very clean.
["r", "g", "b"].reduce(function(res) {
return res + ("0" + ~~(Math.random()*256).toString(16)).slice(-2)
}, "#")
It needs a shim for old browsers.
function get_random_color() {
return "#" + (Math.round(Math.random() * 0XFFFFFF)).toString(16);
}
I wanted to create very distinctive and vibrant colors (for graphing). For anything serious, hsl is a better method than rgb. If necessary, you can convert hsl to rgb as already mentioned by others.
Simple way:
Create a random Hue from 0 to 360
Create a random Saturation from 0.5 to 1 (or 50 to 100) for vividness
Fix Lightness to 50% for best visibility.
color_generator = () => hsl (360*Math.random(), 0.5 + Math.random()/2, 0.5)
modified way
It creates a very nice spectrum of bright and vivid colors but the problem is that in usual color spectrum red, green, blue shades are way more dominant than yellow, cyan, and purple. So, I transformed the hue through acos function. The technical reason is very boring, so I skip it but you can dig in wiki.
color_generator = () => {
let color_section = Math.floor(Math.random()/0.33) // there are three section in full spectrum
let transformed_hue = Math.acos(2*Math.random() - 1)/3.14 // transform so secondary colors would be as dominant as the primary colors
let hue = 120*color_section + 120*transformed_hue
return hsl(hue, 0.5 + Math.random()/2, 0.5)
}
The result is the best color spectrum I had after experimenting with many other methods.
References:
https://observablehq.com/@d3/color-schemes
https://en.wikipedia.org/wiki/HSL_and_HSV
This function goes above and beyond other answers in two ways:
It attempts to generate colors as distinct as possible by finding which color out of 20 tries has the farthest Euclidean distance from the others in the HSV cone.
It allows you to restrict the hue, saturation, or value range, but it still attempts to pick colors as distinct as possible within that range.
It's not super efficient, but for reasonable values (who could even pick apart 100 colors easily?) It's fast enough.
/**
* Generates a random palette of HSV colors. Attempts to pick colors
* that are as distinct as possible within the desired HSV range.
*
* @param {number} [options.numColors=10] - the number of colors to generate
* @param {number[]} [options.hRange=[0,1]] - the maximum range for generated hue
* @param {number[]} [options.sRange=[0,1]] - the maximum range for generated saturation
* @param {number[]} [options.vRange=[0,1]] - the maximum range for generated value
* @param {number[][]}[options.exclude=[[0,0,0],[0,0,1]]] - colors to exclude
*
* @returns {number[][]} an array of HSV colors (each HSV color
* is a [hue, saturation, value] array)
*/
function randomHSVPalette(options) {
function random(min, max) {
return min + Math.random() * (max - min);
}
function HSVtoXYZ(hsv) {
var h = hsv[0];
var s = hsv[1];
var v = hsv[2];
var angle = h * Math.PI * 2;
return [Math.sin(angle) * s * v,
Math.cos(angle) * s * v,
v];
}
function distSq(a, b) {
var dx = a[0] - b[0];
var dy = a[1] - b[1];
var dz = a[2] - b[2];
return dx * dx + dy * dy + dz * dz;
}
if (!options) {
options = {};
}
var numColors = options.numColors || 10;
var hRange = options.hRange || [0, 1];
var sRange = options.sRange || [0, 1];
var vRange = options.vRange || [0, 1];
var exclude = options.exclude || [[0, 0, 0], [0, 0, 1]];
var points = exclude.map(HSVtoXYZ);
var result = [];
while (result.length < numColors) {
var bestHSV;
var bestXYZ;
var bestDist = 0;
for (var i = 0; i < 20; i++) {
var hsv = [random(hRange[0], hRange[1]), random(sRange[0], sRange[1]), random(vRange[0], vRange[1])];
var xyz = HSVtoXYZ(hsv);
var minDist = 10;
points.forEach(function(point) {
minDist = Math.min(minDist, distSq(xyz, point));
});
if (minDist > bestDist) {
bestHSV = hsv;
bestXYZ = xyz;
bestDist = minDist;
}
}
points.push(bestXYZ);
result.push(bestHSV);
}
return result;
}
function HSVtoRGB(hsv) {
var h = hsv[0];
var s = hsv[1];
var v = hsv[2];
var i = ~~(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
v = ~~(255 * v);
p = ~~(255 * p);
q = ~~(255 * q);
t = ~~(255 * t);
switch (i % 6) {
case 0: return [v, t, p];
case 1: return [q, v, p];
case 2: return [p, v, t];
case 3: return [p, q, v];
case 4: return [t, p, v];
case 5: return [v, p, q];
}
}
function RGBtoCSS(rgb) {
var r = rgb[0];
var g = rgb[1];
var b = rgb[2];
var rgb = (r << 16) + (g << 8) + b;
return '#' + ('000000' + rgb.toString(16)).slice(-6);
}
My version:
function RandomColor() {
var hex = (Math.round(Math.random()*0xffffff)).toString(16);
while (hex.length < 6) hex = "0" + hex;
return hex;
}
0
makes the color not random
enough XD
0
to ffffff
. Which is a perfect uniform distribution. That zero is only to complete string, because of browser usage considerations. I suggest you look more careful at this solution.
A bit enhanced one-liner to make the approach more vivid
'#' + Math.round((0x1000000 + 0xffffff * Math.random())).toString(16).slice(1)
Success story sharing
Math.round(Math.random()*15)
are only 1:30, while the other numbers' chances are 1:15.