Создание шестнадцатеричного цвета на основе строки с JavaScript

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

Возможно, даже короткое шестнадцатеричное значение (например: #FFF), если это менее сложно. Фактически, цвет из "веб-безопасной" палитры был бы идеальным.

Ответ 1

Просто портируем Java из Вычислить шестнадцатеричный код цвета для произвольной строки на 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))

Ответ 2

Здесь приведена адаптация ответа CD Sanchez, который последовательно возвращает 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

Мне нужно было такое же богатство цветов для элементов 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;
}

Ответ 4

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

// 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 цветам, я нахожу, что большинство людей не могут действительно сказать разницу после этого в любом случае. Полагаю, вы всегда можете добавить больше цветов.

В то время как в этом коде используются жестко закодированные цвета, вы, по крайней мере, должны знать во время разработки точно, сколько контрастов вы увидите между цветами в производстве.

Список цветов был снят с этого SO-ответа, есть и другие списки с большим количеством цветов.

Ответ 5

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

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

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

Ответ 6

Я открыл пулл-запрос к Please.js, который позволяет генерировать цвет из хеша.

Вы можете сопоставить строку с цветом так:

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

Например, "any string goes here" вернется как "#47291b"
и "another!" возвращается как "#1f0c3d"

Ответ 7

Еще одно решение для случайных цветов:

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 из здесь и некоторые дополнения и математику от меня.

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

Ответ 8

Вот решение, которое я придумал для создания эстетически приятных пастельных цветов на основе входной строки. Он использует первые два символа строки как случайное семя, затем генерирует R/G/B на основе этого семени.

Он может быть легко расширен таким образом, чтобы семя было XOR всех символов в строке, а не только первые два.

Вдохновленный Дэвидом Кроу, ответьте здесь: Алгоритм случайного создания эстетически приятной цветовой палитры

//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 находится здесь: https://gist.github.com/ro-sharp/49fd46a071a267d9e5dd

Ответ 9

Используя hashCode как в ответе Кристиана Санчеса с hsl и современным javascript, вы можете создать 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) {
  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>

Ответ 10

Вот еще одна попытка:

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

Ответ 11

Эта функция делает свое дело. Это адаптация этого, довольно длинная реализация этого репо..

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

Ответ 12

Я конвертирую это для 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;
    }