I'm working on a donut chart using D3.js. I have it doing everything fine except that the labels for each section are being drawn on top of each other as the pieces get smaller. You can see this in the screenshot below.
I can't figure out how to get more spacing or flip the label to the other side.
Here is the relevant code.
var slice = chart.select(".slices").selectAll("path.slice").data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d,i) {return color(i);})
.attr("class", "slice")
.attr("data-label", function(d){ return d.data.label();})
.attr("data-value", function(d){ return d.data.value();});
slice.transition().ease("exp").duration(animationTime * 2)
.attrTween("d", function(d){
var interpolater = d3.interpolate({startAngle: 2*Math.PI, endAngle: 2*Math.PI}, d);
return function(t) {
return arc(interpolater(t));
}
})
slice.exit().remove();
var text = chart.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.style("font-size", "11pt")
.style("fill", "#8FA1A9")
.text(function(d) {
if(d.data.value() != 0){
return d.data.label();
}
else{
return "";
}
});
function midAngle(d){
return d.startAngle + (d.endAngle - d.startAngle)/2;
}
text.transition().duration(500)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.75 * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate("+ pos +")";
};
})
.styleTween("text-anchor", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start":"end";
};
});
text.exit().remove();
var polyline = chart.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline.enter()
.append("polyline")
.style("fill", "none")
.style("stroke-width", "2px")
.style("stroke", "#8FA1A9")
.style("opacity", "0.4");
polyline.transition().duration(500)
.attrTween("points", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.75 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit().remove();
};
I will be honest and say I don't entirely understand all the code in there for drawing the lines and labels, so any insight or help is appreciated.