UPDATE (July 18, 2016): The code and API links in these tutorials have been updated to target D3 v4, which was a complete rewrite. The D3 wiki contains a breakdown of the changes from v3.
This post is part of a series that explores some key concepts in D3.js by building up an example, step by step, from a bare-bones pie chart to an interactive, animated donut chart that loads external data. For the enough-with-the-jibber-jabber-show-me-the-code types out there, here's a breakdown of the steps we'll be covering:
- Step 0: Intro
- Step 1: A Basic Pie Chart (Code | Demo)
- Step 2: A Basic Donut Chart (Code | Demo) ← You Are Here
- Step 3: Adding a Legend (Code | Demo)
- Step 4: Loading External Data (Code | Demo)
- Step 5: Adding Tooltips (Code | Demo)
- Step 6: Animating Interactivity (Code | Demo)
NOTE: Because we're building things up step by step, the source code contains
REMOVED comments to annotate the lines that have been added, altered or deleted relative to the previous step.
Food-wise, I prefer pie to donuts , but when it comes to data viz, donut charts have certain advantages. Primarily because the interior can be put to use (which we'll be doing in the next step). But how can we make our pie into a donut?
I suppose we could create a white circle, make sure its z-index is over 9000, and then position it absolutely over top of the pie. That could work, but it's a terrible idea . Instead we're going to make two small changes to the code. First we'll define how wide the donut should be:
var donutWidth = 75;
Next we'll update the
innerRadius definition of
var arc = d3.arc() .innerRadius(radius - donutWidth) // UPDATED .outerRadius(radius);
Ta da! Just like that we've transformed our pie chart into a donut chart. With the
innerRadius value set to 0, you get a pie. In this case we've set it to be 75px less than the
outerRadius, which results in a donut 75px wide.
Given that Step 1 was a lot to take in, I thought it would be good to coast through this step on easy mode . Perhaps it was too simple to even be considered a step, but at any rate we can now march forward to Step 3 or take a peak at the updated code: