使用JavaScript根据字符串创建十六进制颜色


141

我想创建将接受任何旧的字符串(通常是单个字),并从该函数在某种程度上产生之间的十六进制值,#000000并且#FFFFFF,这样我就可以把它作为一个HTML元素的颜色。

#FFF如果不那么复杂,甚至可能是一个简写的十六进制值(例如:)。实际上,来自“网络安全”调色板的颜色是理想的。


2
能否提供一些示例输入和/或链接到类似问题?
qw3n

2
不是答案,但是您可能会发现以下有用:将十六进制转换为整数,请使用parseInt(hexstr, 10)。要将整数转换为十六进制,请使用n.toString(16),其中n是整数。
克里斯蒂安·桑切斯

@ qw3n-示例输入:只是短而纯的旧文本字符串……例如“ Medicine”,“ Surgery”,“ Neurology”,“ General Practice”等。范围介于3到20个字符之间……找不到另一个,但是这里是Java问题:stackoverflow.com/questions/2464745 / ... @Daniel-谢谢。我需要坐下来,再认真考虑一下。可能会有用。
达拉格·恩赖特

Answers:


175

只需将Java从Compute hex颜色代码移植到Java 脚本中的任意字符串即可:

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);
Thymine

2
我正在将一堆音乐类型标签转换为背景色,这节省了我很多时间。
凯尔·佩内尔

我希望我可以将其转换为php。
Nimitz E.

6
例如,对于相似的字符串,我在使用几乎相同的颜色时会遇到一些问题: intToRGB(hashCode('hello1')) -> "3A019F" intToRGB(hashCode('hello2')) -> "3A01A0" 我通过为最终的哈希值添加乘法来增强代码:return 100 * hash;
SirWojtek

185

这是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
此代码与NoSQL自动生成的ID配合使用时效果非常好,对于同一用户,您的颜色每次都相同。
deviavir 2014年

我还需要alpha通道来确保十六进制代码的透明性。这有所帮助(在我的十六进制代码末尾为alpha通道添加了两个数字): gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
Husterknupp

@Tjorriemorrie因指出它是彩色而不是彩色而赞扬。是的,是的,它不是真正的话题,但对我来说很重要(实际上,最初键入时,我两次都将其拼写为“颜色”!)。谢谢。
Pryftan

有趣的是,在不同的浏览器/操作系统上,相同字符串的颜色是不同的-例如Chrome + Windows和Chrome + Android-我的电子邮件=>颜色一方面是蓝色,而另一方面是绿色。知道为什么吗?
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 2015年

2
分享解决方案的方法,您可以在其中决定颜色的色彩!
弗洛里安·鲍尔

@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种颜色,但我发现大多数人还是不能真正分辨出区别。我想您可以随时添加更多颜色。

尽管此代码使用了硬编码的颜色,但是至少可以保证在开发过程中确切地知道生产中的颜色之间有多少对比度。

颜色清单已从取消 答案中删除,还有其他具有更多颜色的列表。


首先有一种确定对比度的算法。我几年前用它写过东西(但是用C语言编写)。太多的事情要担心,反正这是一个古老的答案,但我想指出了一种确定对比度的方法。
Pryftan

7

我已打开对Please.js 的拉取请求该允许从哈希生成颜色。

您可以将字符串映射为如下颜色:

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

例如,"any string goes here"将返回为"#47291b"
"another!"返回为"#1f0c3d"


真的很酷,谢谢您的补充。嗨,您想根据像Google收件箱这样的名称生成带有字母的圆圈

当我看到这个答案时,我想,很完美,现在我必须考虑颜色架构,以免它生成非常随机的颜色,然后我阅读了Please.js make_color选项,它使我的脸上露出美丽的笑容。
panchicore

6

如果输入的差异不足以使简单的哈希使用整个色谱,则可以使用种子随机数生成器代替哈希函数。

我正在使用乔·弗里曼(Joe Freeman)的答案中的颜色编码器,以及大卫·鲍(David Bau)的种子随机数生成器

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 2014年

@kikito足够公平,可能我已经以某种方式扩展了原型(JQuery?)。无论如何,我已经编辑了该函数,因此它仅是javascript ...感谢您指出这一点。
estani 2014年

@kikito它是有效的ES6,尽管使用它会忽略跨浏览器的兼容性。
Patrick Roberts

5

使用hashCodeCristian Sanchez的答案hsl和现代javascript中的as ,您可以创建具有良好对比度的颜色选择器,如下所示:

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。

它可以很容易地扩展,以便种子是字符串中所有字符的XOR,而不仅仅是前两个。

受到David Crow的回答的启发:随机生成美观的调色板的算法

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


我必须说,这是一种非常奇怪的方式。这是一种作品,但可用的颜色很少。前两种颜色的XOR不区分顺序,因此只有字母的组合。我增加颜色数量的一个简单加法就是var seed = 0; 对于(input_str中的var i){种子^ = i; }
Gussoh

是的,这实际上取决于您要生成多少种颜色。我记得在这种情况下,我正在UI中创建不同的窗格,并且希望使用有限数量的颜色而不是彩虹:)
Robert Sharp,

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

这会产生很多非常暗的值。
兰登
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.