Sexy Graphs with nvd3
For a recent project I needed to implement some nice-looking graphs. A colleague recommended the nvd3 library, which is built on top of the awesome d3.js package, so sexiness was all-but-guaranteed. Here’s my experience with using nvd3.
First, I found that there is no documentation for nvd3 per se (there’s plenty for d3). Fortunately there are lots of source code examples on the github page.
The most trouble I had was with the stacked bar chart. I’m using a Discrete Stacked Bar Chart (as described here). It is somewhat fussy with its data format.
The basic format for the data points is:
[
{
key: “series name”,
color: “#FF00FF”,
values:
[
{ x: “A”, y: 33 },
{ x: “B”, y: 44 },
{ x: “C”, y: 14 }
]
},
{
…
}
…
]
The chart will start acting quite strangely (weird behaviours including drawing artifacts when displaying and also animating, and “NaN”-style messages in the developer toolbar) if the x’s for different series are out of order (ie. different one series to the next); also all values have to exist for all the series, which means padding out the data with zeroes if necesary.
The library also tries to avoid labels overlapping on the x-axis; it generally seems to do this by missing out values. However this can run into trouble when the labels are lengthy, for example:
The multichart also has a few slight layout issues, where it can cuts off values on the right axis; it also gets a little finnicky when you filter off (using the little legend circles) all of the series on one side (for me, it refused to get into a state where it would only show series from one side). Other than these minor issues it seems to work quite well.
It’s worth pointing out that there seems to be more examples in the github area for nvd3 than are displayed on the main website; for example, this rather busy multichart which features several different types of graph:
I found myself needing to simplify some of the examples, to test how particular things work and to expose a bit more explicitly the required format of the data series (as some of the examples feature programmatically-generated data); for example to play with multicharts which have only line graphs in them, I used the following code:
var testdata = [{},{},{},{},{},{},{}];
for (var i = 0; i <= 6; i++) {
testdata[i].type = “line”;
testdata[i].yAxis = (i <=2 ? 1 : 2);
}
nv.addGraph(function() {
var chart = nv.models.multiChart();
chart.xAxis.tickFormat(d3.format(‘,f’));
chart.yAxis1.tickFormat(d3.format(‘,.1f’));
chart.yAxis2.tickFormat(d3.format(‘,.1f’));
for (var i in testdata) {
testdata[i].key =’Stream’ + i;
var c = i * 8 * (0.1*i);
testdata[i].values= [ {x:9,y:12+c},{x:10,y:94+c},{x:12,y:99+c},{x:13,y:121+c},{x:15,y:133+c},{x:16,y:148+c},{x:19,y:199+c},{x:22,y:299+c}];
testdata[i].color=’#FF’ + (100+(150-i*25)).toString(16) + (100+(i*25)).toString(16);
}
d3.select(‘#chart svg’).datum(testdata).transition().duration(500).call(chart);
return chart;
});
Further customisation of the graphs is certainly possible with some tinkering and help from StackOverflow and Google Groups posts (e.g. having one of a series switched off by default – you just include disabled: true when defining the series’ object).
Because nvd3 is SVG based, saving a chart to an image is not easy like it is with, say, canvas. Two options for accomplishing this appear to be phantomjs, or, possibly more simply, canvg.
Of course nvd3 has competitors, such as xCharts (which is also built on d3.js), polychart.js and Highcharts JS (both commercial products).
Despite the small issues I had with nvd3, most of which are easily enough worked-around once you’re aware of them, the visual results are certainly nice – seeing bars animate and shift when filtering from one set of data to the next is guaranteed to get some “ooh’s” and “aah’s” from most audiences.
Leave a Reply
Want to join the discussion?Feel free to contribute!