Draw a Sparkline with D3

Overview

A Sparkline is a kind of line chart, usually drawn without axes, placed inline with text e.g. with tabular data. It is the simplest of visualisations and an ideal entry into learning D3. This post discusses the visualisation of a Burndown chart as a Sparkline, built with Angular and D3.

Sparkline

Data

D3 means ‘Data Driven Documents’ with the idea that it is your data mapped to a visualisation. D3 is not limited to standard chart types e.g. Line or Bar, but is flexible in how data can be represented. The data for a Burndown visualisation will have a time component e.g. Days in a sprint and a work component e.g. Tasks completed. The data for this burndown sparkline covers 10 days (two weeks) and 25 tasks, with 4 tasks remaining incomplete at the end of the sprint.

{
  name: 'Team 1',
  burn: [
    { day: 1, tasks: 25 },
    { day: 2, tasks: 24 },
    { day: 3, tasks: 23 },
    { day: 4, tasks: 20 },
    { day: 5, tasks: 17 },
    { day: 6, tasks: 15 },
    { day: 7, tasks: 12 },
    { day: 8, tasks: 10 },
    { day: 9, tasks: 7 },
    { day: 10, tasks: 4 }
  ]
}

Javascript

The Sparkline is built as an Angular Directive, making it reuseable in the application.
D3 outputs an SVG and the sparkline itself is drawn as a path, appended to the SVG.

// Append path to SVG
svg.append('path').attr('class', 'linePath');

This path can then be retrieved and updated using D3’s select function, so the sparkline updates dynamically when resizing occurs e.g. when the orientation moves from landscape to portrait.

function draw(svg, x, y, line, data) {
  var width = parseInt(svg.style('width'));
  var height = parseInt(svg.style('height'));

  x.range([0, width]).nice();
  y.range([height, 0]).nice();
  x.domain(d3.extent(data, function(d) { return d.day; }));
  y.domain([0, d3.max(data, function(d) { return d.tasks; })]);

  svg.select('.linePath').attr('d', line(data));
}

Note that the width and height are retrieved from the SVG element style, which in this case is the width of the <td> parent container. Range and Domain are important concepts in D3, mapping your data to the available X and Y axes. For the burndown chart we want the Y axis to begin at 0, even though our data range is 4-25, so the chart communicates that tasks were incomplete at the end of the sprint. For the X axis, D3’s extent function is used to dynamically find the min and max data values.

HTML

The Sparkline Directive is included as an attribute of the span element, so D3 will output the SVG as a child of this span, using the array of burn down data provided to the data element.

CSS

The SVG component output by D3 is a standard HTML element and can be targeted with CSS. The following style sizes the SVG element to the width of its parent.

.chart svg {
  width: 100%;
  height: 55px;
}

Conclusion

D3 is not the most intuitive of technologies to learn, with a number of techniques to master before being able to create a visualisation. Begin by observing the many examples available on the internet to understand the fundamentals and then make something uniquely your own. The sparkline discussed in this post covers the fundamentals of D3 and sets us up to explore more sophisticated visualisations.

Source code for the Sparkline is available on GitHub

Published by Mark Brownsword

I've been working as an enterprise developer for about 15 years, always using .NET platform and mostly using Oracle databases. My degree is in Business Studies, majoring in information systems, where I learnt the fundamentals of software engineering for building systems for business. In my spare time I like to play around with games programming because the emphasis is much more on pure computer science.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s