Developing dank datavis
with
d3.js

Richard Westenra

twitter.com/richardwestenra   •   github.com/richardwestenra

But first, let's discuss

principles

1. Just show the data

2. Be honest

The Lie factor

3. Don't make me think

Napoleon

Compare:

Rugby Six Nations Head to Head

vs

An iPod visualised as Vinyl

Working with data

Importing data


var data; // a global

d3.csv('path/to/file.csv', function(error, json) {
  if (error) {
    return console.warn(error);
  }
  data = json;
  visualizeit();
});
        

Works for JSON, CSV, TSV, XML, HTML, text, etc.

See github.com/mbostock/d3/wiki/Requests

Format data before use


var rawData = [
  {n: 'bunnies', c: 1},
  {n: 'kittens', c: 2},
  {n: 'puppies', c: 2},
  {n: 'cows', c: 0}
];

var formattedData = data.map(function (d){
  return {
    name: d.n.toUpperCase() + '!!!',
    cuteness: ['Not very cute', 'Cute', 'Very cute!!!'][d.c]
  };
});
        

Selections


d3.select('ul').selectAll("li")
        

Binding data


d3.select('ul').selectAll("li").data(['foo','bar','baz'])
        

See bost.ocks.org/mike/join and bost.ocks.org/mike/circles


d3.select('ul')
  .selectAll('li')
  .data(['foo','bar','baz'])
  .enter()
  .append('li')
  .text(function (d) {
    return d;
  });
        


  • foo
  • bar
  • baz

Exit, Enter, update

Exit, Enter, update


var rect = svg.selectAll('rect')
  .data(data);

rect.exit()
  .remove();

rect.enter()
  .append('rect')
  .attr('y', function(d) { return d.y; });

rect.attr('width', function(d) { return d.width; });
        

Transitions

Transitions


d3.selectAll('rect')
  .data(randomData)
  .enter()
  .append('rect')
  .attr('width',0)
  .transition()
  .duration(600)
  .delay(function (d,i){ return i * 200;})
  .attr('width', function (d){ return x(d);});
        

Scales

are functions that map from an input domain to an output range


Input: Domain!

Output: Range!

Quantitative


var x = d3.scale.linear()
  .domain([12, 24])
  .range([0, 720]);

x(16); // 240
        

Ordinal


var x = d3.scale.ordinal()
  .domain(['A', 'B', 'C', 'D'])
  .range([0, 10, 20, 30]);

x('B'); // 10
        

Maps!

GeoJSON & TopoJSON


See Mike Bostock's Let's Make a Map

Layouts!

Use the force, Luke!

See mbostock.github.io/d3/talk/20110921

Collision detection

0.05
0
0.9

See bl.ocks.org/mbostock/3231298

Making it responsive

Thanks!


Slides and code:

richardwestenra.com/d3-talk or github.com/richardwestenra/d3-talk

Resources