Створіть шістнадцятковий колір на основі рядка з JavaScript


141

Я хочу створити функцію, яка прийме будь-яку стару рядок (зазвичай це буде одне слово) і з цього якось генерувати шістнадцяткове значення між #000000і#FFFFFF , тому я можу використовувати його як колір для елемента HTML.

Можливо, навіть шістнадцяткове значення (наприклад,:), #FFFякщо це менш складно. Насправді ідеально підійде колір із палітри "безпечної для Інтернету".


2
Чи могли б дати деякий зразок введення та / або посилання на подібні запитання?
qw3n

2
Не відповідь, але вам може бути корисне наступне: Щоб перетворити шістнадцятковий у ціле число, використовуйте parseInt(hexstr, 10). Щоб перетворити ціле число в шістнадцятковий, використовуйте n.toString(16), де n - ціле число.
Крістіан Санчес

@ qw3n - зразок введення: просто короткі, прості старі текстові рядки ... на кшталт "Медицина", "Хірургія", "Неврологія", "Загальна практика" і т. д. Розміщення між 3 і скажімо, 20 символами ... не знайти інший один , але ось ява питання: stackoverflow.com/questions/2464745 / ... @Daniel - Дякую. Мені потрібно сісти і ще серйозно піти на це. може бути корисним.
Darragh Enright

Відповіді:


176

Просто перенесення Java з Compute шістнадцятковим кольоровим кодом для довільної рядки в 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;
}

Для перетворення ви зробите:

intToRGB(hashCode(your_string))

1
чудово! дякую, це працює добре. Я не знаю багато про розрядні оператори та інше, тому ваша допомога, яка переносить його, цінується.
Darragh Enright

Їй потрібно наклеїти шістнадцяткові струни, такі як:("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);
Тимін

2
Я перетворюю купу тегів жанру музики у кольори тла, і це заощадило мені багато часу.
Кайл Пеннелл

Я б хотів, щоб я міг перетворити це на PHP.
Німіц Е.

6
У мене є проблеми з майже однаковими кольорами для подібних рядків, наприклад: intToRGB(hashCode('hello1')) -> "3A019F" intToRGB(hashCode('hello2')) -> "3A01A0" І я покращую ваш код, додаючи множення на остаточне значення хешу:return 100 * hash;
SirWojtek

185

Ось адаптація відповіді компакт-диска Санчеса, яка послідовно повертає 6-значний код кольору:

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

Використання:

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

Приклад:

http://jsfiddle.net/sUK45/

(Альтернативне / простіше рішення може включати повернення коду кольору в стилі 'rgb (...)'.)


3
Цей код працює приголомшливо в поєднанні з автоматично створеними ідентифікаторами NoSQL, ваш колір буде однаковий кожного разу для одного і того ж користувача.
deviavir

Мені також потрібен альфа-канал для прозорості в моїх шестигранних кодах. Це допомогло (додавання двох цифр для альфа-каналу наприкінці мого шістнадцяткового коду): gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
Husterknupp

@Tjorriemorrie Запропоновано вказати, що це колір, а не колір. Так, так, це не насправді на тему, але це щось важливе для мене (адже, коли ви вводили його оригінально, я написав його "кольором" обидва рази!). Дякую.
Прифтан

Цікаво, що колір відрізняється для однієї і тієї ж рядка в різних браузерах / oss - наприклад, Chrome + Windows та Chrome + Android - мій e-mail => колір - синій на одному, а зелений - з іншого. Будь-яка ідея чому?
avenmore

43

Мені хотілося подібного багатства кольорів для елементів HTML, я з подивом виявив, що CSS тепер підтримує кольори hsl (), тому повне рішення для мене знаходиться нижче:

Також див. Як автоматично генерувати N "різних" кольорів? для більшої кількості альтернатив, подібних до цієї.

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

У HSL його відтінок, насиченість, легкість. Тож відтінок між 0-359 набуде всіх кольорів, насиченість - наскільки насиченим вам потрібен колір, на мене працює 100%. А легкість визначає глибину, 50% - це нормально, 25% - темні кольори, 75% - пастельні. У мене 30%, тому що це найкраще відповідає моїй колірній гамі.


3
Дуже універсальне рішення.
MastaBaba

2
Thx для спільного використання рішення, де ви можете вирішити, якими кольорами повинні бути кольори!
Флоріан Бауер

@haykam Дякуємо, що перетворили його в фрагмент!
Тимін

Цей підхід дуже корисний, щоб надати бажану яскравість / тонкість, необхідну моєму додатку. Випадковий шестигранник дуже сильно відрізняється насиченістю та яскравістю, щоб бути корисним у більшості ситуацій. Дякую за це!
simey.me

Це рішення повертає занадто мало кольорів, не обійдеться.
катамфетамін

9

Я вважаю, що генерування випадкових кольорів має тенденцію створювати кольори, які не мають достатнього контрасту на мій смак. Найпростіший спосіб, який я знайшов, - це попередньо заповнити список дуже різних кольорів. Для кожного нового рядка призначте наступний колір у списку:

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

Хоча це обмежує лише 64 кольори, я вважаю, що більшість людей все-таки не можуть зрозуміти різницю після цього. Я думаю, ви завжди можете додати більше кольорів.

Хоча цей код використовує жорстко закодовані кольори, ви принаймні гарантовано знаєте під час розробки, скільки саме контрасту ви побачите між кольорами у виробництві.

Список кольорів був знятий з цієї відповіді ТА , є й інші списки з більшою кількістю кольорів.


Fwiw є алгоритм для визначення контрасту. Я щось писав із цим років тому (але на С). Занадто багато буде турбуватися про це, і все одно це стара відповідь, але я подумав, що я можу зазначити, що є спосіб визначити контраст.
Прифтан

7

Я відкрив запит на виклик у Please.js, який дозволяє генерувати колір із хеша.

Ви можете зіставити рядок у такий колір:

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

Наприклад, "any string goes here"повернеться як "#47291b"
і "another!"повертається як"#1f0c3d"


Дуже класно дякую за додавання цього. Привіт хочу створити кола з літерами на основі такої назви, як Google Inbox :)
marcus7777

коли я побачив цю відповідь, я подумав, що ідеально, тепер я повинен думати про кольорову схему, щоб вона не генерувала дуже випадкових кольорів, тоді я прочитала про параметри make.color Please.js, і це поставило мені красиву посмішку в обличчя.
panchicore

6

Якщо ваші входи недостатньо відрізняються, щоб простий хеш використав весь спектр кольорів, замість хеш-функції можна використовувати генератор випадкових чисел насіння.

Я використовую кольоровий кодер з відповіді Джо Фрімена і генератора випадкових чисел Девіда Бау .

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

Ще одне рішення для випадкових кольорів:

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

Це суміш речей, яка робить роботу для мене. Я використовував функцію JFreeman Hash (також відповідь у цій темі) та псевдо випадкову функцію Asykäri звідси а також деякі прокладки та математику від себе.

Я сумніваюся, що функція створює рівномірно розподілені кольори, хоча це виглядає приємно і робить те, що має робити.


'0'.repeat(...)не дійсний javascript
kikito

@kikito досить справедливо, напевно, я мав прототип якось подовжений (JQuery?). У всякому разі, я змінив цю функцію, тому це лише JavaScript ... дякую, що вказав на це.
Естані

@kikito дійсний ES6, хоча його використання нехтуватиме сумісністю між веб-браузерами.
Патрік Робертс

5

Використовуючи відповідь hashCodeКрістіана Санчеса hslі сучасний javascript, ви можете створити колектор вибору кольорів з хорошим контрастом, як це:

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>

Оскільки це hsl, ви можете масштабувати яскравість, щоб отримати контраст, який шукаєте.

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>


4

Ось рішення, яке я придумав, щоб створити естетично приємні пастельні кольори на основі вхідного рядка. Він використовує перші два символи рядка як випадкове насіння, потім генерує R / G / B на основі цього насіння.

Це можна легко розширити, так що насіння є ХОР усіх символів у рядку, а не лише перших двох.

Натхненний відповіддю Девіда Кроу тут: Алгоритм випадкового генерування естетично приємної палітри кольорів

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

ГІСТ тут: https://gist.github.com/ro-sharp/49fd46a071a267d9e5dd


Треба сказати, що це дійсно дивний спосіб зробити це. Це працює, але кольорів не дуже багато. XOR з перших двох кольорів не відрізняє порядку, тому є лише комбінації літер. Простим доповненням, який я зробив для збільшення кількості кольорів, було варне насіння = 0; for (var i in input_str) {seed ^ = i; }
Gussoh

Так, це дійсно залежить від того, скільки кольорів ви хочете генерувати. Я пам’ятаю, що в цьому випадку я створював різні панелі в інтерфейсі і хотів обмежити кількість кольорів, а не веселку :)
Роберт Шарп

1

Ось ще одна спроба:

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

Все, що вам справді потрібно, - це хороша хеш-функція. На вузлі я просто використовую

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

0

Я конвертую це для Java.

Баки для всіх.

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

-1

Ця функція виконує трюк. Це адаптація цієї, досить тривалої реалізації цього репорту .

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

Це генерує багато дуже темних значень.
Ленґдон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.