NVD3 add a border/stroke to area chart

5.4k views Asked by At

I have a stacked area chart like the one at : http://nvd3.org/ghpages/stackedArea.html

Is it possible to add a stroke to the top of the area bit of the plot so it looks like it has a border/stroke?

I tried adding in a stroke with the webkit inspector but nothing seems to happen (assuming this is like using .style('stroke','#000000')

So if there was just one series on the stackedAreaExample and it was blue in colour, the border would make it look something like this:

enter image description here

2

There are 2 answers

4
Lars Kotthoff On BEST ANSWER

There's no border as such in SVG, so you have to add a rectangle that determines the border and assign the appropriate style. NVD3 doesn't have an option for this, but you can select the relevant element after it has been drawn and add the new content.

d3.select(".nv-stackedWrap")
.append("rect")
.attr("width", chart.xAxis.scale().range()[1])
.attr("height", chart.yAxis.scale().range()[0])
.style("fill", "none")
.style("stroke", "black");

This works for the stacked area chart; for other types of charts the name of the class of the element to select will be different.

Setting a border on the top area is tricker, as SVG doesn't allow you to set the stroke for only a single side of a path. You can do it with stroke-dasharray however -- you just need the total length of the path.

d3.select(".nv-area-" + (data.length-1))
    .style("stroke", "black")
    .style("stroke-opacity", 1)
    .style("stroke-dasharray", function() {
      return this.getTotalLength()/2 + "," + this.getTotalLength();
    });

This selects the last (i.e. top) area and sets the stroke for it. The specified dasharray means that there will be a stroke for half of the path (i.e. the top) and then nothing for the length of the path (to make it appear as if there was only a stroke on the top).

The problem with this and NVD3 is the transition that "grows" the areas. If you run this code when the graph is created, the length of the line may be shorter than what it will be in the end. To make sure that the length is correct, you would need to (re)run this code after the transition is complete, e.g. using setTimeout.

1
Pramma On

Instead you can just draw a line chart with same data with darker color which will look like a border.

    var areaFunc = d3.svg.area()
        .interpolate("monotone")
        .x(function(d) { return d.index; })
        .y0(THIS.height)
        .y1(function(d) { return d.delay });

    var lineFunc = d3.svg.line()
        .x(function(d) { return d.index; })         
        .y(function(d) { return d.delay });

           .......

    svg.append("path")
      .datum(myData)
      .attr("class", "area")
      .attr("d", areaFunc);

    svg.append("path")
      .datum(myData)
      .attr("class", "line")  // with a darker color
      .attr("d", lineFunc);