2009-04-08 21 views
31

Estoy generando algunos gráficos que necesitan una cadena hexadecimal para los colores.¿Cómo creo una cadena hexagonal aleatoria que represente un color?

Ejemplo:

<dataseries name="ford" color="FF00FF" /> 

estoy creando estos dinámicamente, lo que me gustaría para generar el código hexadecimal para cada dataseries aleatoriamente.

¿Cuál es la mejor manera de hacerlo?

+0

Acabo de notar que mi ejemplo no ha llegado. Supongo que es porque era una cadena xml ... Bueno, no importó ya que la respuesta funcionó muy bien. – rahkim

+1

@rahkim - pregunta actualizada para arreglar eso y agregar un título más significativo –

Respuesta

94

La manera más fácil es usar String.Format y usar el formato hexadecimal para el argumento.

var random = new Random(); 
var color = String.Format("#{0:X6}", random.Next(0x1000000)); // = "#A197B9" 
+2

+1 Eso es increíblemente simple, claro y rápido. –

+0

Lo sé, primero miré pensando en usar una matriz y elegir elementos, entonces recuerdo que String.Format puede hacer hexadecimal. – Samuel

+2

Corrígeme si me equivoco, pero con ese código, nunca generarás el valor 0xFFFFFF ya que el entero que pasas al método Next es el límite superior no inclusivo. Entonces necesitaría random.Next (0x1000000) para que se devuelva 0xFFFFFF. –

4
Random rand = new Random(); // specify a seed 
int r = rand.Next(0x1000000); 
Console.WriteLine("#{0:X6}", r); 
+1

Esto no maneja valores bajos. 0x00FFFF se convierte en #FFFF que no es lo mismo que # 00FFFF. – Samuel

15

OMI, puramente colores al azar puede no ser preferible que necesite colores que son distinguibles en los ojos humanos.

¿Qué hay de preajustar varios colores y elegirlos aleatoriamente?

Quizás pueda encontrar mejores respuestas en algunas bibliotecas de creación de gráficos de fuente abierta.

+0

Este sería el método preferido, pero quizás el OP tenga otras razones para colores completamente aleatorios. – Samuel

+0

Pensé en esto ya que algunos colores pueden mezclarse. No estaba seguro de cuántos predefinir, ya que podría tener un gran número de series. – rahkim

+0

Un híbrido de preconfigurado y aleatorio puede ayudar. Preconfigura cuidadosamente unos 10 colores agradables. Vaya por azar si hay más que eso. En general, los ojos inexpertos comienzan a confundirse en un gráfico excesivamente coloreado, por lo que los colores exactos utilizados no son realmente importantes. – Canton

12

La respuesta de Samuel es la mejor manera de hacerlo, solo asegúrate de que si generas los colores dentro de un bucle, no instancias un nuevo objeto Random cada vez porque new Random() siembra el generador usando el reloj del sistema. Su ciclo se ejecutará más rápido de lo que el reloj puede marcar, por lo que terminará generando varios de los mismos colores una y otra vez porque random está siendo sembrado con el mismo valor.

Debe ser algo como esto:

int numColors = 10; 
var colors = new List<string>(); 
var random = new Random(); // Make sure this is out of the loop! 
for (int i = 0; i < numColors; i++) 
{ 
    colors.Add(String.Format("#{0:X6}", random.Next(0x1000000))); 
} 

en lugar de:

int numColors = 10; 
var colors = new List<string>(); 
for (int i = 0; i < numColors; i++) 
{ 
    var random = new Random(); // Don't put this here! 
    colors.Add(String.Format("#{0:X6}", random.Next(0x1000000))); 
} 
+0

¡Buena lectura! –

+1

Esto explica por qué rahkim obtiene colores aleatorios cuando usa un punto de interrupción. lol – Samuel

+0

Esto ni siquiera se me pasó por la cabeza. ¿Está agregando los colores a una lista por algún motivo?Solo una buena práctica, o hay algo que me falta? – rahkim

11

Una buena manera de generar un buen conjunto de colores es definirlos mediante la saturación fijo y el brillo y variar el matiz.

  1. Establezca la saturación y el brillo en algo que desee, por ejemplo, 50% de saturación y 90% de brillo.
  2. Ahora divida los 360 grados de matiz por el número de colores distintos que desee.
  3. colores escoger de VHS utilizando ese intervalo para el matiz, y el S fijo y V.

Esto le da un buen conjunto de colores, todos los cuales parecen que vinieron de la misma 'set' - todo pastel, o todo intenso, o todo blanco roto, lo que sea. Y es bastante fácil codificar si tiene Color.FromHSV().

Probablemente deje de funcionar una vez que obtenga demasiados colores, sin embargo, serán indistinguibles. Pero probablemente tendrás ese problema de todos modos.

En pseudocódigo:

Sat = 0.5 * 255 //assuming we want range 0-255... 
Brightness = 0.9 * 255 
NumberOfColours = 7 
HueSeparation = 360/7 
Colors = [] 
for (i = 0 ; i< NumberOfColours; i++) 
    Colors.Add(Color.FromHSV(HueSeparation * i, Sat, Brightness) 

o

n = 7 
Colors = [Color.FromHSV(x*360/n, 128, 230) for x in range(n)] 

(me gustan las listas por comprensión ...)

+0

Idea genial. Desearía poder ponerlo en el código. ;-) – rahkim

3

Noté que usted (Rahkim) comentó en la publicación de Greg que desea que pueda poner su idea (manteniendo la saturación y el valor constantes, y simplemente variando el matiz ... una buena idea) en el código. ¡Usted puede! O, mejor dicho, ¡alguien ya tiene para ti!

Encontré esta publicación en el blog Converting HSV to RGB colour using C#, y estoy seguro de que hay más por ahí. Probablemente termines con un conjunto de colores más agradable de esta manera que escogiéndolos totalmente al azar.

Además, por supuesto, este método hace que sea sencillo para conseguir un buen conjunto de colores ... ya que el tono va de 0-359, se podría hacer algo así como establecer su tono algo como esto:

Hue = (PreviousHue + 50) % 360; 

(Elegí 50 ya que no entra 360 de manera uniforme, así que si vas más allá de 360 ​​no comenzarás a repetir los tonos al instante. Tendrás que jugar con el valor para obtener una separación ideal dependiendo de cuántos diferentes colores que estás esperando.)

De esta manera no tienes que preocuparte por el caso en el que el código esté escogiendo aleatoriamente dos colores que están muy cerca de un punto ella cuando todavía hay mucho espacio "hue" sin usar.

+0

Me gusta esto. Me da algo de flexibilidad. – rahkim

Cuestiones relacionadas