Generatore di colori casuale


441

Data questa funzione, voglio sostituire il colore con un generatore di colori casuale.

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

Come posso farlo?


31
'#' + Math.floor (Math.random () * 16777215) .ToString (16);
SepehrM


2
@SepehrM quando i ritorni casuali 0.001allora il risultato è "#4189"(colore non valido - 4 cifre)
Kamil Kiełczewski

Questa è una soluzione molto bella, per me molto utile github.com/davidmerfield/randomColor
maikelm

5
'#'+Math.random().toString(16).substr(2,6) (fonte: CodeGolf )
ashleedawg

Risposte:


1019

Utilizzare getRandomColor()al posto di "#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>


87
Si noti che ciò ha una propensione verso colori piuttosto scuri e insaturi a causa del modo in cui RGB avvolge lo spazio colore. Martin Ankerl ha pubblicato un bell'articolo sulla generazione di colori da altri spazi (come HSV): martin.ankerl.com/2009/12/09/…
Thomas Ahle

13
Le probabilità di colpire 0 o 15 durante l'utilizzo Math.round(Math.random()*15)sono solo 1:30, mentre le probabilità degli altri numeri sono 1:15.
user123444555621

3
Puoi rimuovere la chiamata .split (''). La stringa ha già l'indicizzatore di array.
ujeenator,

3
Puoi anche usare una Funzione generatore come tale
tsuz,

5
Questo codice è zoppo. Heres an oneliner: Math.floor (Math.random () * 16777215) .toString (16)
DDD

269

Dubito che qualcosa sarà più veloce o più breve di questo:

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

Sfida!


18
Hai dimenticato di riempire con zero.
user123444555621

144
'#'+(Math.random()*0xFFFFFF<<0).toString(16);
Mohsen,

15
@Mohsen, FYI ogni tanto il tuo codice produce un numero di 5 cifre non valido
rochal

6
Il risultato non è arrotondato a 6 cifre
Taha Jahangir

33
('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6)restituirà sempre una lunghezza di 6. sebbene questo metodo restituirà (raramente) piccoli numeri che danno risultati simili 000cf4o 0000a7che è un po 'confuso, credo. in questi casi il componente rosso non contribuisce al colore casuale.
bryc,

162

Ecco un'altra opinione su questo problema.

Il mio obiettivo era quello di creare colori vivaci e distinti. Per garantire che i colori siano distinti, evito di usare un generatore casuale e seleziono i colori "equidistanti" dall'arcobaleno.

Questo è perfetto per la creazione di marcatori a comparsa in Google Maps con "unicità" ottimale (ovvero, nessun marcatore avrà colori simili).

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

Se desideri vedere come appare in azione, vedi http://blog.adamcole.ca/2011/11/simple-javascript-rainbow-color.html .


7
Ho cercato qualcosa di simile! Roba fantastica!
Khôi,

Ho realizzato un'implementazione semplificata della stessa idea della risposta a una domanda simile stackoverflow.com/a/14187677/421010
Andrew

16
Quindi quale sarà il valore del parametro?
Ekramul Hoque,

2
Ho anche creato qualcosa del genere, ma è abbastanza casuale e abbastanza distinto. Lo pseudo-codice è qui . Utilizza hsv anziché rgb, perché hsv ha un comportamento molto più prevedibile. Se ti interessa vedere l'implementazione di Python, l'ho usata qui e qui . Dovrai cercare "color" nel codice.
zondo,

1
@RobertMolina: Mi spiace, ho spostato le mie cose su Gitlab. Lo pseudo-codice è ora qui , con i progetti qui e qui .
zondo,

56

Chi può batterlo?

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

Garantito per funzionare sempre: http://jsbin.com/OjELIfo/2/edit

Sulla base del commento di @eterps, il codice sopra può ancora generare stringhe più brevi se la rappresentazione esadecimale del colore casuale è molto breve ( 0.730224609375=> 0.baf)

Questo codice dovrebbe funzionare in tutti i casi:

function makeRandomColor(){
  var c = '';
  while (c.length < 7) {
    c += (Math.random()).toString(16).substr(-6).substr(-1)
  }
  return '#'+c;
}

12
Quando Math.random () restituisce 0,022092682472568126 questo codice produce una stringa '# 5a7dd' non valida. pazzesco!
rochal

Come questo dal momento che #ffffff non appare troppo spesso.
Warface,

Ci sono alcuni casi in cui questo non funzionerà. Controlla il seguente output per Math.random () ... 0.730224609375, 0.43603515625, 0.957763671875 e l'elenco continua ...
eterps

@eterps Quelli NON sono numeri casuali appropriati ! Vedere prime IEEE 754 doppia in esadecimale: 0.730224609375 = 0x3fe75e0000000000, 0.43603515625 = 0x3fdbe80000000000, 0.957763671875 = 0x3feea60000000000. Quasi nessuna delle mantissa viene utilizzata! Sono solo frazioni glorificate. Un corretto output a "12 cifre" produrrebbe risultati come:0.347876714234 = 0x3fd6439cb1ab32ac, 0.447556256665 = 0x3fdca4c2ff5fc450
bryc,

Dal 2015, credo che molti browser web abbiano sostituito i PRNG scadenti usati sotto il cofano Math.random()(che devo presumere siano responsabili dei risultati di @ etertp) con quelli migliori, quindi quei tipi di numeri casuali di bassa qualità dovrebbero appartenere al passato adesso.
bryc,

30

Puoi anche usare HSL disponibile su tutti i buoni browser ( http://caniuse.com/#feat=css3-colors )

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

Questo ti darà solo colori brillanti, puoi giocare con la luminosità, la saturazione e l'alfa.

// es6
const randomHsl = () => `hsla(${Math.random() * 360}, 100%, 50%, 1)`

Grazie! Sono riuscito a ottenere colori perfetti per gli sfondi con:'hsla(' + (Math.floor(Math.random()*360) + ', 100%, 70%, 1)'
jj_

1
Nessun problema, sono stato sorpreso di vedere nessuno usando il potere di hsl :)
kigiri

stackoverflow.com/a/23861752/1693593 , HSLA senza che alfa = 1, solo uso HSL

1
Non puoi generare 16M di kolor in questo modo (ad es. Non otterrai mai una scala di grigi bianco-nero) - comunque sì - se usiamo random per ciascun componente allora otteniamo tutte le hsl corols
Kamil Kiełczewski

1
+1 In questo modo è più semplice utilizzare la luminosità e la saturazione per impostare colori di sfondo casuali, garantendo nel contempo che il testo sia sempre leggibile
Osvaldo Maria,

29

Non è necessario un hash di lettere esadecimali. JavaScript può farlo da solo:

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

27

Mi piace questa: '#' + (Math.random().toString(16) + "000000").substring(2,8)


Oppure'#' + Math.floor(Math.random()*16777215).toString(16);
Mohammad Anini il

@MohammadAnin che ha una possibilità su 16 di produrre meno di 6 cifre
James

1
Ciò potrebbe generare colori non validi. Per esempio '#' + (0.125).toString(16).substring(2, 8) === '#2'. È pericoloso perché la probabilità è bassa (1 su 4096 credo), quindi è probabile che un bug superi i test. Dovresti ('#' + Math.random().toString(16) + "000000").substring(2, 8)
James,

Correzione: dovrebbe essere'#' + (Math.random().toString(16) + "000000").substring(2,8)
James

25

Generazione casuale di colore con controllo della luminosità:

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

1
Molto bello, anche se genera principalmente "pastelli" piuttosto che colori più vivaci che speravo di vedere la luminosità. Sto ancora andando nella mia borsa di trucchi!
JayCrossler,

Mi piace molto questo perché puoi personalizzarlo per essere in armonia con la tavolozza dei colori del tuo sito 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

Mi piace questo per la sua leggibilità
hitautodestruct

1
se il risultato Math.random()restituito 0.125sarà #0.2(colore non valido) (è necessario aggiungere un po 'di padding anziché slice)
Kamil Kiełczewski

18

L'articolo scritto da Paul Irish su Random Hex Color Code Generator in JavaScript è assolutamente sorprendente. Uso:

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

Ecco il link di origine:

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


5
questo a volte restituirà valori cromatici non ben formati come "1fa4c" (devono essere 3 o 6 caratteri)
jj_

1
@jj_ è? scusa non me ne sono accorto. Grazie per aver condiviso
way2vin il

quando il ritorno casuale 0.00001quindi il risultato è #a7(colore non valido)
Kamil Kiełczewski

1
'#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0')
Haytam,

17

Ecco una svolta alla soluzione fornita da @Anatoliy.

Avevo bisogno di generare solo colori chiari (per gli sfondi), quindi sono andato con il formato a tre lettere (#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;
}

Penso che questo probabilmente produrrà colori molto simili tra loro, sebbene leggeri. Per una gamma più sparsa di colori casuali, penso che la risposta di Anatoli sia in gran parte
migliore

15

Se sei un noob come me, all'oscuro degli esadecimali e simili, potrebbe essere più intuitivo.

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

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

Devi solo finire con una stringa come 'rgb(255, 123, 220)'


questa risposta deve essere la migliore
Gil Epshtain,

Dovresti usare 256 per ottenere 0 però.
Lisa Cerilli,

13

Questo può essere facilmente trovato usando Ricerca 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;
    }
}

Versione aggiornata:

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

1
Può darsi; ma a quale sito preferiresti le possibili entrate di Google Adwords? =)
David dice di ripristinare Monica il

2
quale sito ti dà la risposta? se ti danno la risposta, dovrebbero ottenere i colpi.
Funky Dude,

1
@FunkyDude ora questo risultato è il primo su google e il motivo per cui esiste lo
stackoverflow

10

Risposta breve con pad per dimensioni esatte

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


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

Una ripartizione di come funziona:

Math.random()*256ottiene un numero casuale (in virgola mobile) da 0 a 256 (da 0 a 255 inclusi)
Risultato di esempio: 116.15200161933899

Aggiungendo le |0strisce da tutto dopo il punto decimale.
Es .: 116.15200161933899 -> 116

Usando .toString(16)converte questo numero in esadecimale (base 16).
Esempio: 116 -> 74
Altro esempio: 228 -> e4

L'aggiunta lo "0"riempie con uno zero. Questo sarà importante quando otteniamo la sottostringa, poiché il nostro risultato finale deve avere due caratteri per ogni colore.
Esempio: 74 -> 074
Altro esempio: 8 -> 08

.substr(-2)ottiene solo gli ultimi due personaggi.
Es: 074 -> 74
Un altro es: 08 -> 08 (se non avessimo aggiunto il "0", questo avrebbe prodotto "8" anziché "08")

Il forciclo esegue questo ciclo tre volte, aggiungendo ogni risultato alla stringa di colore, producendo qualcosa del genere:
#7408e4


Dovresti arricchire la tua risposta.
giovedì

8

Quindi, mentre tutte le risposte qui sono buone, volevo un po 'più di controllo sull'output. Ad esempio, vorrei evitare qualsiasi sfumatura quasi bianca, assicurandomi di ottenere colori vivaci e brillanti e non sfumati.

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

Quindi ora posso specificare 3 intervalli arbitrari da cui scegliere i valori rgb. Puoi chiamarlo senza argomenti e ottenere il mio set predefinito che di solito genererà un colore piuttosto vibrante con una tonalità dominante una volta ovvia, oppure puoi fornire la tua gamma di intervalli.


1
L'API di Google Map supporta solo il colore HTML esadecimale nel formato "#FFFFFF".
Valery Viktorovsky,

Certo, abbastanza semplice per convertire un numero in esadecimale n.toString (16) solo un problema è che devi azzerare il pad per assicurarti di ottenere un valore di ritorno di due caratteri dalla funzione g interna.
Ollie Edwards,

8

Il commento più votato della risposta principale suggerisce che l'approccio di Martin Ankerl è migliore dei numeri esadecimali casuali e, sebbene non abbia migliorato la metodologia di Ankerl, l'ho tradotto con successo in JavaScript. Ho pensato di pubblicare una risposta aggiuntiva a questo thread SO già di dimensioni mega perché la risposta principale ha un altro commento collegato a un Gist con l'implementazione JS della logica di Ankerl e quel collegamento è interrotto (404). Se avessi avuto la reputazione, avrei semplicemente commentato il link jsbin che ho creato.

// 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


7

Per casualità decente.

Colore casuale

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

Alfa casuale, colore casuale.

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

7

Ci sono molti modi in cui puoi farlo. Ecco alcuni che ho fatto:

Genera sei cifre esadecimali casuali (0-F)

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

One-liner estremamente corto

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

Genera singoli componenti HEX (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;
}

Stringa esadecimale sovraingegnerizzata (XOR 3 emette insieme per formare il colore)

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

extremley shor one-liner: quando i ritorni casuali 0.125allora il risultato è #0.2(colore non valido)
Kamil Kiełczewski

@ KamilKiełczewski 0.125= 3FC0000000000000in esadecimale IEEE. 3 cifre esadecimali sono esponenti, 13 sono mantissa. C'è una possibilità di 1 su 4.5 quadrilioni che Mantissa sia completamente vuota in quel modo. Ho provato 100m volte in Firefox / Chrome. Stai solo cercando di romperlo;). nonMath.random dovrebbe mai darti 0,125. E se lo fa, c'è un problema con il PRNG, che non è il mio problema. Frazioni come 0,5, 0,25, 0,0625 ecc. Sono inutili, non contengono casualità. Forse hai una soluzione a questo caso estremo, hm? ;)
bryc

sì, '#'+Math.random().toString(16).split('.')[1].slice(-6).padStart(6,0)ma preferisco questo
Kamil Kiełczewski,

6

Ancora un altro generatore di colori casuale:

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

6

Array.prototype.reduce lo rende molto pulito.

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

Ha bisogno di uno spessore per i vecchi browser.


nella consolle cromata sempre ritorno # 000000
Kamil Kiełczewski

6

Puoi usare questa semplice funzione

function getRandomColor(){
 var color =  "#" + (Math.random() * 0xFFFFFF << 0).toString(16);
 return color;
}

1
quando random restituisce 0.001il risultato è "#4189"(colore non valido 4 cifre)
Kamil Kiełczewski


5

Usa colori diversi .

Genera una tavolozza di colori visivamente distinti.

i colori distinti è altamente configurabile:

  • Scegli quanti colori ci sono nella tavolozza
  • Limitare la tonalità a un intervallo specifico
  • Limitare il chroma (saturazione) a un intervallo specifico
  • Limitare la leggerezza a un intervallo specifico
  • Configura la qualità generale della tavolozza

3541 righe di codice ... dove altre risposte qui sono ~ 6-10 righe ... sono impressionato come qualcuno ha scritto così tante righe di codice solo per scegliere colori distinti ...
vsync

Scegliere colori veramente visivamente distinti richiede molta più matematica di un semplice generatore di colori casuale.
InternalFX,

Ho appena fatto in 2 righe .. modificato questa funzione: stackoverflow.com/a/20129594/104380
vsync

Non è così semplice. lettura suggerita
InternalFX

Grazie, articolo molto interessante. il mio metodo fornisce sempre gli stessi colori e i risultati sono coerenti e distintivi. Immagino che in alcune situazioni potresti aver bisogno di colori casuali e ben distribuiti che siano belli per l'occhio umano.
vsync,

3

Ecco le mie due versioni per un generatore di codice esadecimale casuale.


/* 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))


3

Questa funzione va oltre le altre risposte in due modi:

Tenta di generare colori il più distinti possibile trovando quale colore su 20 tentativi ha la distanza euclidea più lontana dagli altri nel cono HSV

Ti consente di limitare la tonalità, la saturazione o l'intervallo di valori, ma cerca comunque di scegliere i colori il più distinti possibile all'interno di quell'intervallo.

Non è super efficiente, ma per valori ragionevoli (chi potrebbe persino separare facilmente 100 colori?) È abbastanza veloce.

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

3

Quasi tutti i metodi abbreviati precedenti generano codici esadecimali non validi (cinque cifre). Mi sono imbattuto in una tecnica simile solo senza questo problema qui :

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

Test

Prova questo nella console:

for(i = 0; i < 200; i++) {
    console.log("#" + ("000" + (Math.random()*(1<<24)|0).toString(16)).substr(-6));
}

4
Ho creato un ciclo for che ha eseguito questo codice 20000 volte e stampato sulla console solo se la lunghezza era inferiore a 7 e ho trovato un caso in cui la stringa era inferiore a 6 caratteri. Inoltre, un problema con questo codice è che riempie solo l'intera stringa di 6 cifre, non i singoli codici colore di 2 cifre, il che significa che è più probabile che tu abbia zero nel valore rosso rispetto ai valori verde o blu.
Erin Heyming,

quando random restituisce 0.00001il risultato è "#000a7"(colore non valido - 5 cifre)
Kamil Kiełczewski

3

La mia versione:

function RandomColor() {
  var hex = (Math.round(Math.random()*0xffffff)).toString(16);
  while (hex.length < 6) hex = "0" + hex;
  return hex;
}

Penso che il non casuale 0renda il colore non randomabbastanza XD
shrekuu

Generiamo abbandonando un numero esadecinale da 0a ffffff. Che è una distribuzione uniforme perfetta . Quello zero serve solo a completare la stringa, a causa di considerazioni sull'utilizzo del browser. Ti suggerisco di guardare più attento a questa soluzione.
Prostakov,

Ho apportato alcune modifiche, non collegate al tuo commento :)
Prostakov,

Grazie Prostakov. : D
shrekuu,


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.