สร้างสีฐานสิบหกตามสตริงที่มี JavaScript


141

ผมต้องการสร้างฟังก์ชั่นที่จะยอมรับสตริงเก่า ๆ (โดยปกติจะเป็นคำเดียว) และจากที่ใดสร้างค่าฐานสิบหกระหว่าง#000000และ#FFFFFFดังนั้นฉันสามารถใช้มันเป็นสีสำหรับองค์ประกอบแบบ HTML

อาจเป็นแม้แต่ค่าเลขฐานสิบหกแบบย่อ (เช่น:) #FFFถ้ามันซับซ้อนน้อยกว่า ในความเป็นจริงสีจากจานสี 'ปลอดภัยเว็บ' จะเหมาะ


2
สามารถให้ตัวอย่างอินพุตและ / หรือลิงก์ไปยังคำถามที่คล้ายกันได้หรือไม่
qw3n

2
ไม่ได้คำตอบ แต่คุณอาจพบว่ามีประโยชน์ดังต่อไปนี้: parseInt(hexstr, 10)ในการแปลงเลขฐานสิบหกเป็นจำนวนเต็มใช้ ในการแปลงจำนวนเต็มเป็นเลขฐานสิบหกให้ใช้n.toString(16)โดยที่ n คือจำนวนเต็ม
Cristian Sanchez

@ qw3n - ตัวอย่างอินพุต: สั้น ๆ , สตริงข้อความธรรมดาแบบเก่า ... เช่น 'Medicine', 'Surgery', 'Neurology', 'General Practice' ฯลฯ ช่วงระหว่าง 3 ถึง 20 ตัวอักษร ... หาไม่เจอ อีกคำถามหนึ่ง แต่นี่คือคำถาม java: stackoverflow.com/questions/2464745/… @Daniel - ขอบคุณ ฉันต้องนั่งลงและจริงจังกับสิ่งนี้อีก อาจมีประโยชน์
Darragh Enright

คำตอบ:


176

เพียงแค่ย้ายไปที่ 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))

1
ที่ดี! ขอบคุณมันใช้งานได้ดี ฉันไม่รู้อะไรมากเกี่ยวกับตัวดำเนินการระดับบิตและสิ่งต่าง ๆ ดังนั้นความช่วยเหลือของคุณในการจัดวางมันจึงเป็นที่นิยม
Darragh Enright

จำเป็นต้องวางสตริง hex เช่น:("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
ฉันกำลังแปลงแท็กประเภทเพลงเป็นสีพื้นหลังและทำให้ฉันประหยัดเวลาได้มาก
Kyle Pennell

ฉันหวังว่าฉันสามารถแปลงเป็น 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 ที่สร้างขึ้นโดยอัตโนมัติสีของคุณจะเหมือนกันทุกครั้งสำหรับผู้ใช้เดียวกัน
deviavir

ฉันต้องการช่องอัลฟาเพื่อความโปร่งใสในรหัสฐานสิบหกของฉันด้วย สิ่งนี้ช่วยได้ (เพิ่มตัวเลขสองหลักสำหรับช่องอัลฟาที่ส่วนท้ายของรหัสเลข
Husterknupp

@Tjorriemorrie Upvoting เพื่อชี้ให้เห็นว่ามันเป็นสีและไม่ใช่สี ใช่ใช่มันไม่ได้อยู่ในหัวข้อ แต่เป็นสิ่งที่สำคัญสำหรับฉัน (อันที่จริงแล้วเมื่อพิมพ์มันในตอนแรกฉันสะกดมันเป็น 'สี' ทั้งสองครั้ง!) ขอบคุณ.
Pryftan

น่าสนใจว่าสีจะแตกต่างกันสำหรับสายอักขระเดียวกันบนเบราว์เซอร์ / oss ที่แตกต่างกัน - เช่น 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

2
ขอบคุณสำหรับการแบ่งปันวิธีแก้ปัญหาที่คุณสามารถตัดสินใจได้ว่าสีสันควรจะมีสีสันแค่ไหน!
Florian Bauer

@ Haykam ขอบคุณที่ทำให้มันเป็นตัวอย่าง!
Thymine

วิธีการนี้มีประโยชน์มากในการสร้างความสั่นสะเทือน / ความละเอียดอ่อนที่แอพของฉันต้องการ เลขฐานสิบหกสุ่มแตกต่างกันมากเกินไปในความอิ่มตัวและความสว่างที่จะเป็นประโยชน์ในสถานการณ์ส่วนใหญ่ ขอบคุณสำหรับสิ่งนี้!
simey.me

วิธีนี้จะให้สีที่น้อยเกินไปจะไม่ทำ
catamphetamine

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 สี แต่ฉันพบว่ามนุษย์ส่วนใหญ่ไม่สามารถบอกความแตกต่างได้หลังจากนั้น ฉันคิดว่าคุณสามารถเพิ่มสีได้เสมอ

ในขณะที่รหัสนี้ใช้สีที่มีการกำหนดรหัสอย่างเข้มงวดคุณอย่างน้อยรับประกันว่าจะทราบได้ในระหว่างการพัฒนาว่าคุณเห็นความแตกต่างระหว่างสีในการผลิตมากน้อยเพียงใด

รายการสีถูกยกขึ้นจากคำตอบ SO นี้มีรายการอื่นที่มีสีมากขึ้น


Fwiw มีอัลกอริทึมที่นั่นเพื่อกำหนดความคมชัด ฉันเขียนบางสิ่งกับมันเมื่อหลายปีก่อน (แต่ใน C) มากเกินไปที่จะกังวลเกี่ยวกับมันและมันเป็นคำตอบเก่า ๆ อยู่แล้ว แต่คิดว่าฉันจะชี้ให้เห็นว่ามีวิธีการกำหนดความคมชัด
Pryftan

7

ฉันได้เปิดคำขอดึงเพื่อPlease.jsที่อนุญาตให้สร้างสีจากแฮช

คุณสามารถแมปสตริงเป็นสีดังนี้:

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

ตัวอย่างเช่น"any string goes here"จะส่งกลับเป็น"#47291b"
และ"another!"ส่งกลับเป็น"#1f0c3d"


ขอบคุณมากสำหรับการเพิ่ม สวัสดีที่ต้องการสร้างแวดวงด้วยตัวอักษรตามชื่อในกล่องจดหมายของ Google ทำ :)
marcus7777

เมื่อฉันเห็นคำตอบนี้ฉันคิดว่าสมบูรณ์แบบตอนนี้ฉันต้องคิดถึงโครงร่างสีดังนั้นมันจึงไม่สร้างสีแบบสุ่มมากจากนั้นฉันอ่านเกี่ยวกับตัวเลือก make_color ของ Please.js และมันทำให้รอยยิ้มที่สวยงามบนใบหน้าของฉัน
panchicore

6

หากอินพุตของคุณไม่แตกต่างกันพอสำหรับแฮชธรรมดาที่จะใช้สเปกตรัมสีทั้งหมดคุณสามารถใช้ตัวสร้างตัวเลขสุ่มแบบ seeded แทนฟังก์ชันแฮช

ฉันใช้ coder สีจากคำตอบโจฟรีแมนและเมล็ดเครื่องกำเนิดไฟฟ้าจำนวนสุ่มเดวิด 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หลอกสุ่มฟังก์ชั่นจากที่นี่และบาง padding และคณิตศาสตร์จากตัวเอง

ฉันสงสัยว่าฟังก์ชั่นจะสร้างสีที่กระจายอย่างสม่ำเสมอแม้ว่ามันจะดูดีและทำในสิ่งที่ควรทำ


'0'.repeat(...)ไม่ถูกต้อง javascript
kikito

@ kikito ยุติธรรมพอฉันอาจจะมีต้นแบบที่ขยายออกไปอย่างใด (JQuery?) อย่างไรก็ตามฉันได้แก้ไขฟังก์ชั่นดังนั้นมันจึงเป็นจาวาสคริปต์เท่านั้น ... ขอบคุณที่ชี้ให้เห็น
estani

@kikito เป็น ES6 ที่ถูกต้อง แต่การใช้มันจะไม่สนใจความเข้ากันได้ของเบราว์เซอร์ข้าม
Patrick Roberts

5

ด้วยการใช้hashCodeคำตอบของ Cristian Sanchez กับhsljavascript ที่ทันสมัยคุณสามารถสร้างเครื่องมือเลือกสีที่มีความเปรียบต่างเช่นนี้:

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

รายการอยู่ที่นี่: https://gist.github.com/ro-sharp/49fd46a071a267d9e5dd


ฉันต้องบอกว่านี่เป็นวิธีที่แปลกจริงๆในการทำมัน มันเป็นงาน แต่ไม่มีสีให้เลือกมากมาย XOR ของสองสีแรกนั้นไม่มีความแตกต่างของคำสั่งดังนั้นจึงมีเพียงชุดของตัวอักษร การเพิ่มอย่างง่ายที่ฉันทำเพื่อเพิ่มจำนวนสีคือ var seed = 0; สำหรับ (var i ใน input_str) {seed ^ = i; }
Gussoh

ใช่มันขึ้นอยู่กับจำนวนสีที่คุณต้องการสร้าง ผมจำได้ว่าในกรณีนี้ผมกำลังสร้างบานหน้าต่างที่แตกต่างกันใน UI และต้องการในจำนวนที่ จำกัด ของสีมากกว่ารุ้ง :)
โรเบิร์ตชาร์ป

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

สิ่งนี้สร้างค่ามืดมาก
Langdon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.