Thursday, June 6, 2013

Charting with D3

After months of wishing we had a good project to try out the D3 charting library, it has finally happened. We do a few charts now and then, but finally a really big charting project has come up. At this point, it's nothing fancy: just some bar charts and pie charts, but it's finally an opportunity.

For the Impatient


If you're impatient, you can skip straight to my Github repo where I have posted some wrapper functions to make D3 easier to work with for our simple use cases.

https://github.com/gregallensworth/Charts_D3

The motivation behind these wrappers, was that I found myself copying and pasting the same 25 lines of code and changing little more than the data and the name of a field. By the time I created a technique for adding tooltips, each function for laying down a pie chart was some 75 lines of code. In our case, every pie chart and every bar chart are basically identical in their needs and a wrapper made a lot of sense.


D3 is Raw


D3 is tough to work with, in that it's not really a charting library but more of a SVG toolkit. A charting library, you declare a list of values for the X and Y axes, pick a color, and get a chart. With D3 it's dozens of lines of defining radii, figuring out how much space to trim off and then positioning to the center of the SVG canvas. It's very much a raw nuts-n-bolts experience, which I normally like... but in the case of a ready-to-draw chart library, not so much.

Being a very raw library, you have to write a lot of the math yourself. The placement of the labels on pie charts, the height of rectangles to create the illusion of a bar chart, ... most of that is written with D3's help but is hardly a "here's data, here're colors, draw a chart" sort of function.

Thus, the wrappers.


Tooltips


The existing samples lacked tooltips, so I had to invent those using the mousemove and mouseout events. I cheated, and did them in jQuery instead of learning enough SVG to emulate the same effect in "more pure" D3 & SVG.

For us, we use jQuery in practically everything so this wasn't a bad way to go.


IE8 and below


D3 does not run in IE8. But R2D3 does. This alternate version of D3 works in IE8, and with some conditionals you can have modern browsers run D3 proper, and have IE8 use the compatible version.

So far  we haven't hit on a case where R2D3 fails to do what D3 does. I'm sure it's not perfect, but at this point we haven't found an imperfection. Neat, eh?


Printing / Saving to PDF


Being a purely client-side phenomenon, drawing charts in D3 makes it difficult to link directly to the chart graphic, or to embed the graphic into a PDF.

For our "Save as PDF" needs we largely use WKHtmlToPDF, which reads a HTML document and renders it as a PDF via Qt and the Webkit engine. It supports JavaScript too, so we largely write the PDF template in HTML and JavaScript -- which can include D3.


Conclusion


An interesting exercise. D3 definitely is not a ready-to-run chart library, but obviously it has a lot of promise if you have significant development time to write code in SVG. Now that I've done the initial investment of developing the wrappers, future pies and bars will be a lot easier.