We will learn how to Create a simple Donut Chart using D3.js . Even though the Pie chart is not very efficient in data visualization the Donut Charts are sometimes very helpful. We have learned how to Create a Simple Pie Chart using D3.js in our previous post.
In this article we will take our basic pie chart and convert that to a donut chart. We will also add the legends and animate the Donut Chart using attrTween
function.
We will use the below dataset to create our Donut Chart.
1 2 3 4 5 6 7 |
var dataset = [ { name: 'IE', percent: 39.10 }, { name: 'Chrome', percent: 32.51 }, { name: 'Safari', percent: 13.68 }, { name: 'Firefox', percent: 8.71 }, { name: 'Others', percent: 6.01 } ]; |
Now create the basic chart using following code. We will use the padAngle()
function to add the padding to the Pie layout.This time we will use the d3.scale.category10()
function for the color scale.We will also set the innerRadius()
to the arc to create the Donut Chart instead of the Pie Chart.
Please refer the previous post on how to Create a Simple Pie Chart using D3.js for more detailed step by step explanation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
var pie=d3.layout.pie() .value(function(d){return d.percent}) .sort(null) .padAngle(.03); var w=300,h=300; var outerRadius=w/2; var innerRadius=100; var color = d3.scale.category10(); var arc=d3.svg.arc() .outerRadius(outerRadius) .innerRadius(innerRadius); var svg=d3.select("#chart") .append("svg") .attr({ width:w, height:h, class:'shadow' }).append('g') .attr({ transform:'translate('+w/2+','+h/2+')' }); var path=svg.selectAll('path') .data(pie(dataset)) .enter() .append('path') .attr({ d:arc, fill:function(d,i){ return color(d.data.name); } }); |
Here is the HTML for the chart.
1 2 3 4 |
<div class="widget"> <div class="header">Browser Market Share</div> <div id="chart" class="chart-container"></div> </div> |
Let’s see the demo here.
See the Pen Simple Donut Chart by Abhisek Jana (@adeveloperdiary) on CodePen.19706
Now we will use the the attrTween() function to animate the chart. We will use the d3.interpolate() method to calculate the intermidiate steps. The transition duration has been set to 1s. Add the following code, refresh the html. You can see the chart is now animating nicely.
1 2 3 4 5 6 7 8 |
path.transition() .duration(1000) .attrTween('d', function(d) { var interpolate = d3.interpolate({startAngle: 0, endAngle: 0}, d); return function(t) { return arc(interpolate(t)); }; }); |
The Next step is to add the legends once the animation has been completed. We will use the setTimeout()
function to create our legends after 1sec so that it will be added after the transition has been completed.
At first we will add the percentage at the center of the arc, which is similar to the previous chart we created. This time we will also animate the text. Here is the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var text=svg.selectAll('text') .data(pie(dataset)) .enter() .append("text") .transition() .duration(200) .attr("transform", function (d) { return "translate(" + arc.centroid(d) + ")"; }) .attr("dy", ".4em") .attr("text-anchor", "middle") .text(function(d){ return d.data.percent+"%"; }) .style({ fill:'#fff', 'font-size':'10px' }); |
In order to add the legends we will draw a text and a rectangle. We will add a group and then add the text and the rect to the group. The position of the group is calculated dynamically. We will pass the color.domain()
in the data()
function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var legendRectSize=20; var legendSpacing=7; var legendHeight=legendRectSize+legendSpacing; var legend=svg.selectAll('.legend') .data(color.domain()) .enter() .append('g') .attr({ class:'legend', transform:function(d,i){ //Just a calculation for x and y position return 'translate(-35,' + ((i*legendHeight)-65) + ')'; } }); |
Now add the text and the rectangle to the group.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
legend.append('rect') .attr({ width:legendRectSize, height:legendRectSize, rx:20, ry:20 }) .style({ fill:color, stroke:color }); legend.append('text') .attr({ x:30, y:15 }) .text(function(d){ return d; }).style({ fill:'#929DAF', 'font-size':'14px' }); |
Click on Run Pen
to see the full demo.
See the Pen Basic Donut Chart by Abhisek Jana (@adeveloperdiary) on CodePen.
You can find the entire code below:
1 2 3 4 |
<div class="widget"> <div class="header">Browser Market Share</div> <div id="chart" class="chart-container"></div> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
var dataset = [ { name: 'IE', percent: 39.10 }, { name: 'Chrome', percent: 32.51 }, { name: 'Safari', percent: 13.68 }, { name: 'Firefox', percent: 8.71 }, { name: 'Others', percent: 6.01 } ]; var pie=d3.layout.pie() .value(function(d){return d.percent}) .sort(null) .padAngle(.03); var w=300,h=300; var outerRadius=w/2; var innerRadius=100; var color = d3.scale.category10(); var arc=d3.svg.arc() .outerRadius(outerRadius) .innerRadius(innerRadius); var svg=d3.select("#chart") .append("svg") .attr({ width:w, height:h, class:'shadow' }).append('g') .attr({ transform:'translate('+w/2+','+h/2+')' }); var path=svg.selectAll('path') .data(pie(dataset)) .enter() .append('path') .attr({ d:arc, fill:function(d,i){ return color(d.data.name); } }); path.transition() .duration(1000) .attrTween('d', function(d) { var interpolate = d3.interpolate({startAngle: 0, endAngle: 0}, d); return function(t) { return arc(interpolate(t)); }; }); var restOfTheData=function(){ var text=svg.selectAll('text') .data(pie(dataset)) .enter() .append("text") .transition() .duration(200) .attr("transform", function (d) { return "translate(" + arc.centroid(d) + ")"; }) .attr("dy", ".4em") .attr("text-anchor", "middle") .text(function(d){ return d.data.percent+"%"; }) .style({ fill:'#fff', 'font-size':'10px' }); var legendRectSize=20; var legendSpacing=7; var legendHeight=legendRectSize+legendSpacing; var legend=svg.selectAll('.legend') .data(color.domain()) .enter() .append('g') .attr({ class:'legend', transform:function(d,i){ //Just a calculation for x & y position return 'translate(-35,' + ((i*legendHeight)-65) + ')'; } }); legend.append('rect') .attr({ width:legendRectSize, height:legendRectSize, rx:20, ry:20 }) .style({ fill:color, stroke:color }); legend.append('text') .attr({ x:30, y:15 }) .text(function(d){ return d; }).style({ fill:'#929DAF', 'font-size':'14px' }); }; setTimeout(restOfTheData,1000); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
body { background-color: #1B1F2A; width: 100%; font-family: 'Roboto', sans-serif; height: 100%; } .widget { margin: 0 auto; width:350px; margin-top:50px; background-color: #222D3A; border-radius: 5px; box-shadow: 0px 0px 1px 0px #06060d; } .header{ background-color: #29384D; height:40px; color:#929DAF; text-align: center; line-height: 40px; border-top-left-radius: 7px; border-top-right-radius: 7px; font-weight: 400; font-size: 1.5em; text-shadow: 1px 1px #06060d; } .chart-container{ padding:25px; } .shadow { -webkit-filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.5) ); filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.5) ); } |
Taufik says
Hello A Developer Diary,
I am new to JavaScript and Web Technologies.
I want to learn more about chart drawings.
I had background from C, C++ and Perl programming.
From where should I start to get proficiency in Dashboard implementations using JavaScript?
Thanx and Regards,
Taufik
Emily says
What version of d3 is this example? Thanks!
Annjalie says
Hi Abhisek,
Thanks for this great example. It looks really cool! I’m trying to implement it but it’s giving me some errors. It says “path” is null just before the transition part. Would you please be able to help? Thank you so much. I’ll be happy to share my email address with you.
Abhisek Jana says
Hi Annjalie,
Please send me your code at adeveloperdiary@gmail.com and I will take a look at it.
Thanks,
Abhisek Jana
Edouard says
Hi, plz how to cchange sections colors ?