Reputation: 45
Apologies for such a basic question. Is it possibly to fill the area between two lines?
For example, I have historical high/low temperature data. I'd like to create a shaded area between these two timeseries.
I've tried using the area feature of a lineChart like this:
return [
{
values: tsData.normal,
key: 'Historical Normal',
classed: 'dashed'
},
{
area: true,
values: tsData.hi,
key: 'Historical Max',
color: '#0000ff'
},
{
area: true,
values: tsData.low,
key: 'Historical Min',
color: '#ffffff',
fillOpacity: 1
}
];
Which results in this image:
Note that the gridlines below the Historical Min line are hidden by the filled areas. This solution is a bit hacky and ugly. Is there a more direct way to do this?
Upvotes: 4
Views: 1535
Reputation: 101
I achieved a better solution by drawing an area using d3.
First I created an array (I called areaData) that merges tsData.hi and tsData.low. For each data point I push for eg: {x: "The x value", y0:"The y value from tsData.hi", y1:"The y value from tsData.low"}
Then I defined the x and y scale based on the chart's scales:
var x = chart.xScale();
var y = chart.yScale();
Then I added an area definition as
var area = d3.svg.area()
.x(function (d) { return x(d.x); })
.y0(function (d) { return y(d.y0); })
.y1(function (d) { return y(d.y1); });
Next I drew the area using:
d3.select('.nv-linesWrap')
.append("path")
.datum(areaData)
.attr("class", "area")
.attr("d", area)
.style("fill", "#AEC7E8")
.style("opacity", .2);
This achieves a better looking solution. Because nvd3 updates the chart when the window is resized. I wrapped the drawing of the area in a function. So that I can call the function when the window is resized while removing the previously drawn area as follows:
var drawArea = function () {
d3.select(".area").remove();
d3.select('.nv-linesWrap')
.append("path")
.datum(areaData)
.attr("class", "forecastArea")
.attr("d", area)
.style("fill", "#AEC7E8")
.style("opacity", .2);
}
drawArea();
nv.utils.windowResize(resize);
function resize() {
chart.update();
drawArea();
}
I also disabled switching the series on and off using the legend as I wasn't handling that case:
chart.legend.updateState(false);
The result:
Upvotes: 4