我想创建一个函数,它将接受任何旧字符串(通常是一个单词),并从中以某种方式生成一个十六进制值在#000000和#FFFFFF之间,所以我可以使用它作为HTML元素的颜色。
如果不那么复杂的话,甚至可能是一个简化的十六进制值(例如:#FFF)。事实上,“网络安全”调色板中的颜色是最理想的。
我想创建一个函数,它将接受任何旧字符串(通常是一个单词),并从中以某种方式生成一个十六进制值在#000000和#FFFFFF之间,所以我可以使用它作为HTML元素的颜色。
如果不那么复杂的话,甚至可能是一个简化的十六进制值(例如:#FFF)。事实上,“网络安全”调色板中的颜色是最理想的。
只是将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))
以下是对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(…)'风格的颜色代码。)
如果您的输入差异不足以让一个简单的哈希使用整个颜色光谱,您可以使用一个种子随机数生成器而不是哈希函数。
我用的是乔·弗里曼的答案中的颜色编码器,还有大卫·鲍的种子随机数生成器。
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;
}
还有一个随机颜色的解决方案:
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伪随机函数,以及我自己的一些填充和数学。
我怀疑该函数产生均匀分布的颜色,尽管它看起来很好,并做了它应该做的事情。
我想要类似丰富的HTML元素的颜色,我惊讶地发现CSS现在支持hsl()颜色,所以一个完整的解决方案如下:
另参见如何自动生成N“不同”的颜色?更多类似的选择。
编辑:根据@zei的版本更新(美式拼写)
var stringToColor = (string, saturation = 100, lightness = 75) => { let hash = 0; for (let i = 0; i < string.length; i++) { hash = string.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } return `hsl(${(hash % 360)}, ${saturation}%, ${lightness}%)`; } // For the sample on stackoverflow function colorByHashCode(value) { return "<span style='color:" + stringToColor(value) + "'>" + value + "</span>"; } 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%,因为它最适合我的配色方案。
下面是另一个尝试:
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;
}
我已经打开了一个pull request to Please.js,它允许从散列中生成颜色。
你可以像这样将字符串映射到一个颜色:
const color = Please.make_color({
from_hash: "any string goes here"
});
例如,"any string goes here"将返回"#47291b" “another!”返回为“#1f0c3d”
我发现随机生成的颜色往往没有足够的对比度来满足我的口味。我发现解决这个问题最简单的方法是预先填充一个非常不同的颜色列表。对于每个新字符串,分配列表中的下一个颜色:
// 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答案中提取的,还有其他更多颜色的列表。
下面是我提出的一个解决方案,根据输入字符串生成美观的粉彩颜色。它使用字符串的前两个字符作为随机种子,然后基于该种子生成R/G/B。
它可以很容易地扩展,以便种子是字符串中所有字符的异或,而不仅仅是前两个字符。
灵感来自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
这个函数很有用。这是一个改编,相当长的执行这个repo ..
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('')}`;
}
使用hashCode,就像Cristian Sanchez用hsl和现代javascript回答的那样,你可以创建一个具有良好对比度的颜色选择器,如下所示:
函数hashCode(str) { 设hash = 0; For (var I = 0;I < str.length;我+ +){ hash = str.charCodeAt(i) + ((hash << 5) - hash); } 返回哈希; } 函数pickColor(str) { 返回' hsl(${hashCode(str) % 360}, 100%, 80%) '; } one.style.backgroundColor = pickColor(one.innerText) two.style.backgroundColor = pickColor(two.innerText) div { 填充:10 px; } < div id = " 1 " > < / div >一 < div id = "两个“>两个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>
我的代码是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;
}
你真正需要的是一个好的哈希函数。在节点上,我只用
const crypto = require('crypto');
function strToColor(str) {
return '#' + crypto.createHash('md5').update(str).digest('hex').substr(0, 6);
}
这是我2021年的版本,带有还原功能和HSL颜色。
function getBackgroundColor(stringInput) {
let stringUniqueHash = [...stringInput].reduce((acc, char) => {
return char.charCodeAt(0) + ((acc << 5) - acc);
}, 0);
return `hsl(${stringUniqueHash % 360}, 95%, 35%)`;
}
在看了相当密集的代码和相当古老的答案之后,我想我应该从2021年的角度来回顾这个问题,只是为了好玩,希望对任何人都有用。现在有了HSL颜色模型和加密API在几乎所有浏览器(当然除了IE)中实现,它可以像这样简单地解决:
async function getColor(text, minLightness = 40, maxLightness = 80, minSaturation = 30, maxSaturation = 100) { let hash = await window.crypto.subtle.digest("SHA-1", new TextEncoder().encode(text)); hash = new Uint8Array(hash).join("").slice(16); return "hsl(" + (hash % 360) + ", " + (hash % (maxSaturation - minSaturation) + minSaturation) + "%, " + (hash % (maxLightness - minLightness) + minLightness) + "%)"; } function generateColor() { getColor(document.getElementById("text-input").value).then(color => document.querySelector(".swatch").style.backgroundColor = color); } input { padding: 5px; } .swatch { margin-left: 10px; width: 28px; height: 28px; background-color: white; border: 1px solid gray; } .flex { display: flex; } <html> <body> <div class="flex"> <form> <input id="text-input" type="text" onInput="generateColor()" placeholder="Type here"></input> </form> <div class="swatch"></div> </div> </body> </html>
这应该比手动生成散列快得多,并且还提供了一种定义饱和度和亮度的方法,以防你不想要太平或太亮或太暗的颜色(例如,如果你想在这些颜色上写文本)。
Javascript解决方案受到Aslam的解决方案的启发,但返回十六进制颜色代码的颜色
/**
*
* @param {String} - stringInput - 'xyz'
* @returns {String} - color in hex color code - '#ae6204'
*/
function getBackgroundColor(stringInput) {
const h = [...stringInput].reduce((acc, char) => {
return char.charCodeAt(0) + ((acc << 5) - acc);
}, 0);
const s = 95, l = 35 / 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0'); // convert to Hex and prefix "0" if needed
};
return `#${f(0)}${f(8)}${f(4)}`;
}
我在一行中将其转换为Python
import hashlib
hash = hashlib.sha1(b'user@email.com').hexdigest()
print("#" + hash[0: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;}
为了找到合适的颜色,你可以使用
function lightOrDark(color) {
// Check the format of the color, HEX or RGB?
if (color.match(/^rgb/)) {
// If HEX --> store the red, green, blue values in separate variables
color = color.match(
/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/,
);
var r = color[1];
var g = color[2];
var b = color[3];
} else {
// If RGB --> Convert it to HEX: http://gist.github.com/983661
color = +(
'0x' + color.slice(1).replace(color.length < 5 && /./g, '$&$&')
);
r = color >> 16;
g = (color >> 8) & 255;
b = color & 255;
}
// HSP equation from http://alienryderflex.com/hsp.html
var hsp = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b));
// Using the HSP value, determine whether the color is light or dark
if (hsp > 127.5) {
return 'light';
} else {
return 'dark';
}
}
2023版本普通和简单的TypeScript箭头函数,返回HSL颜色。
const stringToColor = (value: string) => {
let hash = 0;
for (let i = 0; i < value.length; i++) {
hash = value.charCodeAt(i) + ((hash << 5) - hash);
}
return `hsl(${hash % 360}, 85%, 35%)`;
};