web-dev-qa-db-fra.com

Créer une couleur hexadécimale basée sur une chaîne avec JavaScript

Je veux créer une fonction qui acceptera n'importe quelle chaîne ancienne (ce sera généralement un seul mot) et à partir de celle-ci en quelque sorte générer une valeur hexadécimale entre #000000 et #FFFFFF, je peux donc l'utiliser comme couleur pour un élément HTML.

Peut-être même une valeur hexadécimale abrégée (par exemple: #FFF) si c'est moins compliqué. En fait, une couleur de la palette "Web sécurisée" serait idéale.

120
Darragh Enright

Portant simplement sur le Java de calcule le code de couleur hexadécimal pour une chaîne arbitraire sur 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;
}

Pour convertir, vous feriez:

intToRGB(hashCode(your_string))
136
Cristian Sanchez

Voici une adaptation de la réponse de CD Sanchez qui renvoie systématiquement un code de couleur à 6 chiffres:

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

Usage:

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

Exemple:

http://jsfiddle.net/sUK45/

(Une solution alternative/plus simple pourrait impliquer de renvoyer un code de couleur de style 'rgb (...)'.)

154
Joe Freeman

Je souhaitais une richesse de couleurs similaire pour les éléments HTML. J'ai été surpris de constater que CSS prend désormais en charge les couleurs hsl (). Voici donc une solution complète pour moi:

Voir aussi Comment générer automatiquement N couleurs "distinctes"? pour plus de variantes plus similaires à celui-ci.

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

document.body.innerHTML = [
  "javascript",
  "is",
  "Nice",
].map(colorByHashCode).join("<br/>");
span {
  font-size: 50px;
  font-weight: 800;
}

Dans HSL sa teinte, saturation, légèreté. Ainsi, la teinte entre 0 et 359 aura toutes les couleurs, la saturation correspond à la richesse de la couleur que vous voulez, 100% fonctionne pour moi. Et la clarté détermine la profondeur, 50% est normal, 25% est des couleurs sombres, 75% est pastel. J'ai 30% parce que cela correspond le mieux à ma palette de couleurs.

38
Thymine

Je trouve que la génération de couleurs aléatoires a tendance à créer des couleurs qui n'ont pas assez de contraste à mon goût. Le moyen le plus simple que j'ai trouvé pour contourner ce problème est de pré-renseigner une liste de couleurs très différentes. Pour chaque nouvelle chaîne , attribuez la couleur suivante à la liste:

// 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");

Bien que cela ne limite que 64 couleurs, je trouve que la plupart des humains ne peuvent pas vraiment faire la différence par la suite. Je suppose que vous pouvez toujours ajouter plus de couleurs.

Bien que ce code utilise des couleurs codées en dur, vous êtes au moins assuré de savoir pendant le développement combien de contraste vous verrez entre les couleurs en production.

La liste de couleurs a été levée de this SO answer , il y a d'autres listes avec plus de couleurs.

8
Rick Smith

J'ai ouvert ne demande d'extraction à Please.js qui permet de générer une couleur à partir d'un hachage.

Vous pouvez mapper la chaîne sur une couleur comme ceci:

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

Par exemple, "any string goes here" retournera comme "#47291b"
et "another!" retourne comme "#1f0c3d"

5

Si vos entrées ne sont pas suffisamment différentes pour qu'un simple hachage puisse utiliser tout le spectre de couleurs, vous pouvez utiliser un générateur de nombres aléatoires avec graines au lieu d'une fonction de hachage.

J'utilise le codeur de couleur de la réponse de Joe Freeman, et le générateur de nombres aléatoires de David Ba .

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

Voici une solution que j'ai proposée pour générer des couleurs pastel esthétiquement agréables à partir d'une chaîne d'entrée. Il utilise les deux premiers caractères de la chaîne comme une graine aléatoire, puis génère R/V/B en fonction de cette graine.

Il pourrait être facilement étendu de sorte que la valeur de départ soit XOR) de tous les caractères de la chaîne, plutôt que seulement les deux premiers.

Inspiré par la réponse de David Crow, voici: Algorithme pour générer de manière aléatoire une palette de couleurs esthétique

//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 ici: https://Gist.github.com/ro-sharp/49fd46a071a267d9e5dd

4
Robert Sharp

Encore une autre solution pour les couleurs aléatoires:

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

C'est un mélange de choses qui fait le travail pour moi. J'ai utilisé la fonction JFreeman Hash (également une réponse dans ce fil) et la fonction pseudo-aléatoire Asykäri de ici , ainsi qu'un peu de remplissage et de calcul de moi-même.

Je doute que la fonction produise des couleurs uniformément réparties, même si elle a l’air agréable et fait ce qu’elle devrait faire.

4
estani

En utilisant le hashCode comme dans la réponse de Cristian Sanchez avec hsl et le javascript moderne, vous pouvez créer un sélecteur de couleur avec un bon contraste comme celui-ci:

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

function pickColor(str) {
  return `hsl(${hashCode(str) % 360}, 100%, 80%)`;
}

one.style.backgroundColor = pickColor(one.innerText)
two.style.backgroundColor = pickColor(two.innerText)
div {
  padding: 10px;
}
<div id="one">One</div>
<div id="two">Two</div>

Étant donné que c'est hsl, vous pouvez ajuster la luminance pour obtenir le contraste que vous recherchez.

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

function pickColor(str) {
  // Note the last value here is now 50% instead of 80%
  return `hsl(${hashCode(str) % 360}, 100%, 50%)`;
}

one.style.backgroundColor = pickColor(one.innerText)
two.style.backgroundColor = pickColor(two.innerText)
div {
  color: white;
  padding: 10px;
}
<div id="one">One</div>
<div id="two">Two</div>
3
Kyle Kelley

Voici un autre essai:

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

Je convertis cela pour Java.

Des chars pour tous.

public static int getColorFromText(String text)
    {
        if(text == null || text.length() < 1)
            return Color.BLACK;

        int hash = 0;

        for (int i = 0; i < text.length(); i++)
        {
            hash = text.charAt(i) + ((hash << 5) - hash);
        }

        int c = (hash & 0x00FFFFFF);
        c = c - 16777216;

        return c;
    }
0
Ali Bagheri

Cette fonction fait l'affaire. C'est une adaptation de cette mise en œuvre assez longue ce 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('')}`;
}