Search code examples
javascriptd3.jssvgpie-chartinteractive

How to update labels on d3 pie chart with an interactive legend


I have developed a D3 pie chart. It has an interactive legend clicking on the legend removes or re-enters the corresponding pie segment. My problem is that I cannot figure out how to update the labels when using the legend.

I found this answer particularly helpful, but I still cannot get my own working.

NVd3 pie charts have this functionality, but I am looking for a purely d3 solution.

My code is in this fiddle:

enter image description here

I have included the part I think the problem resides in below:

legend.on('click.updatelabels', function(Task) {                            
    var rect = d3.select(this);                             
    var enabled = true;                                     
    var totalEnabled = d3.sum(chartData.map(function(d) {     
        return (d.enabled) ? 1 : 0;                           
    }));                                                    

    if (rect.attr('class') === 'disabled') {                
        rect.attr('class', '');                               
    } else {                                                
        if (totalEnabled < 2) return;                         
        rect.attr('class', 'disabled');                       
        enabled = false;                                      
    }                                                       

    layoutLabels.value(function (d) { return (d.enabled) ? 1 : 0;  });

    d3.select('Text').selectAll("pieLegend").remove()

    pieLabels.select("text")   
       .attr("transform", function (d) {
           var c = arc.centroid(d),
               x = c[0],
               y = c[1],
               // pythagorean theorem for hypotenuse
               h = Math.sqrt(x * x + y * y);
           return "translate(" + (x / h * labelRadius) + ',' +
              (y / h * labelRadius) + ")";
       })
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      .text(function (d, i) { return ((d.Volume / sum) * 100).toFixed(0) + "%"; });
});    

I would appreciate any help


Solution

  • The issue is here

    layoutLabels.value(function (d) { return (d.enabled) ? 1 : 0;  });
    

    It should be as below so the label values are calculated using the actual corresponding value or assigning 0 to the disabled value

      layoutLabels.value(function(d) {                                 
          if (d.Task === Task) d.enabled = enabled;           
          return (d.enabled) ? d.Volume : 0;                     
      });   
    

    Working jsfiddle below

    https://jsfiddle.net/vncyqudo/