Create a hexadecimal colour based on a string with JavaScript

后端 未结 13 872
旧时难觅i
旧时难觅i 2020-11-30 17:15

I want to create a function that will accept any old string (will usually be a single word) and from that somehow generate a hexadecimal value between #000000

相关标签:
13条回答
  • 2020-11-30 17:54

    Here's a solution I came up with to generate aesthetically pleasing pastel colours based on an input string. It uses the first two chars of the string as a random seed, then generates R/G/B based on that seed.

    It could be easily extended so that the seed is the XOR of all chars in the string, rather than just the first two.

    Inspired by David Crow's answer here: Algorithm to randomly generate an aesthetically-pleasing color palette

    //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 is here: https://gist.github.com/ro-sharp/49fd46a071a267d9e5dd

    0 讨论(0)
  • 2020-11-30 17:54

    Here is another try:

    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;
    }
    
    0 讨论(0)
  • 2020-11-30 18:02

    I find that generating random colors tends to create colors that do not have enough contrast for my taste. The easiest way I have found to get around that is to pre-populate a list of very different colors. For every new string, assign the next color in the list:

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

    While this has a limit to only 64 colors, I find most humans can't really tell the difference after that anyway. I suppose you could always add more colors.

    While this code uses hard-coded colors, you are at least guaranteed to know during development exactly how much contrast you will see between colors in production.

    Color list has been lifted from this SO answer, there are other lists with more colors.

    0 讨论(0)
  • 2020-11-30 18:02

    If your inputs are not different enough for a simple hash to use the entire color spectrum, you can use a seeded random number generator instead of a hash function.

    I'm using the color coder from Joe Freeman's answer, and David Bau's seeded random number generator.

    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;
    }
    
    0 讨论(0)
  • 2020-11-30 18:03

    Here's an adaptation of CD Sanchez' answer that consistently returns a 6-digit colour code:

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

    Usage:

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

    Example:

    http://jsfiddle.net/sUK45/

    (An alternative/simpler solution might involve returning an 'rgb(...)'-style colour code.)

    0 讨论(0)
  • 2020-11-30 18:06

    I wanted similar richness in colors for HTML elements, I was surprised to find that CSS now supports hsl() colors, so a full solution for me is below:

    Also see How to automatically generate N "distinct" colors? for more alternatives more similar to this.

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

    In HSL its Hue, Saturation, Lightness. So the hue between 0-359 will get all colors, saturation is how rich you want the color, 100% works for me. And Lightness determines the deepness, 50% is normal, 25% is dark colors, 75% is pastel. I have 30% because it fit with my color scheme best.

    0 讨论(0)
提交回复
热议问题