Generador de color aleatorio

440

Dada esta función, quiero reemplazar el color con un generador de color aleatorio.

document.overlay = GPolyline.fromEncoded({
    color: "#0000FF",
    weight: 10,
    points: encoded_points,
    zoomFactor: 32,
    levels: encoded_levels,
    numLevels: 4
});

¿Cómo puedo hacerlo?

n00ki3
fuente
31
'#' + Math.floor (Math.random () * 16777215) .toString (16);
SepehrM
2
@SepehrM cuando el 0.001resultado es aleatorio , el resultado es "#4189"(color no válido - 4 dígitos)
Kamil Kiełczewski
Esta es una solución muy buena, para mí muy útil github.com/davidmerfield/randomColor
maikelm
55
'#'+Math.random().toString(16).substr(2,6) (fuente: CodeGolf )
ashleedawg

Respuestas:

1018

Uso getRandomColor()en lugar de "#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());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="colorpad" style="width:300px;height:300px;background-color:#000">

</div>
<button onclick="setRandomColor()">Random Color</button>

Anatoliy
fuente
87
Tenga en cuenta que esto tiene un sesgo hacia colores bastante oscuros e insaturados debido a la forma en que RGB envuelve el espacio de color. Martin Ankerl tiene un buen artículo sobre la generación de colores desde otros espacios (como HSV) también: martin.ankerl.com/2009/12/09/…
Thomas Ahle
13
Las posibilidades de acertar 0 o 15 cuando se usa Math.round(Math.random()*15)son solo 1:30, mientras que las posibilidades de los otros números son 1:15.
user123444555621
3
Puede eliminar la llamada .split (''). La cadena ya tiene indexador de matriz.
ujeenator
3
También puede usar una función de generador como tal
tsuz
44
Este código es cojo. Heres un oneliner: Math.floor (Math.random () * 16777215) .toString (16)
DDD
269

Dudo que algo sea más rápido o más corto que este:

"#"+((1<<24)*Math.random()|0).toString(16)

¡Desafío!

ZPiDER
fuente
18
Olvidaste rellenar con ceros.
user123444555621
144
'#'+(Math.random()*0xFFFFFF<<0).toString(16);
Mohsen
15
@Mohsen, FYI de vez en cuando su código produce un número de 5 dígitos inválido
rochal
66
El resultado no se rellena con 6 dígitos
Taha Jahangir
33
('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6)siempre devolverá una longitud de 6. aunque este método todavía (rara vez) devolverá números pequeños que dan resultados como 000cf4o 0000a7que es un poco raro, creo. en estos casos el componente rojo no contribuye al color aleatorio.
bryc
162

Aquí hay otra versión de este problema.

Mi objetivo era crear colores vibrantes y distintos. Para garantizar que los colores sean distintos, evito usar un generador aleatorio y selecciono colores "uniformemente espaciados" del arco iris.

Esto es perfecto para crear marcadores emergentes en Google Maps que tengan una "unicidad" óptima (es decir, no habrá dos marcadores con colores similares).

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);
}

Si desea ver cómo se ve esto en acción, consulte http://blog.adamcole.ca/2011/11/simple-javascript-rainbow-color.html .

Adam Cole
fuente
77
¡He estado buscando algo como esto! ¡Buena cosa!
Khôi
Hice una implementación simplificada de la misma idea que la respuesta a una pregunta similar stackoverflow.com/a/14187677/421010
Andrew
16
Entonces, ¿cuál será el valor del parámetro?
Ekramul Hoque
2
También creé algo como esto, pero es bastante aleatorio y bastante distinto. El pseudocódigo está aquí . Utiliza hsv en lugar de rgb, porque hsv tiene un comportamiento mucho más predecible. Si te interesa ver la implementación de Python, la usé aquí y aquí . Tendrás que buscar en el código "color".
zondo
1
@RobertMolina: Lo siento, mudé mis cosas a Gitlab. El pseudocódigo ahora está aquí , con los proyectos aquí y aquí .
zondo
56

¿Quién puede vencerlo?

'#'+Math.random().toString(16).substr(-6);

Garantizado para trabajar todo el tiempo: http://jsbin.com/OjELIfo/2/edit

Según el comentario de @eterps, el código anterior aún puede generar cadenas más cortas si la representación hexadecimal del color aleatorio es muy corta ( 0.730224609375=> 0.baf)

Este código debería funcionar en todos los casos:

function makeRandomColor(){
  var c = '';
  while (c.length < 7) {
    c += (Math.random()).toString(16).substr(-6).substr(-1)
  }
  return '#'+c;
}
Mohsen
fuente
12
Cuando Math.random () devuelve 0.022092682472568126, este código produce una cadena inválida '# 5a7dd'. ¡loco!
rochal
Como este ya que #ffffff no aparece con demasiada frecuencia.
Warface
Hay bastantes casos en los que esto no funcionará. Compruebe la siguiente salida para Math.random () ... 0.730224609375, 0.43603515625, 0.957763671875, y la lista continúa ...
eterps
@eterps ¡Esos NO son números aleatorios apropiados ! Ver prima doble IEEE 754 en hexadecimal: 0.730224609375 = 0x3fe75e0000000000, 0.43603515625 = 0x3fdbe80000000000, 0.957763671875 = 0x3feea60000000000. ¡Casi nada de la mantisa se está utilizando! Son solo fracciones glorificadas. Un adecuado salida '12 dígitos' produciría resultados como:0.347876714234 = 0x3fd6439cb1ab32ac, 0.447556256665 = 0x3fdca4c2ff5fc450
Bryc
Desde 2015, creo que muchos navegadores web han reemplazado los PRNG basura usados Math.random()(que debo asumir que es responsable de los resultados de @etertp) por otros mejores, por lo que esos tipos de números aleatorios de baja calidad deberían ser cosa del pasado ahora.
bryc
29

No hay necesidad de un hash de letras hexadecimales. JavaScript puede hacer esto por sí mismo:

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();
}
Alsciende
fuente
29

También puede usar HSL disponible en todos los buenos navegadores ( http://caniuse.com/#feat=css3-colors )

function randomHsl() {
    return 'hsla(' + (Math.random() * 360) + ', 100%, 50%, 1)';
}

Esto solo le dará colores brillantes, puede jugar con el brillo, la saturación y el alfa.

// es6
const randomHsl = () => `hsla(${Math.random() * 360}, 100%, 50%, 1)`
kigiri
fuente
¡Gracias! 'hsla(' + (Math.floor(Math.random()*360) + ', 100%, 70%, 1)'
Logré
1
No hay problema, me sorprendió ver a nadie usando el poder de hsl :)
kigiri
stackoverflow.com/a/23861752/1693593 , hsla no es necesario, alpha = 1, solo use hsl
1
No puede generar 16M kolor de esta manera (por ejemplo, nunca obtendrá una escala de grises blanco-negro); sin embargo, sí, si usamos aleatorio para cada componente, obtendremos todos los hsl corols
Kamil Kiełczewski
1
+1 Esto facilita el uso de la luminosidad y la saturación para establecer colores de fondo aleatorios al tiempo que garantiza que el texto sea siempre legible
Osvaldo Maria
27

Me gusta este: '#' + (Math.random().toString(16) + "000000").substring(2,8)

Nicolas Buduroi
fuente
O bien'#' + Math.floor(Math.random()*16777215).toString(16);
Mohammad Anini
@MohammadAnin que tiene una probabilidad de 1 en 16 de producir menos de 6 dígitos
James
1
Esto podría generar colores no válidos. Por ejemplo '#' + (0.125).toString(16).substring(2, 8) === '#2'. Es peligroso porque la probabilidad es baja (creo que 1 de cada 4096), por lo que es probable que un error pase las pruebas. Deberías ('#' + Math.random().toString(16) + "000000").substring(2, 8)
James
Corrección: debería ser'#' + (Math.random().toString(16) + "000000").substring(2,8)
James
25

Generación de color aleatorio con control de brillo:

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(",") + ")";
}
letronje
fuente
1
Muy genial, aunque en su mayoría genera 'pasteles' en lugar de colores más vibrantes que esperaba cuando vi brillo. Todavía en mi bolsa de trucos!
JayCrossler
Realmente me gusta este porque puedes personalizarlo para que esté en armonía con la paleta de colores de tu sitio web
Emanuel Gianico
20
'#'+Math.random().toString(16).slice(-3) // three-numbers format aka #f3c
'#'+Math.random().toString(16).slice(-6) // six-number format aka #abc123
jt3k
fuente
Me gusta esto por su legibilidad
hitautodestruct
1
si se Math.random()devuelve 0.125, el resultado será #0.2(color no válido) (debe agregar algo de relleno en lugar de un corte)
Kamil Kiełczewski
18

El artículo escrito por Paul Irish sobre Random Hex Color Code Generator en JavaScript es absolutamente increíble. Utilizar:

'#'+Math.floor(Math.random()*16777215).toString(16);

Aquí está el enlace de origen:

http://www.paulirish.com/2009/random-hex-color-code-snippets/

way2vin
fuente
55
esto a veces devolverá valores de color no bien formados como "1fa4c" (debe tener 3 o 6 caracteres)
jj_
1
@jj_ es? lo siento, no me di cuenta de eso. Gracias por compartir
way2vin
cuando el 0.00001resultado es aleatorio , el resultado es #a7(color no válido)
Kamil Kiełczewski
1
'#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0')
Haytam
17

Aquí hay un giro en la solución provista por @Anatoliy.

Necesitaba generar solo colores claros (para fondos), así que elegí el formato de tres letras (#AAA):

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;
}
Andrei R
fuente
Creo que es probable que esto produzca con mayor frecuencia colores que son muy similares aunque ligeros. Para una gama más escasa de colores aleatorios, creo que la respuesta de @ Anatoli es mejor en su mayor parte
larrytech
15

Si eres un novato como yo, ni idea de hexadecimales y demás, esto podría ser más intuitivo.

function r() { return Math.floor(Math.random() * 255) }

var color = 'rgb(' + r() + "," + r() + "," + r() + ')';

Solo necesita terminar con una cadena como 'rgb(255, 123, 220)'

ICoffeeConsumer
fuente
esta respuesta debe ser la mejor
Gil Epshtain
Sin embargo, tendrías que usar 256 para obtener 0.
Lisa Cerilli
13

Esto se puede encontrar fácilmente con la Búsqueda de Google:

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;
    }
}

Versión actualizada:

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;
  }
}
Funky Dude
fuente
1
Tal vez sea así; pero, ¿a qué sitio preferiría que fueran los posibles ingresos de Google Adwords? =)
David dice que reinstale a Monica
2
¿Qué sitio le da la respuesta? si te dan la respuesta, deberían recibir los golpes.
Funky Dude
1
@FunkyDude ahora este resultado es el mejor en google y la razón por la que existe stackoverflow es para no usar google con demasiada frecuencia;)
Akshat
10

Respuesta corta con almohadilla al tamaño exacto

'#'+((1<<24)*(Math.random()+1)|0).toString(16).substr(1)

Taha Jahangir
fuente
10
var color = "#";
for (k = 0; k < 3; k++) {
    color += ("0" + (Math.random()*256|0).toString(16)).substr(-2);
}

Un desglose de cómo funciona esto:

Math.random()*256obtiene un número aleatorio (punto flotante) de 0 a 256 (0 a 255 inclusive)
Resultado del ejemplo: 116.15200161933899

Agregar las |0tiras de todo después del punto decimal.
Ej: 116.15200161933899 -> 116

El uso .toString(16)convierte este número a hexadecimal (base 16).
Ej: 116 -> 74
Otro ex: 228 -> e4

Agregar "0"pads con un cero. Esto será importante cuando obtengamos la subcadena, ya que nuestro resultado final debe tener dos caracteres para cada color.
Ej: 74 -> 074
Otro ej .: 8 -> 08

.substr(-2)obtiene solo los dos últimos caracteres.
Ej: 074 -> 74
Otro ej .: 08 -> 08 (si no hubiéramos agregado el "0", esto habría producido "8" en lugar de "08")

El forciclo ejecuta este ciclo tres veces, agregando cada resultado a la cadena de color, produciendo algo como esto:
#7408e4

Erin Heyming
fuente
Deberías dar cuerpo a tu respuesta.
Joce
8

Entonces, aunque todas las respuestas aquí son buenas, quería un poco más de control sobre la salida. Por ejemplo, me gustaría evitar los tonos casi blancos, al tiempo que me aseguro de obtener colores brillantes y vibrantes que no se desvanezcan.

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() +")";
        };

Entonces ahora puedo especificar 3 rangos arbitrarios para elegir valores rgb. Puede llamarlo sin argumentos y obtener mi conjunto predeterminado que generalmente generará un color bastante vibrante con un tono dominante una vez obvio, o puede proporcionar su propia gama de rangos.

Ollie Edwards
fuente
1
La API de Google Map solo admite el color HTML hexadecimal en el formato "#FFFFFF".
Valery Viktorovsky
Claro, es bastante sencillo convertir un número a hexadecimal n.toString (16) solo el inconveniente es que necesitará cero pad para asegurarse de obtener un valor de retorno de dos caracteres de la función g interna.
Ollie Edwards
8

El comentario más votado de la respuesta superior sugiere que el enfoque de Martin Ankerl es mejor que los números hexadecimales aleatorios, y aunque no he mejorado la metodología de Ankerl, lo he traducido con éxito a JavaScript. Pensé que publicaría una respuesta adicional a este hilo SO ya de gran tamaño porque la respuesta principal tiene otro comentario que se vincula a un Gist con la implementación JS de la lógica de Ankerl y ese enlace está roto (404). Si tuviera la reputación, simplemente habría comentado el enlace jsbin que creé.

// 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) : '';
}

// next two methods converted from Ruby to JS
// soured 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 golden ratio
const golden_ratio_conjugate = 0.618033988749895
let h = Math.random() // # use 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

spakmad
fuente
7

Por aleatoriedad decente.

Color aleatorio

`#${crypto.getRandomValues(new Uint32Array(1))[0].toString(16).padStart(8, 0).slice(-6)}`

Alfa aleatorio, color aleatorio.

`#${crypto.getRandomValues(new Uint32Array(1))[0].toString(16).padStart(8, 0)}`
Константин Ван
fuente
7

Hay muchas maneras de lograr esto. Aquí hay algunos que hice:

Genera seis dígitos hexadecimales aleatorios (0-F)

function randColor() {
    for (var i=0, col=''; i<6; i++) {
        col += (Math.random()*16|0).toString(16);
    }
    return '#'+col;
}

Una línea extremadamente corta

'#'+Math.random().toString(16).slice(-6)

Genera componentes HEX individuales (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;
}

Cadena hexadecimal sobrediseñada (XOR 3 salidas juntas para formar 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);
}
bryc
fuente
extremley shor one-liner: cuando el 0.125resultado es aleatorio , el resultado es #0.2(color no válido)
Kamil Kiełczewski
@ KamilKiełczewski 0.125= 3FC0000000000000en hexadecimal IEEE. 3 dígitos hexadecimales son exponentes, 13 son mantisa. Hay una probabilidad de 1 en 4.5 billones de que la mantisa esté completamente vacía de esa manera. Probé 100m veces en Firefox / Chrome. Solo estás tratando de romperlo;). nuncaMath.random debería darte 0,125. Y si lo hace, hay un problema con el PRNG, que no es mi problema. Las fracciones como 0.5, 0.25, 0.0625 etc. son inútiles, no contienen aleatoriedad. Quizás tengas una solución para este caso extremo, ¿eh? ;)
bryc
sí, '#'+Math.random().toString(16).split('.')[1].slice(-6).padStart(6,0)pero prefiero esto
Kamil Kiełczewski
6

Otro generador de color aleatorio:

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
Salman A
fuente
6

Array.prototype.reduce lo hace muy limpio

["r","g","b"].reduce(function(res) {
    return res + ("0"+~~(Math.random()*256).toString(16)).slice(-2)
}, "#")

Necesita una cuña para los navegadores antiguos.

usuario1106925
fuente
en la consola cromada siempre regresa # 000000
Kamil Kiełczewski
6

Podrías usar esta función simple

function getRandomColor(){
 var color =  "#" + (Math.random() * 0xFFFFFF << 0).toString(16);
 return color;
}
ChandrasekarG
fuente
1
cuando 0.001el resultado es aleatorio, el resultado es "#4189"(color no válido 4 dígitos)
Kamil Kiełczewski
5

Usa colores distintos .

Genera una paleta de colores visualmente distintos.

distintos colores es altamente configurable:

  • Elige cuántos colores hay en la paleta
  • Restringe el tono a un rango específico
  • Restringe el croma (saturación) a un rango específico
  • Restringe la ligereza a un rango específico
  • Configurar la calidad general de la paleta
InternalFX
fuente
3541 líneas de code..where otras respuestas aquí son ~ 6-10 líneas ... Estoy impresionado ¿cómo alguien escribió tantas líneas de código sólo para recoger distintos colores ..
VSYNC
Elegir colores realmente distintos visualmente requiere muchas más matemáticas que un simple generador de colores aleatorio.
InternalFX
Lo acabo de hacer en 2 líneas ... modifiqué esta función: stackoverflow.com/a/20129594/104380
vsync
No es tan simple. lectura sugerida
InternalFX
Gracias, artículo muy interesante. mi método siempre proporciona los mismos colores y los resultados son consistentes y distintivos. Supongo que en algunas situaciones es posible que necesites colores realmente aleatorios y bien distribuidos que sean bonitos para el ojo humano.
vsync
3

Aquí están mis dos versiones para un generador de código hexadecimal aleatorio.


/* Slowest but shortest. */
"#000000".replace(/0/g,function(){return (~~(Math.random()*16)).toString(16);});    

/* Good performance with small size. */
"#"+(function(a,b){while(a--){b+=""+(~~(Math.random()*16)).toString(16);} return b;})(6,"");

/* Remy Sharp provided one that's the fastest but a little bit too long */
(function(h){return '#000000'.substr(0,7-h.length)+h})((~~(Math.random()*(1<<24))).toString(16))

Larry Battle
fuente
3

Esta función va más allá de otras respuestas de dos maneras:

Intenta generar colores lo más distintos posible al encontrar qué color de 20 intentos tiene la distancia euclidiana más lejana de los otros en el cono HSV

Le permite restringir el tono, la saturación o el rango de valores, pero aún intenta elegir colores lo más distintos posible dentro de ese rango.

No es súper eficiente, pero para valores razonables (¿quién podría incluso separar 100 colores fácilmente?) Es lo suficientemente rápido.

Ver JSFiddle

  /**
   * 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);
  }
Andy
fuente
3

Casi todos los métodos anteriores de mano corta generan códigos hexadecimales no válidos (cinco dígitos). Encontré una técnica similar solo sin ese problema aquí :

"#"+("000"+(Math.random()*(1<<24)|0).toString(16)).substr(-6)

Prueba

Prueba esto en la consola:

for(i = 0; i < 200; i++) {
    console.log("#" + ("000" + (Math.random()*(1<<24)|0).toString(16)).substr(-6));
}
manikanta
fuente
44
Hice un bucle for que ejecutó este código 20000 veces y solo imprimió en la consola si la longitud era inferior a 7, y encontré un caso donde la cadena tenía menos de 6 caracteres. Además, un problema con este código es que solo rellena la cadena completa de 6 dígitos, no los códigos de color individuales de 2 dígitos, lo que significa que es más probable que tenga ceros en el valor rojo que en los valores verde o azul.
Erin Heyming
cuando 0.00001el resultado es aleatorio, el resultado es "#000a7"(color no válido - 5 dígitos)
Kamil Kiełczewski
3

Mi version:

function RandomColor() {
  var hex = (Math.round(Math.random()*0xffffff)).toString(16);
  while (hex.length < 6) hex = "0" + hex;
  return hex;
}
Prostakov
fuente
Creo que lo no aleatorio 0hace que el color no sea randomsuficiente XD
shrekuu
Randonly generamos un número hexadecinal de 0a ffffff. Que es una distribución uniforme perfecta . Ese cero es solo para completar la cadena, debido a consideraciones de uso del navegador. Le sugiero que tenga más cuidado con esta solución.
Prostakov
Sin embargo, hice algunos ajustes, no vinculados a su comentario :)
Prostakov
Gracias Prostakov : D
shrekuu
3

mapa (devuelve color rgb siempre válido)

`rgb(${[1,2,3].map(x=>Math.random()*256|0)})`

Kamil Kiełczewski
fuente
2

Puede usar colorchain.js para generar una secuencia de colores con distintos tonos.

alexishacks
fuente