how to create adaptive pie donut charts with transitions in d3 (interactive tutorial and example)

Following up with my last blog post about adaptive line chart graphs (link), I decided to apply this same concept of adaptive charts to a pie / donut chart. The goal is to create a chart similar to the one below, which updates to any new data thrown at it.

NOTE: for mobile devices, view the visual here: link.

generate data

The best way to test the functionality of your graph is to generate new pseudo-data at a set interval and update the graph at that interval. For those unfamiliar with quick data generation in D3, I recommend you take a look at my previous blog (link). For this example, we need to create a single dimensional dataset. Typically pie / donut chart data would be multi-dimensional, at the very least, because it would contain a description of each data point however I will ignore it for this example. The data generation function below takes in one argument, the desired number of data points, and returns an array with that number of data elements. Data is multiplied by 100 to better exaggerate the visuals.

setup page elements

Now, we can start to setup up our page elements, such as the svg dimensions. We need to translate our pie / donut chart container because by default, the center is set to the top left corner of our svg container. It’s good practice to make the translation amounts dynamic based on the page dimensions, but I will gloss over it purpose of this example.

create initial chart

Next we can specify our color scale and set up our pie / donut and arc functions. The thickness of the donut chart is dependent on the difference between the outer and inner radii. Incorporating padding into the chart can be achieved by setting the outer radius as some percentage of the total container dimension (in this case, 90%).
Hint: If you desire a pie chart rather than a donut chart, you can set the inner radius value to 0.

The pie layout function calculates the location of each pie segment and the arc generator determines the path of the arc that is drawn and filled. Finally, we enter the data and save each angle to the _current property of the current element. The reason for this will become evident when we introduce the render function.

Your graph should change each time the page is refreshed and should look something like this:

create render function

Now what we must do is encapsulate the remaining portion of the program in a function, which I have called render. render will be invoked when we want to generate a new dataset and update our graph.

Oh no! Why are the arc segments not expanding to fill in the voids? Turns out we need to transition any old paths to the new paths before entering or removing any new paths.

smooth transition

The graph still does not transition properly, but we’re getting closer. The grand finale is curtosey of Mike Bostock (@mbostock), who came up with an elegant solution to this transition problem. Storing the angles in _current allows us to retrieve the existing angles and use them when transitioning to new angles. Instead of applying the arc function to the .attr of d when we re-render, we will apply the arcTween function to the .attrTween property of d.

complete code

And that’s it! Now your pie chart updates and animates in a visually pleasing way. If you’re interested in seeing the complete code, go ahead and check out my bl.ock: