In this article, I want to take you through an example project that I built recently — a totally original type of visualization using the D3 library, which showcases how each of these components add up to make D3 a great library to learn.
If you’ve ever seen any of the fabulous interactive stories from the New York Times, you’ll already have seen D3 in action. You can also see some cool examples of great projects that have been built with D3 here.
The learning curve is pretty steep for getting started with the library, since D3 has a few special quirks that you probably won’t have seen before. However, if you can get past the first phase of learning enough D3 to be dangerous, then you’ll soon be able to build some really cool stuff for yourself.
There are three main factors that really make D3 stand out from any other libraries out there:
- Flexibility. D3 lets you take any kind of data, and directly associate it with shapes in the browser window. This data can be absolutely anything, allowing for a huge array of interesting use cases to create completely original visualizations.
- Elegance. It’s easy to add interactive elements with smooth transitions between updates. The library is written beautifully, and once you get the hang of the syntax, it’s easy to keep your code clean and tidy.
- Community. There’s a vast ecosystem of fantastic developers using D3 already, who readily share their code online. You can use sites like bl.ocks.org and blockbuilder.org to quickly find pre-written code by others, and copy these snippets directly into your own projects.
As an economics major in college, I had always been interested in income inequality. I took a few classes on the subject, and it struck me as something that wasn’t fully understood to the degree that it should be.
I started exploring income inequality using Google’s Public Data Explorer …
When you adjust for inflation, household income has stayed pretty much constant for the bottom 40% of society, although per-worker productivity has been skyrocketing. It’s only really been the top 20% that have reaped more of the benefits (and within that bracket, the difference is even more shocking if you look at the top 5%).
Here was a message that I wanted to get across in a convincing way, which provided a perfect opportunity to use some D3.js, so I started sketching up a few ideas.
Because we’re working with D3, I could more or less just start sketching out absolutely anything that I could think of. Making a simple line graph, bar chart, or bubble chart would have been easy enough, but I wanted to make something different.
I find that the most common analogy that people tended to use as a counterargument to concerns about inequality is that “if the pie gets bigger, then there’s more to go around”. The intuition is that, if the total share of GDP manages to increase by a large extent, then even if some people are getting a thinner slice of pie, then they’ll still be better off. However, as we can see, it’s totally possible for the pie to get bigger and for people to be getting less of it overall.
My first idea for visualizing this data looked something like this:
The idea would be that we’d have this pulsating pie chart, with each slice representing a fifth of the US income distribution. The area of each pie slice would relate to how much income that segment of the population is taking in, and the total area of the chart would represent its total GDP.
However, I soon came across a bit of a problem. It turns out that the human brain is exceptionally poor at distinguishing between the size of different areas. When I mapped this out more concretely, the message wasn’t anywhere near as obvious as it should have been:
Here, it actually looks like the poorest Americans are getting richer over time, which confirms what seems to be intuitively true. I thought about this problem some more, and my solution involved keeping the angle of each arc constant, with the radius of each arc changing dynamically.
Here’s how this ended up looking in practice:
I want to point out that this image still tends to understate the effect here. The effect would have been more obvious if we used a simple bar chart:
However, I was committed to making a unique visualization, and I wanted to hammer home this message that the pie can get bigger, whilst a share of it can get smaller. Now that I had my idea, it was time to build it with D3.
So, now that I know what I’m going to build, it’s time to get into the real meat of this project, and start writing some code.
You might think that I’d start by writing my first few lines of code from scratch, but you’d be wrong. This is D3, and since we’re working with D3, we can always find some pre-written code from the community to start us off.
This file is written in D3 V3, which is now two versions out of date, since version 5 was finally released last month. A big change in D3 V4 was that the library switched to using a flat namespace, so that scale functions like
d3.scale.ordinal() are written like
d3.scaleOrdinal() instead. In version 5, the biggest change was that data loading functions are now structured as Promises, which makes it easier to handle multiple datasets at once.
To avoid confusion, I’ve already gone through the trouble of creating an updated V5 version of this code, which I’ve saved on blockbuilder.org. I’ve also converted the syntax to fit with ES6 conventions, such as switching ES5 anonymous functions to arrow functions.
Here’s what we’re starting off with already:
I then copied these files into my working directory, and made sure that I could replicate everything on my own machine. If you want to follow along with this tutorial yourself, then you can clone this project from our GitHub repo. You can start with the code in the file
starter.html. Please note that you will need a server (such as this one) to run this code, as under the hood it relies on the Fetch API to retrieve the data.
Let me give you a quick rundown of how this code is working.