Создайте шестнадцатеричный цвет на основе строки с помощью JavaScript - PullRequest
117 голосов
/ 06 августа 2010

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

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

Ответы [ 12 ]

151 голосов
/ 03 мая 2013

Вот вариант ответа 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 (...)'.)

133 голосов
/ 06 августа 2010

Просто портирование через 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))
37 голосов
/ 10 февраля 2014

Мне хотелось такого же богатства цветов для элементов 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%. А Lightness определяет глубину, 50% - это нормально, 25% - темные цвета, 75% - пастель. У меня 30%, потому что он лучше всего подходит для моей цветовой схемы.

8 голосов
/ 25 июня 2015

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

// 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 голосов
/ 18 июля 2014

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

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

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

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

5 голосов
/ 06 ноября 2013

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

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

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;
}
4 голосов
/ 04 июля 2015

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

4 голосов
/ 27 января 2014

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

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 (также ответ в этой теме) и псевдослучайную функцию Asykäri от здесь и некоторые отступы и математические вычисления от себя.

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

3 голосов
/ 29 марта 2018

Используя 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>
1 голос
/ 21 мая 2014

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

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