我想创建一个函数,它将接受任何旧字符串(通常是一个单词),并从中以某种方式生成一个十六进制值在#000000和#FFFFFF之间,所以我可以使用它作为HTML元素的颜色。

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


当前回答

在看了相当密集的代码和相当古老的答案之后,我想我应该从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>

这应该比手动生成散列快得多,并且还提供了一种定义饱和度和亮度的方法,以防你不想要太平或太亮或太暗的颜色(例如,如果你想在这些颜色上写文本)。

其他回答

我发现随机生成的颜色往往没有足够的对比度来满足我的口味。我发现解决这个问题最简单的方法是预先填充一个非常不同的颜色列表。对于每个新字符串,分配列表中的下一个颜色:

// 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答案中提取的,还有其他更多颜色的列表。

我的代码是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;
    }

我已经打开了一个pull request to Please.js,它允许从散列中生成颜色。

你可以像这样将字符串映射到一个颜色:

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

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

我在一行中将其转换为Python

import hashlib

hash = hashlib.sha1(b'user@email.com').hexdigest()

print("#" + hash[0:6])

下面是我提出的一个解决方案,根据输入字符串生成美观的粉彩颜色。它使用字符串的前两个字符作为随机种子,然后基于该种子生成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