Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Donut chart with labels our side with polylines d3 v4
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
/* Add shadow effect to chart. If you don't like it, get rid of it. */
svg {
-webkit-filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.3) );
filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.25) );
}
/*Styling for the lines connecting the labels to the slices*/
polyline{
opacity: .3;
stroke: black;
stroke-width: 2px;
fill: none;
}
/* Make the percentage on the text labels bold*/
.labelName tspan {
font-style: normal;
font-weight: 700;
}
/* In biology we generally italicise species names. */
.labelName {
font-size: 0.9em;
font-style: italic;
}
</style>
</head>
<body>
<script>
// Feel free to change or delete any of the code you see in this editor!
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500)
.append("g");
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var width = 500;
var height = 400;
var radius = Math.min(width, height)/2;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var data = [26,25,10,30,30,50,33,56,38];
var pie = d3.pie().sort(null).value(d => d);
var arc = d3.arc().innerRadius(radius*0.8).outerRadius(radius*0.6);
var outerArc = d3.arc()
.outerRadius(radius * 0.9)
.innerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
svg.selectAll('path')
.data(pie(data))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', (d,i)=> color(i));
svg.append('g').classed('labels',true);
svg.append('g').classed('lines',true);
var polyline = svg.select('.lines')
.selectAll('polyline')
.data(pie(data))
.enter().append('polyline')
.attr('points', function(d) {
// see label transform function for explanations of these three lines.
var pos = outerArc.centroid(d);
pos[0] = radius * 0.95 * (midAngle(d) < Math.PI ? 1 : -1);
return [arc.centroid(d), outerArc.centroid(d), pos]
});
var label = svg.select('.labels').selectAll('text')
.data(pie(data))
.enter().append('text')
.attr('dy', '.35em')
.html(function(d) {
return d.data;
})
.attr('transform', function(d) {
var pos = outerArc.centroid(d);
pos[0] = radius * 0.95 * (midAngle(d) < Math.PI ? 1 : -1);
return 'translate(' + pos + ')';
})
.style('text-anchor', function(d) {
return (midAngle(d)) < Math.PI ? 'start' : 'end';
});
svg.append('text')
.attr('class', 'toolCircle')
.attr('dy', -15) // hard-coded. can adjust this to adjust text vertical alignment in tooltip
.html('sdfsd') // add text to the circle.
.style('font-size', '.9em')
.style('text-anchor', 'middle');
function midAngle(d) { return d.startAngle + (d.endAngle - d.startAngle) / 2; }
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment