【问题标题】:Map value to color scale将值映射到色标
【发布时间】:2013-10-13 04:02:48
【问题描述】:

我有一个值列表,应该用某种颜色绘制到地图上。 地图的绘制已经完成,但我需要找到一种方法将值 n 映射到表示其值的颜色。

到目前为止,我的一个示例和解决方案是根据minmax 对值进行规范化,然后将它们分配给十六进制颜色0 为最低值,255 为最高值。这当然将我的自我限制在灰度范围内。这是代码:

$color = ($value / $max) * 255    // (min is zero)

但是,如果值应该从蓝色变为红色,该怎么做呢? 有没有可以解决这个问题的通用库或工具?到目前为止,我还没有找到任何东西。

【问题讨论】:

  • 那是因为你为每个 RGB 设置颜色,只为红色和蓝色设置它。
  • 我会说将红色设置为$color,将蓝色设置为255 - $color
  • remyabel:我知道。乔治:这可行,但我想知道是否有更通用的方法。
  • @Rasmus 查看渐变或颜色插值。

标签: php colors


【解决方案1】:

可能有库可以做到这一点。然而,让我们对一般原则做一个简短的热身。一般来说,您有以下选择:

  1. 预定义的颜色索引,例如$coloridx=array(0=>'#FFFFFF',1=>'#FFEE00',...);
  2. 任何算法,例如线性渐变,基本上是所有三个 RGB 通道(R = 红色,G = 绿色,B = 蓝色)的基于迭代的自适应。
  3. 两者的结合,通常将任何复杂算法的结果放入颜色索引,然后从那里开始。

如果您在考虑中包含算法,您必须了解没有truefalse。这一切都取决于你想实现什么。在某些情况下,将绿色的变体渲染为n=0..10,然后在n>10 之外的所有内容中将红色变为黑色是有意义的。大写字母和乘数有助于设置重音符号。诸如此类。

实现线性渐变的一种方法是:

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

我更新了代码以添加 dechex,它会反馈给 cmets。

【讨论】:

  • 您的函数以 #{num1}{num1}{num1} 的形式返回值,其中 numX 部分是 十进制 整数值——这使得它们不能直接用作 CSS 颜色(我假设你尝试过通过在它们前面加上 #) 来实现。但这很容易解决,如果您使用 sprintf 和 %02x 来格式化值,那么也许您想在这方面调整您的代码。除此之外,很好的答案! +1
  • 对于任何试图完成上述工作的人,您都需要:
  • str_pad(dechex(intval((($ra*$iterationc)+($rz*$iterationdiff))/$iterationnr)),2,'0',STR_PAD_LEFT)
  • 或者@CBroe提到的这个:
  • 有一个有趣的在线工具可以生成硬编码的渐变步骤,甚至可以使用三种颜色:strangeplanet.fr/work/gradient-generator/index.php 这是我的预览:i.imgur.com/u9ILvSs.jpg
【解决方案2】:

颜色值是表示。数字颜色以及十六进制颜色。 “非灰度”颜色包含至少 2 个不同的信息:红色值、绿色值或蓝色值可能不同。对其表示执行操作会给出错误的结果。然后必须对每条信息执行“映射”。您需要提取红色、绿色和蓝色值,分别执行映射,然后构建结果颜色的表示。这是一个使用“最小颜色”的快速助手" 和 "max color",根据您需要使用的 "n" 值对红色、绿色和蓝色值进行映射,然后以十六进制字符串返回结果颜色。它也适用于任何颜色或灰度颜色.

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

只需将 2 种颜色指定为数值或十六进制字符串(不带哈希!),如下所示:

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

【讨论】:

    【解决方案3】:

    另一个答案非常有用。我决定使用 JS,因为它可以减少服务器负载。要求也发生了变化。条形必须在中间从红色变为白色,然后从白色变为黄色。如果值为 0,它应该是黑色的。这是我的代码,适用于遇到类似情况的任何人。

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

    【讨论】:

      【解决方案4】:

      这里有I2UI

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

      有一个颜色范围:从“灰色”到“绿色”。具有最低比率值的跨度元素获得“灰色”颜色,具有最大比率的元素获得“绿色”颜色。

      因此,边缘之间的跨度得到与其比率成正比的颜色。

      另外,在加载前一个 HTML 之后调用 JavaScript i2.emph()。

      demo

      【讨论】:

      【解决方案5】:

      这是一个只有一个功能的代码,用于将任何给定范围(比如 [0,20])中的任何数字转换为特定颜色,其中 0 是红色,10 是黄色,20 是绿色。您可以使用任何颜色,甚至可以使用 4 种颜色的组合,所以它是红 - 黄 - 绿 - 蓝。

      查看 gist 文件的末尾,这里使用了这个函数。

      代码要点: Click here

      【讨论】:

        猜你喜欢
        • 2012-04-02
        • 2010-10-04
        • 1970-01-01
        • 2020-08-09
        • 1970-01-01
        • 2018-06-21
        • 1970-01-01
        • 2016-04-06
        • 2019-11-26
        相关资源
        最近更新 更多