Erstellen Sie eine hexadezimale Farbe basierend auf einer Zeichenfolge mit JavaScript

140

Ich möchte eine Funktion erstellen, die jede alte Zeichenfolge akzeptiert (normalerweise ein einzelnes Wort) und daraus irgendwie einen hexadezimalen Wert zwischen #000000und generiert #FFFFFF, damit ich sie als Farbe für ein HTML-Element verwenden kann.

Vielleicht sogar ein Hex-Kurzwert (zB :), #FFFwenn das weniger kompliziert ist. In der Tat wäre eine Farbe aus einer "web-sicheren" Palette ideal.

Darragh Enright
quelle
2
Könnten Sie einige Beispieleingaben und / oder Links zu ähnlichen Fragen geben?
qw3n
2
Keine Antwort, aber möglicherweise hilfreich: Um eine Hexadezimalzahl in eine Ganzzahl umzuwandeln, verwenden Sie parseInt(hexstr, 10). Verwenden Sie zum Konvertieren einer Ganzzahl in eine Hexadezimalzahl n.toString(16), wobei n eine Ganzzahl ist.
Cristian Sanchez
@ qw3n - Beispieleingabe: Nur kurze, einfache alte Textzeichenfolgen ... wie 'Medizin', 'Chirurgie', 'Neurologie', 'Allgemeinmedizin' usw. Zwischen 3 und sagen, 20 Zeichen ... können nicht gefunden werden die andere aber hier ist die Java-Frage: stackoverflow.com/questions/2464745/… @Daniel - Danke. Ich muss mich hinsetzen und noch einmal ernsthaft darüber nachdenken. könnte nützlich sein.
Darragh Enright

Antworten:

174

Portieren Sie einfach über Java aus Compute Hex Color Code für eine beliebige Zeichenfolge nach 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;
}

Um zu konvertieren, würden Sie tun:

intToRGB(hashCode(your_string))
Cristian Sanchez
quelle
1
großartig! Danke, das funktioniert gut. Ich weiß nicht viel über bitweise Operatoren und ähnliches, daher wird Ihre Hilfe beim Portieren geschätzt.
Darragh Enright
Es muss die Hex-Zeichenfolgen auffüllen, wie zum Beispiel:("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
2
Ich konvertiere eine Reihe von Musikgenre-Tags in Hintergrundfarben und das hat mir viel Zeit gespart.
Kyle Pennell
Ich wünschte, ich könnte dies in PHP konvertieren.
Nimitz E.
6
Ich habe einige Probleme mit fast gleichen Farben für ähnliche Zeichenfolgen, zum Beispiel: intToRGB(hashCode('hello1')) -> "3A019F" intToRGB(hashCode('hello2')) -> "3A01A0" Und ich verbessere Ihren Code durch Hinzufügen einer Multiplikation für den endgültigen Hashwert:return 100 * hash;
SirWojtek
184

Hier ist eine Anpassung der Antwort von CD Sanchez, die konsistent einen 6-stelligen Farbcode zurückgibt:

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

Verwendung:

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

Beispiel:

http://jsfiddle.net/sUK45/

(Eine alternative / einfachere Lösung könnte die Rückgabe eines Farbcodes im Stil 'rgb (...)' beinhalten.)

Joe Freeman
quelle
3
Dieser Code funktioniert hervorragend in Verbindung mit automatisch generierten NoSQL-IDs. Ihre Farbe ist jedes Mal für denselben Benutzer gleich.
Deviavir
Ich brauchte den Alphakanal auch für die Transparenz meiner Hex-Codes. Dies half (Hinzufügen von zwei Ziffern für den Alpha-Kanal am Ende meines Hex-Codes): gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
Husterknupp
@Tjorriemorrie Upvoted für den Hinweis, dass es Farbe und nicht Farbe ist. Ja, ja, es ist nicht wirklich ein Thema, aber es ist etwas, das mir wichtig ist (tatsächlich habe ich es beim ursprünglichen Schreiben beide Male "Farbe" geschrieben!). Danke dir.
Pryftan
Interessant, dass die Farbe für dieselbe Zeichenfolge in verschiedenen Browsern / Oss unterschiedlich ist - z. B. Chrome + Windows und Chrome + Android - meine E-Mail => Farbe ist auf der einen blau und auf der anderen grün. Irgendeine Idee warum?
Avenmore
43

Ich wollte einen ähnlichen Farbreichtum für HTML-Elemente. Ich war überrascht, dass CSS jetzt hsl () -Farben unterstützt. Eine vollständige Lösung für mich finden Sie unten:

Siehe auch So generieren Sie automatisch N "unterschiedliche" Farben. für mehr Alternativen ähnlicher.

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

In HSL ist sein Farbton, Sättigung, Leichtigkeit. Der Farbton zwischen 0 und 359 erhält also alle Farben. Die Sättigung ist, wie reich die Farbe sein soll. 100% funktioniert für mich. Und Helligkeit bestimmt die Tiefe, 50% sind normal, 25% sind dunkle Farben, 75% sind Pastellfarben. Ich habe 30%, weil es am besten zu meinem Farbschema passt.

Thymin
quelle
3
Eine sehr vielseitige Lösung.
MastaBaba
2
Vielen Dank für das Teilen einer Lösung, bei der Sie entscheiden können, wie bunt die Farben sein sollen!
Florian Bauer
@ Haykam Danke, dass du es zu einem Snippet gemacht hast!
Thymin
Dieser Ansatz ist sehr nützlich, um die gewünschte Lebendigkeit / Subtilität zu erzielen, die meine App benötigt. Ein zufälliges Hex variiert viel zu stark in Sättigung und Helligkeit, um in den meisten Situationen nützlich zu sein. Danke dafür!
simey.me
Diese Lösung liefert zu wenig Farben, reicht aber nicht aus.
Katamphetamin
9

Ich finde, dass das Erzeugen zufälliger Farben dazu neigt, Farben zu erzeugen, die nicht genug Kontrast für meinen Geschmack haben. Der einfachste Weg, dies zu umgehen, besteht darin, eine Liste mit sehr unterschiedlichen Farben vorab auszufüllen. Weisen Sie für jede neue Zeichenfolge die nächste Farbe in der Liste zu:

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

Obwohl dies auf nur 64 Farben begrenzt ist, finde ich, dass die meisten Menschen den Unterschied danach sowieso nicht wirklich erkennen können. Ich nehme an, Sie könnten immer mehr Farben hinzufügen.

Während dieser Code fest codierte Farben verwendet, wissen Sie zumindest während der Entwicklung garantiert genau, wie viel Kontrast Sie zwischen den Farben in der Produktion sehen werden.

Die Farbliste wurde aus dieser SO-Antwort entfernt . Es gibt andere Listen mit mehr Farben.

Rick Smith
quelle
Fwiw gibt es einen Algorithmus, um den Kontrast zu bestimmen. Ich habe vor Jahren etwas damit geschrieben (aber in C). Es ist zu viel los, um sich darüber Sorgen zu machen, und es ist sowieso eine alte Antwort, aber ich dachte, ich würde darauf hinweisen, dass es einen Weg gibt, den Kontrast zu bestimmen.
Pryftan
7

Ich habe eine Pull-Anfrage an Please.js geöffnet , mit der eine Farbe aus einem Hash generiert werden kann.

Sie können die Zeichenfolge einer Farbe wie folgt zuordnen:

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

Gibt beispielsweise "any string goes here"as zurück "#47291b"
und "another!"gibt as zurück"#1f0c3d"

Josue Alexander Ibarra
quelle
Wirklich cool, danke, dass du das hinzugefügt hast. Hallo,
ich
Als ich diese Antwort sah, dachte ich, perfekt, jetzt muss ich über das Farbschema nachdenken, damit es keine sehr zufälligen Farben erzeugt. Dann las ich über die make.color-Optionen von Please.js und brachte ein schönes Lächeln in mein Gesicht.
Panchicore
6

Wenn Ihre Eingaben nicht unterschiedlich genug sind, damit ein einfacher Hash das gesamte Farbspektrum nutzen kann, können Sie anstelle einer Hash-Funktion einen gesetzten Zufallszahlengenerator verwenden.

Ich verwende den Farbcodierer aus Joe Freemans Antwort und David Baus gesetzten Zufallszahlengenerator .

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

Noch eine Lösung für zufällige Farben:

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 ist eine Mischung aus Dingen, die den Job für mich erledigen. Ich habe die JFreeman Hash-Funktion (auch eine Antwort in diesem Thread) und die Asykäri-Pseudozufallsfunktion von hier und etwas Auffüllen und Mathematik von mir selbst verwendet.

Ich bezweifle, dass die Funktion gleichmäßig verteilte Farben erzeugt, obwohl sie gut aussieht und genau das tut, was sie tun sollte.

estani
quelle
'0'.repeat(...)ist nicht gültig Javascript
Kikito
@kikito fair genug, wahrscheinlich hatte ich den Prototyp irgendwie erweitert (JQuery?). Wie auch immer, ich habe die Funktion so bearbeitet, dass sie nur Javascript ist ... danke, dass Sie darauf hingewiesen haben.
Estani
@kikito es ist gültig ES6, obwohl die Verwendung es Cross-Browser-Kompatibilität vernachlässigen würde.
Patrick Roberts
5

Mit dem hashCodewie in Cristian Sanchez 'Antwort mit hslund modernem Javascript können Sie einen Farbwähler mit gutem Kontrast wie folgt erstellen:

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>

Da es sich um hsl handelt, können Sie die Luminanz skalieren, um den gewünschten Kontrast zu erzielen.

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>

Kyle Kelley
quelle
4

Hier ist eine Lösung, die ich gefunden habe, um auf der Grundlage einer Eingabezeichenfolge ästhetisch ansprechende Pastellfarben zu generieren. Es verwendet die ersten beiden Zeichen der Zeichenfolge als zufälligen Startwert und generiert dann R / G / B basierend auf diesem Startwert.

Es kann leicht erweitert werden, sodass der Startwert das XOR aller Zeichen in der Zeichenfolge ist und nicht nur die ersten beiden.

Inspiriert von David Crows Antwort hier: Algorithmus zur zufälligen Erzeugung einer ästhetisch ansprechenden Farbpalette

//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 ist hier: https://gist.github.com/ro-sharp/49fd46a071a267d9e5dd

Robert Sharp
quelle
Ich muss sagen, dass dies eine wirklich seltsame Art ist, dies zu tun. Es funktioniert, aber es sind nicht sehr viele Farben verfügbar. XOR der ersten beiden Farben unterscheidet nicht in der Reihenfolge, daher gibt es nur Buchstabenkombinationen. Eine einfache Ergänzung, die ich gemacht habe, um die Anzahl der Farben zu erhöhen, war var seed = 0; für (var i in input_str) {seed ^ = i; }
Gussoh
Ja, es hängt wirklich davon ab, wie viele Farben Sie generieren möchten. Ich erinnere mich, dass ich in diesem Fall verschiedene Fenster in einer Benutzeroberfläche erstellt habe und eine begrenzte Anzahl von Farben anstelle eines Regenbogens wollte :)
Robert Sharp
1

Hier ist ein weiterer Versuch:

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;
}
Kikito
quelle
1

Alles was Sie wirklich brauchen ist eine gute Hash-Funktion. Auf Knoten benutze ich nur

const crypto = require('crypto');
function strToColor(str) {
    return '#' + crypto.createHash('md5').update(str).digest('hex').substr(0, 6);
}
PulseJet
quelle
0

Ich konvertiere dies für Java.

Panzer für alle.

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;
    }
Ali Bagheri
quelle
-1

Diese Funktion macht den Trick. Es ist eine Anpassung dieser, ziemlich längeren Implementierung dieses Repos .

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('')}`;
}
Theódór Ágúst Magnússon
quelle
Dies erzeugt viele sehr dunkle Werte.
Langdon