Note that there are some explanatory texts on larger screens.

plurals
  1. POd3js Redistributing labels around a pie chart
    text
    copied!<p>I'm using d3.js to create a donut chart with labels on the outside. Using some trigonometry based on the centroids of each slice of the pie, I position the labels. </p> <pre><code>g.append("g") .attr("class", "percentage") .append("text") .attr("transform", function(d) { var c = arc.centroid(d); var x = c[0]; var y = c[1]; var h = Math.sqrt(x*x + y*y); return "translate(" + (x/h * obj.labelRadius) + ',' + (y/h * obj.labelRadius) + ")"; } ) .attr("dy", ".4em") .attr("text-anchor", function(d) { return (d.endAngle + d.startAngle)/2 &gt; Math.PI ? "end" : "start"; } ) .text(function(d) { return d.data.percentage+"%"; }); </code></pre> <p>What I'm ultimately trying to accomplish is to rearrange labels that are outside the edges of the pie chart, to prevent overlaps.</p> <p><img src="https://i.stack.imgur.com/8Hwpl.jpg" alt="enter image description here"></p> <p>One of the ways I have tried to solve the problem is to define set "anchor points", where labels can be positioned, guaranteeing that they will no overlap. Problem is mapping the centroids to the anchors and preserving some sense of visual correspondence between the slices and the labels (Specially difficult when slices are slim).</p> <p><img src="https://i.stack.imgur.com/9vatK.jpg" alt="enter image description here"></p> <p>Image above shows the possible location of the anchors (centroids of the slices shown). With these positions it is impossible to have an overlap.</p> <p>Adding complexity to the problem is the fact that when labels (they're horizontal) are close to the top or bottom of the pie, they are more easily overlapped, than when they are on the right or left of the pie. </p> <p>Any ideas on how to approach this problem?</p> <p>[EDIT] Following the suggestion of meetamit, I implemented the following:</p> <pre><code>.attr("dy", function(d) { var c = arc.centroid(d); var x = c[0]; var y = c[1]; var h = Math.sqrt(x*x + y*y); var dy = y/h * obj.labelRadius; dy=dy*fontSizeParam*.14/heightParam); return (dy)+"em"; }) </code></pre> <p>It helps a bit, and gives some room to the labels, still looking for a solution that will cover all cases though...</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload