In Javascript / D3, how to map colorscale of 5 colors (hex format) to 17 colors

问题: Lets say I have the javascript array ['#1147FF', '#86D8FF', '#FFEF67', '#FF7D11', '#F30000']. If I go to this color scales website here, and click from 5 steps to 17 steps,...

问题:

Lets say I have the javascript array ['#1147FF', '#86D8FF', '#FFEF67', '#FF7D11', '#F30000']. If I go to this color scales website here, and click from 5 steps to 17 steps, it outputs '#1147ff','#4f6cff','#6990ff','#7bb4ff','#86d8ff','#b4dddb','#d3e3b7','#ebe991','#ffef67','#ffd453','#ffb83f','#ff9b2a','#ff7d11','#fd6a0b','#fa5405','#f73902','#f30000', which is essentially the color scale I want.

Is there a way to get this done solely using 6-hex hex values? I'm currently using a horrific approach that converts hex values to rgb values, and then loops the rgb values (below is a rough example of what im referring to, ignore green in the variable names):

    green0pct = { r: 17, g: 71, b: 255 };
    green7p5pct = { r: 134, g: 216, b: 255 };
    green15pct = { r: 252, g: 233, b: 70 };
    green22p5pct = { r: 255, g: 125, b: 17 };
    green30pct = { r: 243, g: 0, b: 0 };

    for (let j = 0; j <= 30; j++) {
        if (j % 2 === 0) {
            if (j < 7.5) {
                newR = green0pct.r - (j * (green0pct.r - green7p5pct.r) / 7.5);//
                newG = green0pct.g - (j * (green0pct.g - green7p5pct.g) / 7.5);
                newB = green0pct.b - (j * (green0pct.b - green7p5pct.b) / 7.5);
            } else if (j < 15) {
                newR = green7p5pct.r - ((j - 7.5) * (green7p5pct.r - green15pct.r) / 7.5);
                newG = green7p5pct.g - ((j - 7.5) * (green7p5pct.g - green15pct.g) / 7.5);
                newB = green7p5pct.b - ((j - 7.5) * (green7p5pct.b - green15pct.b) / 7.5);
            } else if (j < 22.5) {
                newR = green15pct.r - ((j - 15) * (green15pct.r - green22p5pct.r) / 7.5);
                newG = green15pct.g - ((j - 15) * (green15pct.g - green22p5pct.g) / 7.5);
                newB = green15pct.b - ((j - 15) * (green15pct.b - green22p5pct.b) / 7.5);
            } else {
                newR = green22p5pct.r - ((j - 22.5) * (green22p5pct.r - green30pct.r) / 7.5);
                newG = green22p5pct.g - ((j - 22.5) * (green22p5pct.g - green30pct.g) / 7.5);
                newB = green22p5pct.b - ((j - 22.5) * (green22p5pct.b - green30pct.b) / 7.5);
            }
            displayPct = playerOrTeam === 'Team' ? (j - 15) / 2 : j - 15;
            greenScale.push({ text: `${displayPct}%`, col: `rgb(${newR},${newG},${newB})` });
        }}

回答1:

One option could be to use a d3-interpolator:

d3.interpolateRgbBasis(colors) <>

Returns a uniform nonrational B-spline interpolator through the specified array of colors, which are converted to RGB color space. Implicit control points are generated such that the interpolator returns colors[0] at t = 0 and colors[colors.length - 1] at t = 1. (source)

At the most basic, you could produce a new list of n colors based on an array of colors and the interpolator with:

// Starting colors:
var colors = ['#1147FF', '#86D8FF', '#FFEF67', '#FF7D11', '#F30000'];

// Create an interpolator:
var interpolate = d3.interpolateRgbBasis(colors);

// Make 17 new colors: 
var n = 17;
var newColors = d3.range(n).map(function(d) {
  return interpolate(d/(n-1));  // d/(n-1) will range from 0 through 1
})

Here's a demonstration:

var colors = ['#1147FF', '#86D8FF', '#FFEF67', '#FF7D11', '#F30000'];
var interpolate = d3.interpolateRgbBasis(colors);

var n = 17;
var newColors = d3.range(n).map(function(d) {
  return interpolate(d/(n-1));
})

console.log(newColors);

d3.select("svg")
  .selectAll("rect")
  .data(newColors)
  .enter()
  .append("rect")
  .attr("fill", function(d) { return d; })
  .attr("width", 10)
  .attr("height",10)
  .attr("x", function(d,i) {
    return i*12;
  })
  .attr("y", 20);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

  • 发表于 2019-03-10 14:43
  • 阅读 ( 172 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除