I think this comes close to what you aimed to achieve: http://jsfiddle.net/4PS53/3/
The changes needed are the following:
function getAngle(d) {
// Offset the angle by 90 deg since the '0' degree axis for arc is Y axis, while
// for text it is the X axis.
var thetaDeg = (180 / Math.PI * (arc.startAngle()(d) + arc.endAngle()(d)) / 2 - 90);
// If we are rotating the text by more than 90 deg, then "flip" it.
// This is why "text-anchor", "middle" is important, otherwise, this "flip" would
// a little harder.
return (thetaDeg > 90) ? thetaDeg - 180 : thetaDeg;
}
slices.append("text")
.style("font-size", "10px")
.attr("x", function(d) { return d[1]; })
// Rotate around the center of the text, not the bottom left corner
.attr("text-anchor", "middle")
// First translate to the desired point and set the rotation
// Not sure what the intent of using this.parentNode.getBBox().width was here (?)
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")" + "rotate(" + getAngle(d) + ")"; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d){return d[2]})
.attr("pointer-events","none");
Now to make it work with zooming, where the reference point changes, we need a bit more infrastructure.
- Make the
g.form-container
and not only thepath.form
visible/invisible. This means that we do not have to worry about making the labels disappear separately. (I have added theform-container
class.) Calculate the new point and calculate the
centroid
androtation
for it. This is a bit more tricky, but not too difficult:function change_ref(data_point, reference_point) { return [ get_start_angle(data_point, reference_point), get_stop_angle (data_point, reference_point), data_point[2], get_level (data_point, reference_point) ]; } // And while doing transitioning the `text.label`: svg.selectAll('.label') .filter( function (b) { return b[0] >= new_ref[0] && b[1] <= new_ref[1] && b[3] >= new_ref[3]; } ).transition().duration(1000) .attr("transform", function(b) { var b_prime = change_ref(b, d); return "translate(" + arc.centroid(b_prime) + ")" + "rotate(" + getAngle(b_prime) + ")"; })
I have added the class
label
to thetext
.
Updated Demo: http://jsfiddle.net/4PS53/6/
However, I have argued that there might be better ways of presenting this data, esp. if you are allowing zooming and panning: D3 put arc labels in a Pie Chart if there is enough space