Simple animated donut chart using D3
by Rishabh Sharma
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<div id="donut" data-donut="19"></div>
CSS
body {
font-family: sans-serif;
margin: 0 auto;
width: 960px;
padding-top: 10%;
background-color: #fff;
}
text {
font-family: sans-serif;
font-size: 4rem;
letter-spacing: -.2rem;
font-weight: 600;
line-height: 12rem;
fill: #0096D6;
}
#donut {
width: 28rem;
height: 28rem;
margin: 0 auto;
}
path.color0 {
fill: #0096D6;
}
path.color1 {
fill: transparent;
}
JavaScript
var duration = 1200,
transition = 200;
drawDonutChart(
'#donut',
$('#donut').data('donut'),
280,
280,
".4em"
);
function drawDonutChart(element, percent, width, height, text_y) {
width = typeof width !== 'undefined' ? width : 280;
height = typeof height !== 'undefined' ? height : 280;
text_y = typeof text_y !== 'undefined' ? text_y : "-.10em";
var dataset = {
lower: calcPercent(0),
upper: calcPercent(percent)
},
radius = Math.min(width, height) / 2,
pie = d3.layout.pie().sort(null),
format = d3.format(".0%");
var arc = d3.svg.arc()
.innerRadius(radius - 40)
.outerRadius(radius)
pie.startAngle(180 * (Math.PI/180));
pie.endAngle(540 * (Math.PI/180));
var svg = d3.select(element).append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var path = svg.selectAll("path")
.data(pie(dataset.lower))
.enter().append("path")
.attr("class", function(d, i) { return "color" + i })
.attr("d", arc)
.each(function(d) { this._current = d; });
var text = svg.append("text")
.attr("text-anchor", "middle")
.attr("dy", text_y);
if (typeof(percent) === "string") {
text.text(percent);
}
else {
var progress = 0;
var timeout = setTimeout(function () {
clearTimeout(timeout);
path = path.data(pie(dataset.upper));
path.transition().duration(duration).attrTween("d", function (a) {
var i = d3.interpolate(this._current, a);
var i2 = d3.interpolate(progress, percent)
this._current = i(0);
return function(t) {
text.text( format(i2(t) / 100) );
return arc(i(t));
};
});
}, 1000);
}
};
function calcPercent(percent) {
return [percent, 100-percent];
};