D3.js Starter Pack

Let me preface this by saying D3.js and Mike Bostock are amazing. However, it can be difficult at first to get your footing with this library, and actually create a visualization without feeling like you're just stabbing at SVGs with a butter knife in the dark. This post distills down D3's main concepts to help you internalize the flow, without diving too far into specific use cases. You can use this as a guide while building your first, or fifteenth, visualization. If you don't know where to start, take a look at these basic examples.

Selections

D3's selection methods take any CSS selector and return the matching elements. .select() returns the first matching element and .selectAll() returns an array of all matching elements.

d3.selectAll('div.goat')
// => [array of divs with the class goat]

SVGs

The most important thing to understand about SVGs is that they are not just images. They are documents, or objects, written in XML markup, and can be created in a text editor or software like Adobe Illustrator. The size and position of an SVG relies on a coordinate system, with (0,0) at the top left. If you don't know about SVG shapes, it is essential that you read this or something like it.

Key Methods

These three methods are all you need to create an endless variety of things.

.append() appends an SVG, or whatever, to a selection.

var goat = d3.select('.goat').append('svg');

.attr() sets any valid HTML attribute of the selection.

goat.attr('height', 300)
    .attr('width', 400);

.style() adds CSS to the selection.

goat.style('background', '#ccc');

I use this method when I need to apply styles programmatically because it takes a function. For styling that doesn't vary according to the data (as above), I just add a CSS class with .attr('class', 'className') and put my styling in an external stylesheet like a law abiding developer.

Data Binding

While with the above methods you can make a lot of really pretty visualizations and art, you won't be able to create a true data visualization until you utilize D3's data binding methods.

.data() parses and counts a given dataset for the proceeding functions. After this method is called, the variables "d" and "i" represent a single element in the dataset and its index.

.enter() creates placeholder elements corresponding to the data values provided.

Given a dataset, an array of numbers perhaps, say you want to append circles to the goat SVG we created earlier that correspend in some way (position, size, whatever) to each element in the array. I like to think about data binding in four steps:

goat.selectAll('circle')   // Make an "empty selection" of the elements you intend to append
    .data(dataset)         // Join the data to the selection
    .enter()               // Create placeholder elements for each datum
    .append('circle')      // Append an SVG (or whatever you want) for each datum

After those steps are complete, you can access any element in the dataset array and do whatever you want with it.

    // Position the circle on the x-axis at d pixels
    .attr('cx', function(d) { return d; })  
    // Position the circle on the y-axis at d + 10 pixels
    .attr('cy', function(d) { return d + 10 })
    // Set the radius of the circle to be d * its index
    .attr('r', function(d, i) { return d * i })) 
    // Set the color of the circle with d/2 as the blue channel
    .attr("fill", function(d) { return "rgb(0, 0, " + (d/2) + ")"; });

Scales

You need scales to map data to a visual range (pixel position, size, color, etc). Quantitative scales have a continuous domain, as in the case of a set of numerical data or dates.

A linear scale is quantitative and probably the most useful. Below is a use case where we create a scale for the axis. The range here is the 0 and the height of the SVG, meaning we do not want to map any data outside of these visual boundaries. The domain is simply an array with the maximum and minimum values in the dataset, which are to be plotted within the range.

var yDomain = d3.extent(data); // Returns an array with the minimum and maximum values in 'data'

var scale = d3.scale.linear()
    .range([height, 0]); // Height is the minimum because you are drawing top down
    .domain(yDomain);

Understand the differences between linear, time and ordinal scales.

Axes

The D3 axis component does an incredible amount of work for you. Using the scales you create and various axis methods, you can draw axes, ticks and labels in any way imaginable. Using the scale variable we set above, here is an example:

var yAxis = d3.svg.axis()
  .scale(scale)
  .orient('left') // Positions the y-axis on the left
  .ticks(10);     // Limits the amount of ticks on the y-axis to 10

goat.append('g')  // Appends a "group" element used to contain other elements, such as ticks
    .attr('class', 'y-axis')
    .call(yAxis);

Resources: