Gerador aleatório de cores


440

Dada essa função, desejo substituir a cor por um gerador de cores aleatório.

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

Como eu posso fazer isso?


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


2
@SepehrM quando retorna aleatórios 0.001seguida resultado é "#4189"(cor inválido - 4 dígitos)
Kamil Kiełczewski

Esta é uma solução muito agradável, para mim muito útil github.com/davidmerfield/randomColor
maikelm

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

Respostas:


1018

Use getRandomColor()no 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>


87
Observe que isso tem um viés em direção a cores bastante escuras e insaturadas, devido à maneira como o RGB envolve o espaço de cores. Martin Ankerl tem um bom artigo sobre a geração de cores de outros espaços (como HSV): martin.ankerl.com/2009/12/09/…
Thomas Ahle

13
As chances de atingir 0 ou 15 ao usar Math.round(Math.random()*15)são apenas 1:30, enquanto as chances dos outros números são 1:15.
user123444555621

3
Você pode remover a chamada .split (''). A string já possui um indexador de matriz.
ujeenator

3
Você também pode usar uma função Generator como tal
tsuz

4
Este código é coxo. Aqui está um oneliner: Math.floor (Math.random () * 16777215) .toString (16)
DDD

269

Duvido que algo seja mais rápido ou mais curto que este:

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

Desafio!


18
Você esqueceu de preencher com zeros.
User123444555621

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

15
@Mohsen, FYI a cada momento e, em seguida, seu código produz inválido número de 5 dígitos
rochal

6
O resultado não é preenchido com 6 dígitos
Taha Jahangir

33
('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6)sempre retornará um comprimento de 6. embora esse método ainda (raramente) retorne pequenos números que dão resultados como 000cf4ou 0000a7que são um pouco hacky, eu acho. nesses casos, o componente vermelho não contribui para a cor aleatória.
bryc

162

Aqui está outra opinião sobre esse problema.

Meu objetivo era criar cores vibrantes e distintas. Para garantir que as cores sejam distintas, evito usar um gerador aleatório e seleciono cores "espaçadas igualmente" no arco-íris.

Isso é perfeito para criar marcadores pop-out no Google Maps que tenham uma "exclusividade" ideal (ou seja, dois marcadores não terão cores semelhantes).

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 você deseja ver como isso fica em ação, consulte http://blog.adamcole.ca/2011/11/simple-javascript-rainbow-color.html .


7
Eu estive procurando por algo assim! Coisas boas!
Khôi 17/10/12

Eu fiz uma implementação simplificada da mesma idéia que a resposta à pergunta semelhante stackoverflow.com/a/14187677/421010
Andrew

16
Então, qual será o valor do parâmetro?
Ekramul Hoque

2
Eu também criei algo assim, mas é bastante aleatório e bastante distinto. O pseudo-código está aqui . Ele usa hsv em vez de rgb, porque o hsv tem um comportamento muito mais previsível. Se você gostaria de ver a implementação do Python, usei aqui e aqui . Você terá que procurar no código por "cor".
Zondo

1
@RobertMolina: Desculpe, mudei minhas coisas para o Gitlab. O pseudo-código está agora aqui , com os projetos aqui e aqui .
zondo 20/02/19

56

Quem pode vencê-lo?

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

Garantido para trabalhar o tempo todo: http://jsbin.com/OjELIfo/2/edit

Com base no comentário @eterps, o código acima ainda pode gerar seqüências mais curtas se a representação hexadecimal da cor aleatória for muito curta ( 0.730224609375=> 0.baf)

Este código deve funcionar em todos os casos:

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

12
Quando Math.random () retorna 0,022092682472568126, esse código produz uma string '# 5a7dd' inválida. louco!
rochal

Como este, pois #ffffff não aparece com muita frequência.
Warface

Existem algumas ocorrências em que isso não funciona. Verifique a saída a seguir para Math.random () ... 0.730224609375, 0.43603515625, 0.957763671875, e a lista continua ...
eterps 27/03

@eterps Esses NÃO são números aleatórios adequados ! Veja matéria IEEE 754 double em hexadecimal: 0.730224609375 = 0x3fe75e0000000000, 0.43603515625 = 0x3fdbe80000000000, 0.957763671875 = 0x3feea60000000000. Quase nenhuma mantissa está sendo usada! São apenas frações glorificadas. Uma saída adequada de '12 dígitos 'produziria resultados como:0.347876714234 = 0x3fd6439cb1ab32ac, 0.447556256665 = 0x3fdca4c2ff5fc450
bryc 28/02/19

Desde 2015, acredito que muitos navegadores substituíram os PRNGs Math.random()de baixa qualidade usados ​​sob o capô (os quais, suponho, são responsáveis ​​pelos resultados da @ etertp) pelos melhores, então esses tipos de números aleatórios de baixa qualidade devem ser uma coisa do passado agora.
bryc 28/02/19

29

Não há necessidade de um hash de letras hexadecimais. O JavaScript pode fazer isso sozinho:

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

29

Você também pode usar o HSL disponível em todos os bons navegadores ( http://caniuse.com/#feat=css3-colors )

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

Isso fornecerá apenas cores brilhantes. Você pode brincar com brilho, saturação e alfa.

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

Obrigado! Consegui obter cores perfeitas para fundos com:'hsla(' + (Math.floor(Math.random()*360) + ', 100%, 70%, 1)'
jj_ 28/10

1
Sem problemas, fiquei surpreso ao ver ninguém usando o poder do HSL :)
kigiri

stackoverflow.com/a/23861752/1693593 , o hsla não é necessário, alpha = 1, basta usar o hsl

1
Você não pode gerar 16M kolor desta forma (por exemplo, você nunca vai ficar em tons de cinza branco-preto) - no entanto sim - se usarmos aleatória para cada componente, em seguida, temos todas corols HSL
Kamil Kiełczewski

1
+1 Isto torna mais fácil de usar luminosidade e saturação para definir cores de fundo aleatório, assegurando que o texto é sempre legível
Osvaldo Maria

27

Eu gosto deste: '#' + (Math.random().toString(16) + "000000").substring(2,8)


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

@MohammadAnin que tem um 1 em 16 chances de produzir menos de 6 dígitos
James

1
Isso pode gerar cores inválidas. Por exemplo '#' + (0.125).toString(16).substring(2, 8) === '#2'. É perigoso porque a probabilidade é baixa (1 em 4096, eu acho), portanto é provável que um bug seja submetido ao teste. Você deveria ('#' + Math.random().toString(16) + "000000").substring(2, 8)
James

Correção: deve ser #'#' + (Math.random().toString(16) + "000000").substring(2,8)
James

25

Geração aleatória de cores com controle de brilho:

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
Muito legal, embora gere principalmente 'pastéis' em vez de cores mais vibrantes que eu esperava quando vi o brilho. Ainda vou para a minha sacola de truques!
JayCrossler

Eu realmente como este, porque você pode personalizá-lo para estar em harmonia com sua paleta de cores website
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

I como este para a sua legibilidade
hitautodestruct

1
Se Math.random()retorno 0.125, em seguida resultado será #0.2(cor inválida) (você precisa adicionar algum estofamento em vez fatia)
Kamil Kiełczewski

18

O artigo escrito por Paul Irish no Random Hex Color Code Generator em JavaScript é absolutamente incrível. Usar:

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

Aqui está o link da fonte:

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


5
isso vai voltar algures valores de cor não-formados, bem como "1fa4c" (necessidade de ser 3 ou 6 caracteres)
jj_

1
@jj_ é? desculpe, eu não percebi isso. Obrigado por compartilhar
way2vin

quando o retorno aleatório 0.00001seguida resultado é #a7(cor inválido)
Kamil Kiełczewski

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

17

Aqui está uma reviravolta na solução fornecida pela @Anatoliy.

Eu precisava gerar apenas cores claras (para planos de fundo), então usei o formato de três 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;
}

Eu acho que isso provavelmente produzirá cores mais semelhantes, embora leves. Para uma gama mais escassa de cores aleatórias, eu acho @ resposta de Anatoli é melhor para a maior parte
larrytech

15

Se você é um noob como eu, sem noção sobre hexadecimais e coisas assim, isso pode ser mais intuitivo.

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

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

Você só precisa terminar com uma string como 'rgb(255, 123, 220)'


esta resposta tem de ser a de cima
Gil Epshtain

Você precisaria usar 256 para obter 0.
Lisa Cerilli

13

Isso pode ser facilmente encontrado usando a Pesquisa do 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;
    }
}

Versão atualizada:

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
Talvez sim; mas em qual site você prefere a possível receita do Google Adwords? =)
David diz para reinstalar Monica

2
qual site dá a resposta? se eles fornecerem a resposta, eles devem receber os hits.
21339 Funky Dude

1
@FunkyDude agora este resultado é o topo um no Google e no stackoverflow razão existe é a de não usar o Google muitas vezes;)
Akshat

10

Resposta curta com teclado para o tamanho exato

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

Um detalhamento de como isso funciona:

Math.random()*256obtém um número aleatório (ponto flutuante) de 0 a 256 (inclusive 0 a 255)
Resultado do exemplo: 116.15200161933899

Adicionando as |0tiras de tudo depois do ponto decimal.
Ex: 116.15200161933899 -> 116

Usar .toString(16)converte esse número em hexadecimal (base 16).
Ex: 116 -> 74
Outro ex: 228 -> e4

Adicionar "0"almofadas com um zero. Isso será importante quando obtivermos a substring, pois nosso resultado final deve ter dois caracteres para cada cor.
Ex: 74 -> 074
Outro ex: 8 -> 08

.substr(-2)recebe apenas os dois últimos caracteres.
Ex: 074 -> 74
Outro ex: 08 -> 08 (se não o tivéssemos adicionado "0", isso teria produzido "8" em vez de "08")

O forloop executa esse loop três vezes, adicionando cada resultado à sequência de cores, produzindo algo como isto:
#7408e4


Você deve elaborar sua resposta.
joce

8

Portanto, embora todas as respostas aqui sejam boas, eu queria um pouco mais de controle sobre a saída. Por exemplo, eu gostaria de evitar tons quase brancos, garantindo cores vibrantes e brilhantes e não tons desbotados.

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

Então agora eu posso especificar 3 intervalos arbitrários para escolher os valores rgb. Você pode chamá-lo sem argumentos e obter meu conjunto padrão, que geralmente gera uma cor bastante vibrante com uma sombra dominante óbvia, ou pode fornecer sua própria variedade de intervalos.


1
A API do Google Map suporta apenas cores HTML hexadecimais no formato "#FFFFFF".
Valery Viktorovsky

Claro, bastante simples para converter um número em hexadecimal n.toString (16), apenas você precisará zerar pad para garantir um valor de retorno de dois caracteres a partir da função g interna.
Ollie Edwards

8

O comentário mais votado da resposta principal sugere que a abordagem de Martin Ankerl é melhor que os números hexadecimais aleatórios e, embora eu não tenha melhorado a metodologia de Ankerl, eu a traduzi com sucesso para JavaScript. Eu imaginei que postaria uma resposta adicional para esse segmento SO já de tamanho mega, porque a resposta principal tem outro comentário vinculado a um Gist com a implementação JS da lógica de Ankerl e esse link está quebrado (404). Se eu tivesse reputação, teria simplesmente comentado o link jsbin que criei.

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

Para uma aleatoriedade decente.

Cor aleatória

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

Alfa aleatória, cor aleatória.

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

7

Existem muitas maneiras de conseguir isso. Aqui estão alguns que eu fiz:

Gera seis dígitos hexadecimais aleatórios (0-F)

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

Uma linha extremamente curta

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

Gera componentes HEX individuais (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;
}

Sequência hexadecimal com engenharia excessiva (os XORs 3 saem juntos para formar cores)

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 os retornos aleatórios 0.125seguida resultado é #0.2(cor inválido)
Kamil Kiełczewski

@ KamilKiełczewski 0.125= 3FC0000000000000em hexadecimal IEEE. 3 dígitos hexadecimais são expoente, 13 são mantissa. Há uma chance de 1 em 4,5 quadrilhões de que a mantissa esteja completamente vazia assim. Testei 100 milhões de vezes no Firefox / Chrome. Você está apenas tentando quebrá-lo;). nuncaMath.random deve lhe dar 0,125. E se isso acontecer, há um problema com o PRNG, que não é meu problema. Frações como 0,5, 0,25, 0,0625 etc. são inúteis, elas não contêm aleatoriedade. Talvez você tenha uma solução para esse caso extremo, hm? ;)
bryc

sim, '#'+Math.random().toString(16).split('.')[1].slice(-6).padStart(6,0)mas eu prefiro isso #
Kamil Kiełczewski 19/03/19

6

Outro gerador aleatório de cores:

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 torna muito limpo.

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

Precisa de um calço para navegadores antigos.


no console do Chrome sempre retorne # 000000 #
Kamil Kiełczewski 19/03/19

6

Você poderia usar esta função simples

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

1
quando retornos aleatórios, 0.001o resultado é "#4189"(cor inválida, 4 dígitos) #
Kamil Kiełczewski 19/03/19


5

Use cores distintas .

Ele gera uma paleta de cores visualmente distintas.

cores distintas é altamente configurável:

  • Escolha quantas cores estão na paleta
  • Restrinja o matiz a um intervalo específico
  • Restrinja o croma (saturação) a um intervalo específico
  • Restrinja a luminosidade a um intervalo específico
  • Configurar a qualidade geral da paleta

3541 linhas de code..where outras respostas aqui são ~ 6-10 linhas ... Estou impressionado como é que alguém escreveu tantas linhas de código apenas para escolher cores distintas ..
vsync

Escolher cores verdadeiramente visualmente distintas requer muito mais matemática do que apenas um gerador de cores aleatório.
InternalFX

Acabei de fazê-lo em 2 linhas .. modifiquei esta função: stackoverflow.com/a/20129594/104380
vsync

Não é tão simples assim. leitura sugerida
InternalFX

Obrigado, artigo muito interessante. meu método sempre fornece as mesmas cores e os resultados são consistentes e distintos. Eu acho que em algumas situações você pode precisar de cores realmente aleatórias e bem distribuídas, que são bonitas para o olho humano.
vsync

3

Aqui estão minhas duas versões para um gerador aleatório de código hexadecimal.


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

Essa função vai acima e além de outras respostas de duas maneiras:

Ele tenta gerar cores o mais distintas possível, descobrindo qual das 20 tentativas tem a maior distância euclidiana das outras no cone do HSV

Ele permite restringir o matiz, a saturação ou o intervalo de valores, mas ainda tenta escolher cores o mais distintas possível dentro desse intervalo.

Não é super eficiente, mas por valores razoáveis ​​(quem pode escolher 100 cores facilmente?) É rápido o suficiente.

Veja 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

Quase todos os métodos anteriores de mão curta estão gerando códigos hexadecimais inválidos (cinco dígitos). Me deparei com uma técnica semelhante apenas sem esse problema aqui :

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

Teste

Tente isso no console:

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

4
Fiz um loop for que executou esse código 20000 vezes e só imprimiu no console se o comprimento fosse menor que 7 e encontrei um caso em que a string tinha menos de 6 caracteres. Além disso, um problema com esse código é que ele apenas preenche toda a cadeia de 6 dígitos, não os códigos de cores individuais de 2 dígitos, o que significa que é mais provável que você tenha zeros no valor vermelho do que nos valores verde ou azul.
Erin Heyming

quando os retornos aleatórios 0.00001o resultado é "#000a7"(cor inválido - 5 dígitos)
Kamil Kiełczewski

3

Minha versão:

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

Eu acho que os não-aleatórias 0torna a cor não randomo suficiente XD
shrekuu

Geramos um número hexadecinal de 0para ffffff. Qual é uma distribuição uniforme perfeita . Esse zero é apenas para concluir a sequência, devido a considerações de uso do navegador. Eu sugiro que você pareça mais cuidadoso com esta solução.
Prostakov

Fiz alguns ajustes, porém, não vinculados ao seu comentário :) #
Prostakov

Obrigado Prostakov. : D
shrekuu


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.