区域填充的 D3 图不起作用

D3 graph with area fill not working

我想让折线图中的区域正确填充。 (看图看问题)

注意填充区域和填充下方的文字:

代码如下:

<!DOCTYPE html>
<style type="text/css">

.area {
    fill: lightsteelblue;
    stroke-width: 0;
}

</style>
<svg width="860" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var parseTime = d3.timeParse("%d-%b-%y");

var x = d3.scaleTime()
    .range([0, width]);

var y = d3.scaleLinear()
    .range([height, 0]);

var line = d3.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.close); });

d3.tsv("data.tsv", function(d) {
  d.date = parseTime(d.date);
  d.close = +d.close;
  return d;
}, function(error, data) {
  if (error) throw error;

  x.domain(d3.extent(data, function(d) { return d.date; }));
  y.domain([0, d3.max(data, function(d) { return d.close; })]);

var xAxis = d3.axisBottom(x)
    .ticks(d3.timeYear);

var yAxis = d3.axisRight(y)
    .tickSize(width);

var area = d3.area()
    .x0(function () {
    return 0,width;
})
    .x1(function (d) {
    return x(d.date);
}).y0(function () {
    return height,height;
})
    .y1(function (d) {
    return y(d.close);
});

var valueline = d3.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.close); });

g.append("g")
    .attr("transform", "translate(0," + height + ")")
    .call(customXAxis);

g.append("g")
    .call(customYAxis);

function customXAxis(g) {
  g.call(xAxis);
  g.select(".domain").remove();
  g.selectAll(".tick line")
  .attr("stroke", "#e9e9e9")
  .attr("height","510px")
  .attr("transform", "translate(0," + -height + ")");
}

function customYAxis(g) {
  g.call(yAxis);
  g.select(".domain").remove();
  g.selectAll(".tick:not(:first-of-type) line").attr("stroke", "#e9e9e9");
  g.selectAll(".tick text").attr("x", width - 18).attr("dy", -4);
}

  g.append("path")
      .datum(data)
      .attr("fill", "none")
      .attr("stroke", "steelblue")
      .attr("stroke-linejoin", "round")
      .attr("stroke-linecap", "round")
      .attr("stroke-width", 1.5)
      .attr("d", line);

g.append("path")
    .datum(data)
    .attr("class", "area")
    .attr("d", area);

});

</script>

此外,如果可能的话,如果有人知道,如何让区域填充不与 y 轴文本和所有轴线重叠,以便文本和轴线位于区域填充之上.

还有一件事,我已经尝试了几个小时。如何让x轴线与灰色y轴线一起创建网格?

如有任何帮助,我将不胜感激。谢谢

对于您的主要问题:

您正在使用线生成器创建面积图 - 在填充生成的路径时,您只需连接第一个点和最后一个点,即您的图像。生成器 "know" 填充区域的底部应该如何? y 轴值为零对于基数来说可能很常见,但它肯定不是通用的。 在任何情况下,线生成器都需要包含缩放 y 值为 0 的点以创建正确的填充 - 这不会是表示数据的准确线,除非起点和终点的 y 值为0,这就是为什么d3除了线生成器还提供了区域生成器。

而不是 d3.line,使用 d3.area (also, here's a canonical example likely using your data):

var area = d3.area()
    .x(function(d) { return x(d.date); })
    .y1(function(d) { return y(d.close); })   // top of area
    .y0(yScale(0));                           // bottom of area

.y0 方法是可选的,如果未指定,则默认为零,但这里是它的文档:

If y is specified, sets the y0 accessor to the specified function or number and returns this area generator. If y is not specified, returns the current y0 accessor, which defaults to:

function y() { return 0; }

When an area is generated, the y0 accessor will be invoked for each defined element in the input data array, being passed the element d, the index i, and the array data as three arguments. See area.x0 for more information. (source).

y1 方法表示图的顶部(与折线图中的 y 访问器相同),y0 方法表示底部,在您的情况下是常量。