Need help plotting area between multivariate lines

2020-07-24 15:27发布

问题:

I'm brand new to d3.js, and I'm struggling to fill in the area between lines in a multivariate percentile graph.

  • I don't want any area filled below the bottom most line, or above the top most line.
  • The first column will always be at the bottom of the graph (5th percentile)
  • The last column will always be at the top of the graph (95th percentile)
  • I need separate area segments between each line

I know I need to define an area to fill between (y0, y1) like so:

var area = d3.svg.area()
.x(function(d) { return x(d.date); })
.y0(function(d) { return y(BOTTOM); })
.y1(function(d) { return y(TOP); });

However I can't figure out what to put in for the .y1 section. Ideally, I'd just grab the next value of the next row in the TSV, but I don't know how to do this properly.

For testing purposes, I have the following which creates ONE of the area segments I need:

.y0(function(d) { return y(+d.p05); })
.y1(function(d) { return y(+d.p25); });

I want something like this, but this example doesn't help since it isn't referencing a different row from a csv/tsv:

http://bl.ocks.org/mbostock/4060954

This one is similar, but its bivariate, not multivariate.

http://bl.ocks.org/mbostock/3894205


Here's my work in progress(view source):

http://artfuladvection.com/project/NOAA/percentilesGraph/multipercentile.html

My TSV is setup like this:

date    p05 p25 p50 p75 p95
20140122    3   4   5   6   12
20140123    9   10  12  22  34
20140124    14  16  18  34  66

Any help?

回答1:

For a single area, the code would look something like this.

var area = d3.svg.area()
  .x(function(d) { return x(d.date); })
  .y0(function(d) { return y(+d.p05); })
  .y1(function(d) { return y(+d.p25); });

per.append("g")
   .attr("class", "per")
   .append("path")
   .attr("class", "area")
   .attr("d", function (d) { return area(data); });

For multiple areas, you can use the domain of your color scale to loop over the different values like you have done before. That is, the code above would be in a loop like this.

var values = color.domain();
for(var i = 0; i < values.length() - 1; i ++) {
  var area = d3.svg.area()
    .x(function(d) { return x(d.date); })
    .y0(function(d) { return y(+d[values[i]]); })
    .y1(function(d) { return y(+d[values[i+1]]); });

  per.append("g")
     .attr("class", "per-" + values[i])
     .append("path")
     .attr("class", "area-" + values[i])
     .attr("d", function (d) { return area(data); });
}