Label outside arc (Pie chart) d3.js

后端 未结 8 1378
日久生厌
日久生厌 2020-11-28 03:55

I\'m new to d3.js and I\"m trying to make a Pie-chart with it. I have only one problem: I can\'t get my labels outside my arcs... The labels are positioned with arc.centroid

相关标签:
8条回答
  • 2020-11-28 04:44

    Thanks!

    I found a different way to solve this problem, but yours seems better :-)

    I created a second arc with a bigger radius and used it to position my labels.

    ///// Arc Labels ///// 
    // Calculate position 
    var pos = d3.svg.arc().innerRadius(r + 20).outerRadius(r + 20); 
    
    // Place Labels 
    arcs.append("svg:text") 
           .attr("transform", function(d) { return "translate(" + 
        pos.centroid(d) + ")"; }) 
           .attr("dy", 5) 
           .attr("text-anchor", "middle") 
           .attr("fill", function(d, i) { return colorL(i); }) //Colorarray Labels
           .attr("display", function(d) { return d.value >= 2 ? null : "none"; })  
           .text(function(d, i) { return d.value.toFixed(0) + "%"});
    
    0 讨论(0)
  • 2020-11-28 04:47

    Specifically for pie charts, the d3.layout.pie() function will format data with a startAngle and endAngle attributes. The radius can be whatever you desire (how far out from the center you would like to place the label).

    Combining these pieces of information with a couple trigonometric functions lets you determine the x and y coordinates for labels.

    Consider this gist/block.

    Regarding the x/y positioning of the text, the magic is in this line (formatted for readability):

    .attr("transform", function(d) {
      return "translate(" + 
        ( (radius - 12) * Math.sin( ((d.endAngle - d.startAngle) / 2) + d.startAngle ) ) +
        ", " +
        ( -1 * (radius - 12) * Math.cos( ((d.endAngle - d.startAngle) / 2) + d.startAngle ) ) +
      ")";
     })
    
    • ((d.endAngle - d.startAngle) / 2) + d.startAngle gives us our angle (theta) in radians.
    • (radius - 12) is the arbitrary radius I chose for the position of the text.
    • -1 * the y axis is inverted (see below).

    The trig functions used are: cos = adjacent / hypotenuse and sin = opposite / hypotenuse. But there are a couple things we need to consider to make these work with our labels.

    1. 0 angle is at 12 o'clock.
    2. The angle still increases in a clockwise direction.
    3. The y axis is inverted from the standard cartesian coordinate system. Positive y is in the direction of 6 o'clock - down.
    4. Positive x is still in the direction of 3 o'clock - right.

    That messes things up quite a bit and basically has the effect of swapping sin and cos. Our trig functions then become: sin = adjacent / hypotenuse and cos = opposite / hypotenuse.

    Substituting variable names we have sin(radians) = x / r and cos(radians) = y / r. After some algebraic manipulation we can get both functions in terms of x and y respectively r * sin(radians) = x and r * cos(radians) = y. From there, just plug those into the transform/translate attribute.

    That'll put the labels in the right location, to make them look fancy, you need some styling logic like this:

    .style("text-anchor", function(d) {
        var rads = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
        if ( (rads > 7 * Math.PI / 4 && rads < Math.PI / 4) || (rads > 3 * Math.PI / 4 && rads < 5 * Math.PI / 4) ) {
          return "middle";
        } else if (rads >= Math.PI / 4 && rads <= 3 * Math.PI / 4) {
          return "start";
        } else if (rads >= 5 * Math.PI / 4 && rads <= 7 * Math.PI / 4) {
          return "end";
        } else {
          return "middle";
        }
      })
    

    This will make the labels from 10:30 o'clock to 1:30 o'clock and from 4:30 o'clock to 7:30 o'clock anchor in the middle (they are above and below), the labels from 1:30 o'clock to 4:30 o'clock anchor on the left (they are to the right), and the labels from 7:30 o'clock to 10:30 o'clock anchor on the right (they are to the left).

    The same formulas can be used for any D3 radial graph, the only difference is how you determine the angle.

    I hope this helps anyone stumbling across it!

    0 讨论(0)
提交回复
热议问题