将数值映射到颜色比例尺

6
我有一个值列表,需要将其绘制到地图上并着色。已经完成了地图的绘制,但我需要找出一种将值n映射到代表其值的颜色的方法。
一个例子和我的解决方案是基于最小值和最大值对值进行标准化,然后将它们分配给十六进制颜色0表示最低,255表示最高。这当然限制了我只使用灰度。以下是代码:
$color = ($value / $max) * 255    // (min is zero)

如果需要的值从蓝色到红色,该怎么做呢?是否有常见的库或工具可以解决这个问题?迄今为止,我还没有找到任何解决方案。


这是因为你正在为每个RGB设置颜色,只需为红色和蓝色的那些设置颜色即可。 - user1508519
我建议将红色设置为 $color,蓝色设置为 255 - $color - George Marques
remyabel: 我知道。 George: 那可能行,但我想知道是否有更通用的方法。 - CodeTower
@Rasmus 请研究一下渐变或颜色插值。 - user1508519
5个回答

5

可能有一些库可以完成这个操作,但是让我们先对一般原则进行简单介绍。一般而言,您有以下几种选择:

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

如果您需要考虑算法,则必须了解没有什么是“真”或“假”的。这完全取决于您希望实现什么。有时将绿色的变化呈现为 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,并且根据评论进行了反馈。


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

1
颜色值是表示的。数字颜色和十六进制颜色都是如此。一个“非灰度”颜色至少包含两个不同的信息:红色值、绿色值或蓝色值可能不同。在其表示上执行操作会得到错误的结果。然后必须对每个信息片段执行“映射”。您需要提取红色、绿色和蓝色值,分别执行映射,然后构建结果颜色的表示形式。这里有一个快速帮助程序,使用“最小颜色”和“最大颜色”,根据您需要处理的“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>';
    }

0

这个可以使用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>

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

因此,处于边缘之间的span将获得与其比率成正比的颜色。

此外,在先前的HTML加载完后调用JavaScript i2.emph()。

请参见演示


链接已失效。不过在Github上有一些5年前的代码,链接为https://github.com/verezh/i2ui。 - The Godfather

0

另一个答案非常有用。我决定使用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);
}

0

这是一个仅包含一个函数的代码,可以将任何给定范围内的数字(比如[0,20])转换为特定颜色,其中0为红色,10为黄色,20为绿色。您可以使用任何颜色,甚至可以使用4种颜色的组合,例如红-黄-绿-蓝。

请查看gist文件的末尾,了解此函数的用法。

Demo

包含代码的要点: 点击这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接