2010-08-06 16 views
71

Quiero crear una función que acepte cualquier cadena de edad (por lo general será una sola palabra) ya partir de ese alguna manera generar un valor hexadecimal entre #000000 y #FFFFFF, por lo que puede usarlo como un color para un elemento HTML.crear un color hexadecimal basado en una cadena con JavaScript

Tal vez incluso un valor hexadecimal hexadecimal (por ejemplo: #FFF) si eso es menos complicado. De hecho, un color de una paleta 'web-safe' sería ideal.

+2

¿Podría dar algunos ejemplos de entrada y/o enlaces a las preguntas similares? – qw3n

+2

No es una respuesta, pero puede encontrar útil lo siguiente: Para convertir un hexadecimal en un entero, use 'parseInt (hexstr, 10)'. Para convertir un entero a un hexadecimal, use 'n.toString (16)', donde n es un entero. –

+0

@ qw3n - entrada de muestra: cadenas de texto simples, cortas, simples ... como 'Medicina', 'Cirugía', 'Neurología', 'Práctica general', etc. Que van desde 3 hasta 20 caracteres ... lata no encuentra el otro, pero esta es la pregunta de Java: http://stackoverflow.com/questions/2464745/compute-hex-color-code-for-an-arbitrary-string @Daniel - Gracias. Necesito sentarme y tener otra oportunidad seria en esto. Podría ser útil. –

Respuesta

80

Sólo portar sobre el Java desde Compute hex color code for an arbitrary string de Javascript:

function hashCode(str) { // java String#hashCode 
    var hash = 0; 
    for (var i = 0; i < str.length; i++) { 
     hash = str.charCodeAt(i) + ((hash << 5) - hash); 
    } 
    return hash; 
} 

function intToRGB(i){ 
    var c = (i & 0x00FFFFFF) 
     .toString(16) 
     .toUpperCase(); 

    return "00000".substring(0, 6 - c.length) + c; 
} 

Convertir puede hacer:

intToRGB(hashCode(your_string)) 
+0

¡genial! gracias, esto funciona bienNo sé mucho sobre los operadores bit a bit y esas cosas por lo que se agradece su ayuda al portarlo. –

+5

http://jsfiddle.net/sUxQe/ a veces MENOS que 6 ... –

+0

Necesita rellenar las cadenas hexagonales, tales como: '(" 00 "+ ((this >> 24) & 0xFF) .toString (16)). Slice (-2) + ("00" + ((this >> 16) & 0xFF) .toString (16)). Slice (-2) + ("00" + ((this >> 8) & 0xFF) .toString (16)). Slice (-2) + ("00" + (this & 0xFF) .toString (16)). Slice (-2); ' – Thymine

111

Aquí está una adaptación de la respuesta de CD Sánchez' que devuelve siempre un color de 6 dígitos código:

var stringToColour = function(str) { 
    var hash = 0; 
    for (var i = 0; i < str.length; i++) { 
    hash = str.charCodeAt(i) + ((hash << 5) - hash); 
    } 
    var colour = '#'; 
    for (var i = 0; i < 3; i++) { 
    var value = (hash >> (i * 8)) & 0xFF; 
    colour += ('00' + value.toString(16)).substr(-2); 
    } 
    return colour; 
} 

uso:

stringToColour("greenish"); 
// -> #9bc63b 

Ejemplo:

http://jsfiddle.net/sUK45/

(An/solución más simple alternativa podría implicar devolver un 'rgb (...)' - código de color estilo.)

+0

Un punto de referencia para esto: http://jsperf.com/3-rgb-ints-to-hexcolor-string – yckart

+2

This El código funciona de maravilla junto con las identificaciones generadas automáticamente por NoSQL, su color será el mismo siempre para el mismo usuario. – deviavir

+5

Upvoted para deletrear el color correctamente – Tjorriemorrie

4

Si las entradas no están lo suficientemente diferente para que un hash simple use todo el espectro de colores, puede usar un generador de números aleatorios en lugar de una función de hash.

Estoy usando el codificador de color de la respuesta de Joe Freeman, y David Bau's seeded random number generator.

function stringToColour(str) { 
    Math.seedrandom(str); 
    var rand = Math.random() * Math.pow(255,3); 
    Math.seedrandom(); // don't leave a non-random seed in the generator 
    for (var i = 0, colour = "#"; i < 3; colour += ("00" + ((rand >> i++ * 8) & 0xFF).toString(16)).slice(-2)); 
    return colour; 
} 
3

Sin embargo, otra solución para los colores al azar:

function colorize(str) { 
    for (var i = 0, hash = 0; i < str.length; hash = str.charCodeAt(i++) + ((hash << 5) - hash)); 
    color = Math.floor(Math.abs((Math.sin(hash) * 10000) % 1 * 16777216)).toString(16); 
    return '#' + Array(6 - color.length + 1).join('0') + color; 
} 

Es un mixto de las cosas que hace el trabajo para mí. Utilicé la función JFreeman Hash (también una respuesta en este hilo) y la función pseudo aleatoria Asykäri de here y algo de relleno y matemática de mí mismo.

Dudo que la función produzca colores distribuidos uniformemente, aunque se ve bien y hace lo que debería hacer.

+0

''0'.repeat (...)' no es válido javascript – kikito

+0

@kikito bastante, probablemente tuve el prototipo extendido de alguna manera (¿JQuery?). De todos modos, he editado la función por lo que es solo JavaScript ... gracias por señalar eso. – estani

+0

@kikito es válido ES6, aunque usarlo sería descuidar la compatibilidad entre navegadores. –

21

quería riqueza similar en los colores de los elementos HTML, que se sorprendió al descubrir que el CSS ahora es compatible con HSL() colores, por lo que una solución completa para mí es el siguiente:

Véase también How to automatically generate N "distinct" colors? para más alternativas más similares a esta.

function colorByHashCode(value) { 
    return "<span style='color:" + value.getHashCode().intToHSL() + "'>" + value + "</span>"; 
} 
String.prototype.getHashCode = function() { 
    var hash = 0; 
    if (this.length == 0) return hash; 
    for (var i = 0; i < this.length; i++) { 
     hash = this.charCodeAt(i) + ((hash << 5) - hash); 
     hash = hash & hash; // Convert to 32bit integer 
    } 
    return hash; 
}; 
Number.prototype.intToHSL = function() { 
    var shortened = this % 360; 
    return "hsl(" + shortened + ",100%,30%)"; 
}; 

En HSL es Hue, Saturation, Ligereza. Así que el tono entre 0-359 obtendrá todos los colores, la saturación es la riqueza que desea el color, el 100% funciona para mí. Y la luminosidad determina la profundidad, el 50% es normal, el 25% es de colores oscuros, el 75% es de color pastel. Tengo 30% porque encaja mejor con mi esquema de color.

+1

Una solución muy versátil. – MastaBaba

+1

Thx para compartir una solución, ¡donde puede decidir qué color deben tener los colores! –

1

Aquí es otro intento:

function stringToColor(str){ 
    var hash = 0; 
    for(var i=0; i < str.length; i++) { 
    hash = str.charCodeAt(i) + ((hash << 3) - hash); 
    } 
    var color = Math.abs(hash).toString(16).substring(0, 6); 

    return "#" + '000000'.substring(0, 6 - color.length) + color; 
} 
4

Acabo de construir una característica que encaja a la perfección en Please.js, todavía no se fusiona con el repositorio principal, pero se puede ver aquí:

https://github.com/ibarrajo/PleaseJS

puede asignar la cadena a un color, así:

var color = Please.make_color({from_hash: 'any string goes here'}); 

"any string goes here" volverá como "#47291b"
y "another!" rentabilidad, ya que "#1f0c3d"

+0

Realmente genial gracias por agregar eso. Hola, quiero generar círculos con letras en base a un nombre como la bandeja de entrada de Google :) :) – marcus7777

6

Me parece que la generación de los colores al azar tiende a crear colores que no tienen suficiente contraste para mi gusto. La forma más fácil que he encontrado para evitar eso es rellenar previamente una lista de colores muy diferentes. Por cada nueva cadena , asignar el color siguiente en la lista:

// Takes any string and converts it into a #RRGGBB color. 
var StringToColor = (function(){ 
    var instance = null; 

    return { 
    next: function stringToColor(str) { 
     if(instance === null) { 
      instance = {}; 
      instance.stringToColorHash = {}; 
      instance.nextVeryDifferntColorIdx = 0; 
      instance.veryDifferentColors = ["#000000","#00FF00","#0000FF","#FF0000","#01FFFE","#FFA6FE","#FFDB66","#006401","#010067","#95003A","#007DB5","#FF00F6","#FFEEE8","#774D00","#90FB92","#0076FF","#D5FF00","#FF937E","#6A826C","#FF029D","#FE8900","#7A4782","#7E2DD2","#85A900","#FF0056","#A42400","#00AE7E","#683D3B","#BDC6FF","#263400","#BDD393","#00B917","#9E008E","#001544","#C28C9F","#FF74A3","#01D0FF","#004754","#E56FFE","#788231","#0E4CA1","#91D0CB","#BE9970","#968AE8","#BB8800","#43002C","#DEFF74","#00FFC6","#FFE502","#620E00","#008F9C","#98FF52","#7544B1","#B500FF","#00FF78","#FF6E41","#005F39","#6B6882","#5FAD4E","#A75740","#A5FFD2","#FFB167","#009BFF","#E85EBE"]; 
     } 

     if(!instance.stringToColorHash[str]) 
      instance.stringToColorHash[str] = instance.veryDifferentColors[instance.nextVeryDifferntColorIdx++]; 

      return instance.stringToColorHash[str]; 
     } 
    } 
})(); 

// Get a new color for each string 
StringToColor.next("get first color"); 
StringToColor.next("get second color"); 

// Will return the same color as the first time 
StringToColor.next("get first color"); 

Si bien esto tiene un límite a sólo 64 colores, encuentro la mayoría de los humanos no pueden realmente decir la diferencia después de que de todos modos. Supongo que siempre puedes agregar más colores.

Si bien este código utiliza colores codificados, al menos se garantiza que durante el desarrollo se sepa exactamente cuánto contraste se verá entre los colores en producción.

La lista de colores se ha retirado de this SO answer, hay otras listas con más colores.

2

He aquí una solución que surgió para generar colores pastel estéticamente agradables basados ​​en una cadena de entrada. Utiliza los dos primeros caracteres de la cadena como una semilla aleatoria, luego genera R/G/B en base a esa semilla.

Se podría extender fácilmente para que la semilla sea el XOR de todos los caracteres del hilo, en lugar de solo los dos primeros.

Inspirado por la respuesta de David Crow aquí: Algorithm to randomly generate an aesthetically-pleasing color palette

//magic to convert strings to a nice pastel colour based on first two chars 
// 
// every string with the same first two chars will generate the same pastel colour 
function pastel_colour(input_str) { 

    //TODO: adjust base colour values below based on theme 
    var baseRed = 128; 
    var baseGreen = 128; 
    var baseBlue = 128; 

    //lazy seeded random hack to get values from 0 - 256 
    //for seed just take bitwise XOR of first two chars 
    var seed = input_str.charCodeAt(0)^input_str.charCodeAt(1); 
    var rand_1 = Math.abs((Math.sin(seed++) * 10000)) % 256; 
    var rand_2 = Math.abs((Math.sin(seed++) * 10000)) % 256; 
    var rand_3 = Math.abs((Math.sin(seed++) * 10000)) % 256; 

    //build colour 
    var red = Math.round((rand_1 + baseRed)/2); 
    var green = Math.round((rand_2 + baseGreen)/2); 
    var blue = Math.round((rand_3 + baseBlue)/2); 

    return { red: red, green: green, blue: blue }; 
} 

GIST está aquí: https://gist.github.com/ro-sharp/49fd46a071a267d9e5dd

+0

Debo decir que esta es una forma realmente extraña de hacerlo. Funciona, pero no hay muchos colores disponibles. XOR de los primeros dos colores no hace distinción de orden por lo que solo hay combinaciones de letras. Una simple adición que hice para aumentar el número de colores fue var seed = 0; for (var i en input_str) { seed^= i; } – Gussoh

0

Esta función hace el truco. Es una adaptación de esta implementación, bastante más larga this repo ..

const color = (str) => { 
    let rgb = []; 
    // Changing non-hexadecimal characters to 0 
    str = [...str].map(c => (/[0-9A-Fa-f]/g.test(c)) ? c : 0).join(''); 
    // Padding string with zeroes until it adds up to 3 
    while (str.length % 3) str += '0'; 

    // Dividing string into 3 equally large arrays 
    for (i = 0; i < str.length; i += str.length/3) 
     rgb.push(str.slice(i, i + str.length/3)); 

    // Formatting a hex color from the first two letters of each portion 
    return `#${rgb.map(string => string.slice(0, 2)).join('')}`; 
} 
Cuestiones relacionadas