使用 javascript 计算颜色值 (r,g,b)

Calculating color value (r,g,b) using javascript

我有 x 个包含速度值的数组。

数值在m/s中,不知道有多少,有多大。我需要创建一个函数来决定使用什么颜色。

我的想法是找到数组的 maxmin 值(速度),因为我知道这些值都可以被 0.25 整除,所以我想计算可能的数量"steps" 通过 var steps = (max - min) / 0.25

因为我有 RGB 光谱,所以我想我可以通过某种方式计算出要使用的值,但我根本不知道该怎么做。

我想做的是让慢速变红,中速变绿,快变蓝。

例如我有一个数组:

speeds = [0.5, 0.5, 0.75, 1.25, 0.50, 0.75, 1.00, 4.00, 4.50, 8.00, 7.50, 8.50, 6.50, 6.00, 5.00, 5.25, 4.75, 4.00, 3.25, 2.50, 1.25, 0.00]

现在,对于我拥有的每个值,我想计算一种颜色,其中最大值越大,颜色越浓(在蓝色光谱中 - 类似于 (0, 0, 255)),而较小的值它们越低,就越强烈(在红色光谱中 - (255, 0, 0))。对于中间值,我认为如果绿色 (0, 255, 0) 完全位于中间,它们可以更加强烈,然后根据它们倾向于哪一侧添加一点红色或蓝色。

我试图寻找一个可以为我做这件事的插件,但我找不到这样的插件,我也尝试用谷歌搜索来做这件事,但没有任何运气。

如果您不反对使用库,您可以查看 D3.js,特别是创建自定义比例的实用程序。这个 can be found here

的一个例子

例子

您需要使用速度数组 domain 和颜色作为输出来设置色标 range:

let colors = d3.scale.linear().domain([0, Math.max(...speeds)])
  .interpolate(d3.interpolateHcl)
  .range([d3.rgb('#FF0000'), d3.rgb('#0000FF')]);

colors 现在是一个函数,给定一个索引作为输入,将输出一种颜色。设置好后,循环遍历speeds数组得到对应的颜色:

for (let i = 0; i < speeds.length; i++) {
  // colors(i)
}
var min...,max...;
var mid=(min+max)/2;

speeds.foreach(function(x,idx){
  var r,g,b;
  if(x<mid){
    b=0;
    g=255*(x-min)/(mid-min);
    r=255-g;
  }else{
    r=0;
    g=255*(max-x)/(max-mid);
    b=255-g;
  }
  // do something with r-g-b here.
});

思路是这样的,写完后费劲脑筋去验证。我认为现在是正确的红色->绿色->蓝色2段渐变。

超过 2-3 个渐变段,我真的会创建一个调色板。

var r=[];g=[];b=[];
// black-red
for(var i=0;i<256;i++){
    r.push(i);
    g.push(0);
    b.push(0);
}
// red-green
for(var i=1;i<256;i++){
    r.push(255-i);
    g.push(i);
    b.push(0);
}
// green-blue
for(var i=1;i<256;i++){
    r.push(0);
    g.push(255-i);
    b.push(i);
}
// blue-white
for(var i=1;i<256;i++){
    r.push(i);
    g.push(i);
    b.push(255);
}

那么你有一个包含 1021 个元素的调色板,索引是 x*r.length/(max-min)|0

后者的更多 JavaScript 迭代:

var colors=[];
// black-red
for(var i=0;i<256;i++)colors.push({r:i,g:0,b:0}); // black-red
for(var i=1;i<256;i++)colors.push({r:255-i,g:i,b:0}); // red-green
for(var i=1;i<256;i++)colors.push({r:0,g:255-i,b:i}); // green-blue
for(var i=1;i<256;i++)colors.push({r:i,g:i,b:255}); // blue-white

speeds.foreacy(function(x,idx){
  var color=colors[x*colors.length/(max-min)|0]; // r-g-b fields with values 0-255
  ...
}

我会对这个数组进行排序,然后将你的数组分成 3 个较小的数组。在这个操作之后你应该标准化你的数组。您可以使用公式将列表中的每个元素相乘:

(xi - min)/(max - min)

您必须规范化新数组而不是旧数组。对于第一个数组(最小值),您可以通过 k=(max-xi)*255.0 计算红色密集度。这种颜色将是 (k, 0, 0) 。您按公式着色的速度最快的数组:k=xi*255.0 [颜色将为 (0,0,k)]。中间值的公式取决于您的选择。 (更高的速度 = 更多的绿色或更高的速度 = 更慢的速度)。

很抱歉描述复杂。祝你好运。

假设min是最小速度,max是最大速度,那么所有速度都在minmax之间:

min |---------------------------| max
               speeds

你必须把这个区间分成两个更小的区间,像这样:

 |-------------|--------------|
min           mid            max

您可以分配给最小全红、中全绿和最大全蓝:

 R             G              B
 |-------------|--------------|
min           mid            max

现在您必须为每个速度值计算其颜色。假设 s 是您的速度之一的值:

r = g = b = 0;

if (s <= mid) {
    r = 255 - (s - min) / (mid - min) * 255; // r is 255 when s = min and 0 when s = mid
    g = 255 - (mid - s) / (mid - min) * 255; // g is 255 when s = mid and 0 when s = min

} else {
    b = 255 - (s - mid) / (max - mid) * 255;
    g = 255 - (max - s) / (max - mid) * 255;
}

鉴于您的一系列速度,您可以执行以下操作:

var speeds = [0.5, 0.5, 0.75, 1.25, 0.50, 0.75, 1.00, 4.00, 4.50, 8.00, 7.50, 8.50, 6.50, 6.00, 5.00, 5.25, 4.75, 4.00, 3.25, 2.50, 1.25, 0.00]
var max = Math.max(...speeds);
var min = Math.min(...speeds);
var mid = (max - min) / 2;

var colors = speeds.map((s) => {
    var r, g, b;
    r = g = b = 0;

    if (s <= mid) {
        r = 255 - (s - min) / (mid - min) * 255;
        g = 255 - (mid - s) / (mid - min) * 255;

    } else {
        b = 255 - (s - mid) / (max - mid) * 255;
        g = 255 - (max - s) / (max - mid) * 255;
    }

    return [r, g, b];
});

console.log(colors);

数组 colors 将包含 speeds 中每个速度的 [r, g, b] 列表。

另一种选择是简单计算 hsl 值,因为您已经知道要处理的确切颜色。从 hsl 转换为 rgb 应该不难,有很多库可以很好地做到这一点。

这是一个例子。

var speeds = [0.5, 0.5, 0.75, 1.25, 0.50, 0.75, 1.00, 4.00, 4.50, 8.00, 7.50, 8.50, 6.50, 6.00, 5.00, 5.25, 4.75, 4.00, 3.25, 2.50, 1.25, 0.00];
var fragment = document.createDocumentFragment();
var list = document.querySelector('ul');
var speedsMin = Math.min(...speeds);
var speedsMax = Math.max(...speeds);
var hslMin = 0;
var hslMax = 240;

var hslValues = speeds.map(function(value) {
  return { 
    h: Math.ceil( ( (value - speedsMin) / (speedsMax - speedsMin) ) * (hslMax - hslMin) + hslMin ),
    s: 100,
    l: 50
  }
})

hslValues.forEach(function(value) {
  var item = document.createElement('li');
  var color = 'hsl(' + value.h + ',' + value.s + '%,' + value.l + '%)';
  item.style.backgroundColor = color;
  fragment.appendChild(item)
})

list.appendChild(fragment)
ul {
  list-style-type: none
  margin: 0;
  padding: 0;
}

ul li {
  width: 20px;
  height: 20px;
  border-radius: 10px;
  display: inline-block;
  margin: 0 4px
}
<ul></ul>

你可以计算出两个区域的颜色,然后用这三种颜色来生成渐变。

function getColor(v, min, max) {

    function getC(f, l, r) {
        return {
            r: Math.floor((1 - f) * l.r + f * r.r),
            g: Math.floor((1 - f) * l.g + f * r.g),
            b: Math.floor((1 - f) * l.b + f * r.b),
        };
    }

    var left = { r: 255, g: 0, b: 0 },
        middle = { r: 0, g: 255, b: 0 },
        right = { r: 0, g: 0, b: 255 },
        mid = (max - min) / 2;

    return v < min + mid ?
        getC((v - min) / mid, left, middle) :
        getC((v - min - mid) / mid, middle, right);
}

var speeds = [0.5, 0.5, 0.75, 1.25, 0.50, 0.75, 1.00, 4.00, 4.50, 8.00, 7.50, 8.50, 6.50, 6.00, 5.00, 5.25, 4.75, 4.00, 3.25, 2.50, 1.25, 0.00],
    min = Math.min(...speeds),
    max = Math.max(...speeds);

speeds.forEach(function (a) {
    var color = getColor(a, min, max);
    document.body.innerHTML += '<span style="color: #fff; background-color: rgb(' + color.r + ',' + color.g + ',' + color.b + ');">' + a + '</span> ';
});