Posts

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.

Adventures with Javascript Graphing Libraries

I was looking for a Javascript library that would display a graph – in the mathematical sense of a node-arc network such as the following:

I might require curved lines and maybe arrows, and I need it to be zoomable and pannable.  I also need node labels and click events on both nodes and edges.

Remembering a few links someone sent around showing off impressive applications of libraries such as d3.js and jQuery Sparklines I had high hopes of finding something I could use that was polished and snazzy with superb documentation and an enthusiastic community.

The first thing I noticed is that it seems like everyone is in love with Force-Directed Layouts these days – you know those graphs where the nodes appear “springy” and the spatial layout is “discovered” by the physics algorithm, such as this example.  By their nature, however, these graphs have a dynamic layout – you generally can’t specify exact positions for your nodes.

The libraries I looked at included the following.  A discussion of SVG vs Canvas is here.

d3.js – this library is SVG-based (as opposed to say, HTML5 canvas-based).  With a cursory look I couldn’t see how to zoom (you should be able to though, right – it’s scalable vector graphics…!), and the docs are pretty large and initially confusing.  The consensus seems to be that it is a power users tool.

Sigma.js has some nice-looking examples and appears to scale to hundreds of nodes and arcs nicely. It can use GEXF graph format. However, it lacks good documentation and doesn’t seem to have much momentum – the last source code change was 9 months ago.

jsPlumb has demos that do not appear to be zoomable, though the library seems to be still actively developed and has good docs.  It can render by canvas/SVG/VML using jQuery/MooTools etc.  However it seems more aimed at connecting elements with drag and drop than showing graphs per se.

Raphael seems nice enough, is SVG based, has intriguing demos and reasonable docs, the last change on github was 10 months ago, but again the demos had no zoom.

The Javascript InfoVis Toolkit strikes the right balance of functionality with simplicity for me – there’s enough simplicity that I can actually delve into the source (only one file needed – jit.js) and pretty easily see what’s going on.  It’s canvas-based, but appears to mousewheel zoom (very smoothly) using canvas’ scale function.  The project was also involved in a Google Summer of Code.  Although there was no static graph example, I found it quite easy to adapt the force-directed example code to show a nice zoomable graph with node coordinates that I explictly specified (and has node and edge click events).  (In doing this, I also discovered something interesting – the force-directed layout example gives you a totally new layout every time you refresh – you can see this by refreshing the demo page here multiple times.  This randomised behaviour seems somewhat less than useful. Also interesting is the drag and drop of the nodes in the force directed example).

So I did not find anything that fit squarely with my requirements, though I’m going with the Infovis Toolit for now.  (Of course there is always the possibility to handcode it myself, which for reasonably simple requirements is always an option, though less preferred particularly as you might encounter issues such as cross-browser bugs that have been addressed in the libraries and frameworks.)

On the plus side I truly learnt what Bezier curves actually are (and how they differ from quadratic Bezier curves), thanks to some help from the Wikipedia page and this neat interactive page where you can drag the control points around to see the effect on the curve.

Some time after doing the above (admittedly rather cursory) research, I then came across another cluster of libraries with a slightly different focus.  These libraries are more geared towards interactive elements on canvas (e.g. drag and drop) and persisting the state of the elements when they are changed – a good starting discussion is at the Stack Overflow page here.  The “master list” of these libraries I found in a Google doc here.  These libraries provide more of a “scene graph” implementation which would be useful if you need a framework for proper tracking of the elements being drawn (especially if they are to be animated, e.g. a particle simulator).