Map value to color scale

后端 未结 5 768
执念已碎
执念已碎 2021-01-18 11:13

I have a list of values which should be plotted to a map with a certain color. The plotting to the map is already done, but I need to figure out a way to map the value

相关标签:
5条回答
  • 2021-01-18 11:23

    Colors values are representations. Numeric colors as well as hexadecimal colors. A "not grayscale" color contains at least 2 different informations: Red value, green value or blue values may be different. Performing operation on its representation gives wrong result. The 'Mapping" must then be performed on each pieces of information. You need to extract red, green and blue values, perform the mapping seperatly, then build the representation of the result color. Here is a quick helper that use a "min color" and "max color", performs mapping on red, green and blue values, according to the "n" value you need to work with, then return the result color in hexadecimal string. It works for any colors or gray scale color as well.

    function linear_color($from, $to, $ratio) {
            // normalize ralio
            $ratio = $ratio<0?0:($ratio>1?1:$ratio);
            // unsure colors are numeric values
            if(!is_numeric($from))$from=hexdec($from);
            if(!is_numeric($to))$to=hexdec($to);
    
            $rf = 0xFF & ($from >> 0x10);
            $gf = 0xFF & ($from >> 0x8);
            $bf = 0xFF & $from;
            $rt = 0xFF & ($to >> 0x10);
            $gt = 0xFF & ($to >> 0x8);
            $bt = 0xFF & $to;
            return str_pad( dechex(($bf + (($bt-$bf)*$ratio)) + ($gf + (($gt-$gf)*$ratio) << 0x8) + ($rf + (($rt-$rf)*$ratio) << 0x10)), 6,'0',STR_PAD_LEFT);
    }
    

    Just specify 2 colors as numeric value or hexadecimal string (without hash!) like this :

    $color_from = hexdec('c2c2c2');
    $color_to = hexdec('1eb02b');
    for($i=-0.2; $i<=1.3; $i+=0.04){
            echo '<div style="background-color: #';
            echo linear_color($color_from, $color_to, $i);
            echo '">';
            echo 'Result color when n = <strong>'.$i.'</strong>';
            echo '</div>';
        }
    
    0 讨论(0)
  • 2021-01-18 11:34

    The other answer was very usefull. I decided to use JS as it reduces server load. The requirements also changed. The bar has to go from Red to white in the middle and then from white to yellow. And if the value is 0 it should be black. Here is my code for anyone who ever encounters a similar situation.

    var normalize_base = 2*255;
    var no_con_color = "black";
    
    function decimalToHex(d, padding) {
        var hex = Number(d).toString(16);
        padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding;
    
        while (hex.length < padding) {
            hex = "0" + hex;
    }
    
        return hex;
    }
    
    function normalize(max, min, value)
    {
         var normalized = (value - min) / (max - min) ;
         return Math.floor(normalized * normalize_base);
    }
    
    function value2Color(value)
    {
        if(value <= 0 || value == undefined)
        {
            return no_con_color;
        }
        var g = 0;
        var b = 0;
        var r = 0;
        if(value < 255)
        {
            r = 255;
            g = value;
            b = value;
        } else {
            r = (2*255) - value;
            g = 255;
            b = (2*255) - value;
        }  
    
        return "#" + decimalToHex(r) + decimalToHex(g) +  decimalToHex(b);
    }
    
    0 讨论(0)
  • 2021-01-18 11:37

    This is one-function-only code to convert any number from any given range (let's say [0,20]) to particular color where 0 is red, 10 is yellow, 20 is green. You can use any colors and even use combination of 4 colors, so it's red - yellow - green - blue.

    See the end of the gist file, where this function is used.

    Gist with the code: Click here

    0 讨论(0)
  • 2021-01-18 11:40

    There might be libs to do that. However let's get a short warm up into the general principles. In general you have following options:

    1. A predefined color index, e.g. $coloridx=array(0=>'#FFFFFF',1=>'#FFEE00',...);
    2. Any algorithm, e.g. linear gradient, which is basically an iterations based adaption of all three RGB channels (R = red, G = green, B = blue).
    3. A combination of both, which usually puts the result of any complex algorithm to the color index and then goes from there.

    If you include algorithms in your considerations you must understand that there is no true or false. It all depends on what you would like to implement. There might be occasions where it makes sense to render variations of green into n=0..10 and then have red to black in everything beyond n>10. Caps and multipliers help to set accents. Things like that.

    One way of implementing a linear gradient would be:

    function lineargradient($ra,$ga,$ba,$rz,$gz,$bz,$iterationnr) {
      $colorindex = array();
      for($iterationc=1; $iterationc<=$iterationnr; $iterationc++) {
         $iterationdiff = $iterationnr-$iterationc;
         $colorindex[] = '#'.
            dechex(intval((($ra*$iterationc)+($rz*$iterationdiff))/$iterationnr)).
            dechex(intval((($ga*$iterationc)+($gz*$iterationdiff))/$iterationnr)).
            dechex(intval((($ba*$iterationc)+($bz*$iterationdiff))/$iterationnr));
      }
      return $colorindex;
    }
    
    $colorindex = lineargradient(
      100, 0, 0,   // rgb of the start color
      0, 255, 255, // rgb of the end color
      256          // number of colors in your linear gradient
    );
    
    $color = $colorindex[$value];
    

    I UPDATED the code to add dechex, which feeds back on the comments.

    0 讨论(0)
  • 2021-01-18 11:49

    There is I2UI for this.

    <div data-i2="color:['#404040','#00FF21']">
        <span data-i2="rate:1">A</span>
        <span data-i2="rate:2">B</span>
        <span data-i2="rate:3">C</span>
        <span data-i2="rate:4">D</span>
        <span data-i2="rate:5">E</span>
    </div>
    

    There is a color range: from "Gray" - to "Green". The span element that has lowest rate value get the "Gray" color, the element with the biggest rate get "Green" color.

    Thus, the span that are between edges get the color that has direct ratio to its rate.

    Also, call JavaScript i2.emph() after the previous HTML have been loaded.

    See demo

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