D3:如何创建自定义的倾斜色标?

D3: How to create a custom, skewed color scale?

我创建了以下色标:

代码如下:

  function continuous(selector_id, colorscale) {
    var legendheight = 200,
      legendwidth = 80,
      margin = { top: 10, right: 60, bottom: 10, left: 2 };

    var canvas = d3
      .select(selector_id)
      .style("height", legendheight + "px")
      .style("width", legendwidth + "px")
      .style("position", "relative")
      .append("canvas")
      .attr("height", legendheight - margin.top - margin.bottom)
      .attr("width", 1)
      .style("height", legendheight - margin.top - margin.bottom + "px")
      .style("width", legendwidth - margin.left - margin.right + "px")
      .style("border", "1px solid #000")
      .style("position", "absolute")
      .style("top", margin.top + "px")
      .style("left", margin.left + "px")
      .node();

    var ctx = canvas.getContext("2d");

    var legendscale = d3
      .scaleLinear()
      .range([1, legendheight - margin.top - margin.bottom])
      .domain(colorscale.domain());

    var image = ctx.createImageData(1, legendheight);
    d3.range(legendheight).forEach(function (i) {
      var c = d3.rgb(colorscale(legendscale.invert(i)));
      image.data[4 * i] = c.r;
      image.data[4 * i + 1] = c.g;
      image.data[4 * i + 2] = c.b;
      image.data[4 * i + 3] = 255;
    });
    ctx.putImageData(image, 0, 0);

    var legendaxis = d3.axisRight().scale(legendscale).tickSize(6).ticks(8);

    var svg = d3
      .select(selector_id)
      .append("svg")
      .attr("height", legendheight + "px")
      .attr("width", legendwidth + "px")
      .style("position", "absolute")
      .style("left", "0px")
      .style("top", "0px");

    svg
      .append("g")
      .attr("class", "axis")
      .attr(
        "transform",
        "translate(" +
          (legendwidth - margin.left - margin.right + 3) +
          "," +
          margin.top +
          ")"
      )
      .call(legendaxis);
  }

  useEffect(() => {
    var colorScale = d3.scaleSequential(d3.interpolateRdYlGn).domain([-4, 16]);
    var svg = continuous("#legend1", colorScale);
  }, []);

由于我的数据偏向于大于 0 的值,我想创建一个自定义比例,其中偏斜的红色到绿色着色和发生在 0 而不是 6 的过渡。但是,我在实现自定义缩放功能时遇到了问题。

我遵循了 post 的建议,但无法实现功能,即:

var custom = d3.scaleLinear()
  .domain([0,       50,       90,        95,       100])
  .range(['#edfc1b','#ec6f3b','#bc2e67','#7c0093', '#0b0074']);

目前,我从上面的代码中得到的是:

所以,我的问题是:如果我有一个值数组,例如 [0, 50, 90, 95, 100]?

,我怎样才能绘制出完整的域?

或者,是否有更好的方法在 D3 中创建自定义色标?

定义比例的代码是正确的:

  var custom = d3.scaleLinear()
    .domain([0,       50,       90,        95,       100])
    .range(['#edfc1b','#ec6f3b','#bc2e67','#7c0093', '#0b0074']);

问题在于将此颜色比例转换为空间比例的代码:

  var legendscale = d3
      .scaleLinear()
      .range([1, legendheight - margin.top - margin.bottom])
      .domain(colorscale.domain())

上面的代码创建了一个范围长度为2,域长度为5的比例尺。scaleLinear需要域和范围长度相等的数组,否则不会做1 -to-1 映射如预期。

当域的长度固定(在您的情况下为 5)时,一个快速修复方法是通过中间步骤手动扩展范围。

  var max = legendheight - margin.top - margin.bottom;
  var legendscale = d3
      .scaleLinear()
      .range([1, max / 4, 2*(max / 4), 3*(max / 4), max])
      .domain(colorscale.domain())