Tạo màu thập lục phân dựa trên chuỗi bằng JavaScript


141

Tôi muốn tạo một hàm sẽ chấp nhận bất kỳ chuỗi cũ nào (thường sẽ là một từ đơn) và từ đó bằng cách nào đó tạo ra một giá trị thập lục phân giữa #000000#FFFFFF, vì vậy tôi có thể sử dụng nó làm màu cho một phần tử HTML.

Thậm chí có thể là một giá trị hex tốc ký (ví dụ #FFF:) nếu điều đó ít phức tạp hơn. Trên thực tế, một màu từ bảng màu 'an toàn web' sẽ là lý tưởng.


2
Có thể cung cấp một số đầu vào mẫu và / hoặc liên kết đến các câu hỏi tương tự?
qw3n

2
Không phải là một câu trả lời, nhưng bạn có thể thấy hữu ích sau: Để chuyển đổi một hệ thập lục phân thành số nguyên, hãy sử dụng parseInt(hexstr, 10). Để chuyển đổi một số nguyên thành thập lục phân, sử dụng n.toString(16), trong đó n là một số nguyên.
Cristian Sanchez

@ qw3n - đầu vào mẫu: chỉ là các chuỗi văn bản cũ, ngắn, đơn giản ... như 'Thuốc', 'Phẫu thuật', 'Thần kinh', 'Thực hành chung', v.v. Khác nhau giữa 3 và nói, 20 ký tự ... không thể tìm thấy một câu hỏi khác nhưng đây là câu hỏi java: stackoverflow.com/questions/2464745/ Khăn @Daniel - Cảm ơn. Tôi cần phải ngồi xuống và có một nghiêm túc khác ở đây. có thể hữu ích
Darragh Enright

Câu trả lời:


176

Chỉ cần chuyển qua Java từ tính toán mã màu hex cho một chuỗi tùy ý sang 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;
}

Để chuyển đổi bạn sẽ làm:

intToRGB(hashCode(your_string))

1
tuyệt quá! cảm ơn, điều này hoạt động tốt Tôi không biết nhiều về các toán tử bitwise và các công cụ để sự giúp đỡ của bạn chuyển nó qua được đánh giá cao.
Darragh Enright

Nó cần phải đệm các chuỗi hex, chẳng hạn như:("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
Tôi đang chuyển đổi một loạt các thẻ thể loại âm nhạc sang màu nền và điều này giúp tôi tiết kiệm rất nhiều thời gian.
Kyle Pennell

Tôi ước tôi có thể chuyển đổi nó thành php.
Nimitz E.

6
Tôi có một số vấn đề với các màu gần như giống nhau cho các chuỗi tương tự, ví dụ: intToRGB(hashCode('hello1')) -> "3A019F" intToRGB(hashCode('hello2')) -> "3A01A0" Và tôi tăng cường mã của bạn bằng cách thêm phép nhân cho giá trị băm cuối cùng:return 100 * hash;
SirWojtek

185

Đây là bản phóng tác của câu trả lời của CD Sanchez, luôn trả về mã màu gồm 6 chữ số:

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

Sử dụng:

stringToColour("greenish");
// -> #9bc63b

Thí dụ:

http://jsfiddle.net/sUK45/

(Một giải pháp thay thế / đơn giản hơn có thể liên quan đến việc trả lại mã màu theo kiểu 'rgb (...)'.)


3
Mã này hoạt động tuyệt vời khi kết hợp với ID được tạo tự động của NoQuery, màu của bạn sẽ giống nhau mỗi lần cho cùng một người dùng.
deviavir

Tôi cũng cần kênh alpha để minh bạch trong mã hex của mình. Điều này đã giúp (thêm hai chữ số cho kênh alpha ở cuối mã hex của tôi): gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
Husterknupp

@Tjorriemorrie Upvote vì đã chỉ ra rằng đó là màu chứ không phải màu. Vâng, vâng, nó không thực sự về chủ đề nhưng nó là thứ gì đó quan trọng đối với tôi (thực tế khi gõ nó ban đầu tôi đã đánh vần là "màu" cả hai lần!). Cảm ơn bạn.
Pryftan

Điều thú vị là màu sắc khác nhau cho cùng một chuỗi trên các trình duyệt / oss khác nhau - ví dụ: Chrome + Windows và Chrome + Android - e-mail của tôi => màu là màu xanh lam trên một màu và màu xanh lục khác. Bất cứ ý tưởng tại sao?
avenmore

43

Tôi muốn sự phong phú tương tự về màu sắc cho các yếu tố HTML, tôi đã ngạc nhiên khi thấy rằng CSS hiện hỗ trợ màu hsl (), vì vậy một giải pháp đầy đủ cho tôi là dưới đây:

Xem thêm Cách tự động tạo N "màu" khác biệt? cho nhiều lựa chọn thay thế tương tự như thế này.

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

Trong HSL, Huế, Saturation, Lightness. Vì vậy, màu sắc trong khoảng 0-359 sẽ nhận được tất cả các màu, độ bão hòa là mức độ bạn muốn màu sắc phong phú, 100% hoạt động với tôi. Và Độ sáng quyết định độ sâu, 50% là bình thường, 25% là màu tối, 75% là màu pastel. Tôi có 30% vì nó phù hợp nhất với bảng màu của tôi.


3
Một giải pháp rất đa năng.
MastaBaba

2
Thx để chia sẻ một giải pháp, nơi bạn có thể quyết định màu sắc nên như thế nào!
Florian Bauer

@haykam Cảm ơn bạn đã biến nó thành một đoạn trích!
Thymine

Cách tiếp cận này thực sự hữu ích để mang lại độ rung / tinh tế mong muốn mà ứng dụng của tôi cần. Một Hex ngẫu nhiên thay đổi quá nhiều về độ bão hòa và độ sáng sẽ hữu ích trong hầu hết các tình huống. Cảm ơn vì điều đó!
simey.me 18/03/19

Giải pháp này trả về quá ít màu sắc, sẽ không làm.
catamphetamine

9

Tôi thấy rằng việc tạo ra các màu ngẫu nhiên có xu hướng tạo ra các màu không có đủ độ tương phản theo sở thích của tôi. Cách dễ nhất mà tôi đã tìm thấy để giải quyết vấn đề đó là điền trước một danh sách các màu rất khác nhau. Đối với mỗi chuỗi mới , chỉ định màu tiếp theo trong danh sách:

// 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");

Mặc dù điều này có giới hạn chỉ 64 màu, nhưng tôi thấy hầu hết mọi người thực sự không thể biết được sự khác biệt sau đó. Tôi cho rằng bạn luôn có thể thêm nhiều màu sắc hơn.

Mặc dù mã này sử dụng các màu được mã hóa cứng, nhưng ít nhất bạn được đảm bảo để biết trong quá trình phát triển chính xác mức độ tương phản bạn sẽ thấy giữa các màu trong sản xuất.

Danh sách màu đã được nâng lên từ câu trả lời SO này , có những danh sách khác có nhiều màu hơn.


Fwiw có một thuật toán ngoài đó để xác định độ tương phản. Tôi đã viết một cái gì đó với nó nhiều năm trước (nhưng bằng C). Quá nhiều thứ để lo lắng về nó và dù sao đó cũng là một câu trả lời cũ nhưng tôi đã chỉ ra rằng có một cách để xác định độ tương phản.
Pryftan

7

Tôi đã mở một yêu cầu kéo tới Please.js cho phép tạo màu từ hàm băm.

Bạn có thể ánh xạ chuỗi thành một màu như vậy:

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

Ví dụ, "any string goes here"sẽ trả về "#47291b"
"another!"trả về"#1f0c3d"


Thực sự cảm ơn vì đã thêm nó. Xin chào, muốn tạo vòng kết nối với các chữ cái dựa trên tên như hộp thư đến của Google không :)
marcus7777

Khi tôi thấy câu trả lời này, tôi nghĩ, thật hoàn hảo, bây giờ tôi phải suy nghĩ về lược đồ màu để nó không tạo ra các màu rất ngẫu nhiên, sau đó tôi đọc về các tùy chọn make_color của Make.js và nó nở một nụ cười đẹp.
panchicore

6

Nếu đầu vào của bạn không đủ khác nhau để một hàm băm đơn giản sử dụng toàn bộ phổ màu, bạn có thể sử dụng trình tạo số ngẫu nhiên được tạo hạt thay vì hàm băm.

Tôi đang sử dụng bộ mã màu từ câu trả lời của Joe Freeman và trình tạo số ngẫu nhiên có hạt giống của 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

Một giải pháp khác cho màu sắc ngẫu nhiên:

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

Đó là một hỗn hợp của những thứ làm công việc cho tôi. Tôi đã sử dụng hàm JFreeman Hash (cũng là một câu trả lời trong chuỗi này) và hàm ngẫu nhiên giả Asykäri từ đây và một số phần đệm và toán học từ chính tôi.

Tôi nghi ngờ chức năng tạo ra màu sắc phân bố đồng đều, mặc dù nó trông đẹp và làm những gì nó nên làm.


'0'.repeat(...)javascript không hợp lệ
kikito

@kikito đủ công bằng, có lẽ tôi đã mở rộng nguyên mẫu bằng cách nào đó (JQuery?). Dù sao, tôi đã chỉnh sửa chức năng để chỉ javascript ... cảm ơn vì đã chỉ ra điều đó.
estani

@kikito đó là ES6 hợp lệ, mặc dù sử dụng nó sẽ bỏ qua khả năng tương thích trình duyệt chéo.
Patrick Roberts

5

Sử dụng hashCodenhư trong câu trả lời của Cristian Sanchez hslvà javascript hiện đại, bạn có thể tạo một công cụ chọn màu với độ tương phản tốt như thế này:

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>

Vì đó là hsl, bạn có thể điều chỉnh độ chói để có được độ tương phản mà bạn đang tìm kiếm.

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

Đây là một giải pháp tôi đã đưa ra để tạo ra các màu pastel có tính thẩm mỹ dựa trên chuỗi đầu vào. Nó sử dụng hai ký tự đầu tiên của chuỗi làm hạt giống ngẫu nhiên, sau đó tạo R / G / B dựa trên hạt giống đó.

Nó có thể dễ dàng được mở rộng để hạt giống là XOR của tất cả các ký tự trong chuỗi, thay vì chỉ hai ký tự đầu tiên.

Lấy cảm hứng từ câu trả lời của David Crow tại đây: Thuật toán tạo ngẫu nhiên một bảng màu thẩm mỹ

//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 có tại đây: https://gist.github.com/ro-sharp/49fd46a071a267d9e5dd


Tôi phải nói rằng đây là một cách thực sự kỳ quặc. Đó là loại công việc nhưng không có nhiều màu sắc có sẵn. XOR của hai màu đầu tiên không phân biệt thứ tự nên chỉ có sự kết hợp của các chữ cái. Một bổ sung đơn giản tôi đã làm để tăng số lượng màu là var seed = 0; for (var i in input_str) {seed ^ = i; }
Gussoh

Vâng, nó thực sự phụ thuộc vào số lượng màu bạn muốn tạo. Tôi nhớ lại trong trường hợp này, tôi đã tạo ra các khung khác nhau trong giao diện người dùng và muốn số lượng màu hạn chế thay vì cầu vồng :)
Robert Sharp

1

Đây là một thử khác:

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

Tất cả những gì bạn thực sự cần là một hàm băm tốt. Trên nút, tôi chỉ sử dụng

const crypto = require('crypto');
function strToColor(str) {
    return '#' + crypto.createHash('md5').update(str).digest('hex').substr(0, 6);
}

0

Tôi chuyển đổi cái này cho Java.

Xe tăng cho tất cả.

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

Chức năng này thực hiện các mẹo. Đó là một sự thích ứng của điều này, thực hiện khá lâu hơn repo này ..

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

Điều này tạo ra rất nhiều giá trị rất tối.
Langdon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.