【问题标题】:Calculating color value (r,g,b) using javascript使用javascript计算颜色值(r,g,b)
【发布时间】:2017-12-30 00:10:58
【问题描述】:

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

这些值以 m/s 为单位,我不知道它们有多少以及它们有多大。我需要创建一个函数来决定使用什么颜色。

我的想法是找到数组的 maxmin 值(速度),因为我知道这些值都可以除以 0.25,所以我想通过执行 @ 来计算可能的“步数” 987654324@

因为我有一个 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)中更加强烈,然后根据它们倾向于哪一侧添加一点红色或蓝色。

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

【问题讨论】:

    标签: javascript colors gradient rgb


    【解决方案1】:

    如果您不反对使用库,可以查看 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)
    }
    

    【讨论】:

      【解决方案2】:

      另一个选择是简单地计算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
      }
      &lt;ul&gt;&lt;/ul&gt;

      【讨论】:

      • 这看起来很棒。但是,我需要按照它们到达的顺序使用我的速度,所以对它们进行排序对我来说不是一个好主意。但我想如果我能以不同的方式获得最小值和最大值,我仍然可以使用你的函数
      • 不需要对它们进行排序,只是觉得它看起来更好;)。我进行了编辑。
      • 我同意它看起来更好,但我在地图上使用点的颜色,它们不会完全按顺序排列。无论如何谢谢。这完美无缺! :D
      • 抱歉再次询问。我已经使用了上述方法,但我可以使用一个有序的 l 列表,就像你以前没有重复的那样。你知道上面的例子是如何实现的吗?
      • 要预先对数组进行排序,您可以简单地执行[….].sort(function(a,b) { return a - b})。这是你的意思吗?
      【解决方案3】:

      假设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 将包含[r, g, b] 列表,用于speeds 中的每个速度。

      【讨论】:

      • 这是一个非常简洁的例子。我会尝试实现它。谢谢! :D
      • @Zeliax,不客气!我在帖子末尾添加了更多信息以提供更多帮助。
      【解决方案4】:

      您可以计算两个区域的颜色,并使用这三种颜色来生成渐变。

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

      【讨论】:

        【解决方案5】:
        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.
        });
        

        这个想法是这样的,但是写完之后我很难弯曲我的大脑来验证它。我认为现在是正确的 red->green->blue 2-segment 渐变。

        超过 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
          ...
        }
        

        【讨论】:

        • 考虑您的第二个解决方案,如何在 4.25 的速度下获得所需的输出值? x 应该是 4.25 吗?
        • @Zeliax 是的,x 是实际速度值
        • 好的。据我了解,我将为每个“颜色部分”(黑红、红绿等)提供一个调色板,但您建议的索引仅使用红色数组?我该怎么做才能获得实际的颜色? var color = x * r.lenght/(max-min)|0?
        • 哦,我想我现在明白了。应该是var index = x * r.length/(max-min)|0,然后我可以做red = r(index), green = g(index), blue = b(index)。我说的对吗?
        • @Zeliax 是的,但是现在我添加了一个更好的变体,带有颜色“对象”。你可能会发现它更有用
        【解决方案6】:

        我会对这个数组进行排序,然后将你的数组分成 3 个较小的数组。在此操作之后,您应该规范化您的数组。您可以通过使用公式将列表中的每个元素相乘来做到这一点:

        (xi - min)/(max - min)

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

        对于复杂的描述,我很抱歉。祝你好运。

        【讨论】:

        • 对不起。我不能使用这个程序,因为我需要速度按照它们来的顺序。无论如何感谢分享
        • 您可以将它们复制到其他数组中并记住它们的索引。但我发现了另一个问题。您应该将 255.0 更改为 128.0 并将 128.0 添加到公式中(例如:(max-xi)*128.0 + 128.0),因为当您在数组中具有最小值时,结果将在所有数组中为黑色。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-25
        • 2011-04-14
        • 1970-01-01
        • 2014-12-05
        • 2020-03-23
        • 1970-01-01
        相关资源
        最近更新 更多