Search code examples
d3.jschartspie-chartdonut-chart

d3 donut/pie chart - drawing a line between arcs


can't figure to find the endpoint of the arc to draw a line from (0,0) to the arc's endpoint..image attached

enter image description here

I could find the centroid of the arc and draw a line but here I want to pull a line to end of arc so that I can extend that line to the left /right side (and then append the circle at line's endpoint)...could't find any such solution over whole google. Any help will be appreciated. Just a hint will do.


Solution

  • When you pass a data array to the pie generator, it returns an array of objects with the following properties:

    • data - the input datum; the corresponding element in the input data array.
    • value - the numeric value of the arc.
    • index - the zero-based sorted index of the arc.
    • startAngle - the start angle of the arc.
    • endAngle - the end angle of the arc.
    • padAngle - the pad angle of the arc.

    From these, you can use startAngle or endAngle to draw your lines, since they hold the arcs' starting points (and endpoints).

    But there is a catch: unlike the regular trigonometric representation, D3 pie generator puts the 0 angle at 12 o'clock:

    The angular units are arbitrary, but if you plan to use the pie generator in conjunction with an arc generator, you should specify angles in radians, with 0 at -y (12 o’clock) and positive angles proceeding clockwise.

    Therefore, we have to subtract Math.PI/2 to get the correct angles.

    In the following demo, the coordinates are calculates using sine and cosine:

    .attr("y2", function(d) {
        return Math.sin(d.startAngle - Math.PI / 2) * (outerRadius)
    })
    .attr("x2", function(d) {
        return Math.cos(d.startAngle - Math.PI / 2) * (outerRadius)
    }) 
    

    Check the demo:

    var data = [10, ,12, 50, 15, 20, 40, 6, 32, 17];
    
    var width = 500,
      height = 400,
      radius = Math.min(width, height) / 2;
    
    var color = d3.scaleOrdinal(d3.schemeCategory10)
    
    var pie = d3.pie()
      .sort(null);
    
    var arc = d3.arc()
      .innerRadius(radius - 100)
      .outerRadius(radius - 50);
    
    var svg = d3.select("body")
      .append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
    var path = svg.selectAll(null)
      .data(pie(data))
      .enter().append("path")
      .attr("fill", function(d, i) {
        return color(i);
      })
      .attr("d", arc);
    
    var lines = svg.selectAll(null)
      .data(pie(data))
      .enter()
      .append("line")
      .attr("x1", 0)
      .attr("y1", 0)
      .attr("y2", function(d) {
        return Math.sin(d.startAngle - Math.PI / 2) * (radius - 50)
      })
      .attr("x2", function(d) {
        return Math.cos(d.startAngle - Math.PI / 2) * (radius - 50)
      })
      .attr("stroke", "black")
      .attr("stroke-width", 1)
    <script src="https://d3js.org/d3.v4.min.js"></script>