Search code examples
javascriptd3.jschartspie-chart

d3.js - Pie chart with interactive legend hover problems


I made d3.js pie chart and related legend with population data popu. When I hover over pie segments I achieved to enlarge related legend square parts and the pie segment itself (larger outerRadius). Now I am trying to do contrary. When I hover over square of legend I want to enlarge square itself and related pie segment as well. Something like this example here https://www.amcharts.com/demos/pie-chart-with-legend/. I will write down just part of the code related to pie chart problem that I have.

var pie = d3.pie()
            .value(function(d) {return d.pop})(popu);

var seg = d3.arc()
             .innerRadius(100)
             .outerRadius(150)
             .padAngle(.1)
             .padRadius(45);

var segover = d3.arc()
               .innerRadius(100)
               .outerRadius(170)
               .padAngle(.1)
               .padRadius(45);

So this part is working great.

svg.append("g")
   .attr("class", "pieChart")
   .attr("transform", "translate(1250,570)")
   .selectAll("path")
   .data(pie) 
   .append("path")
   .attr("class", "pie")
   .attr("id", function(d){return d.data.id})
   .attr("d", seg)
   .on("mouseenter", function(d){
         d3.select(this)
           .transition(10)
           .duration(100)
           .attr("d", segover)
})

Then I tried to change pie chart segment when hovering on legend related segments.

var pieEl = svg.selectAll(".pie");
var piePath = pieEl.nodes();

svg.append("g")
   .attr("class", "legend")
   .attr("transform", "translate(-50,280)")
   .selectAll(".mySquers")
   .data(pie)
   .enter()
   .append("rect")
   .attr("class", "rec")
   .attr("x", 100)
   .attr("y", function(d,i){ return 100 + i*25})
   .attr("width", "15")
   .attr("height", "15")
   .attr("id", function(d,i){ return (popu[d,i].id)})
   .style("fill",function(d,i){
          if (this.id == piePath[i].id){
              return piePath[i].getAttribute("fill")
              }
              })
  .on("mouseenter", function(d){
          for (var i=0; i<piePath.length; i++){                                                                
              if (piePath[i].id == d.data.id){
                  piePath[i].setAttribute("d", segover);
               }}
})

When I tray to setAttribute("d", segover) in DOM instead of d attribute written as string as usually (d="M144.58.....") I have a function (d="function(pie){ _e);}" and on hover pie segment dissapear. But for example if I set attribute fill to red on hover it change and segment is painted. So the notation of code is good. Is there some behavior of d path generated with d3.arc() that I am missing? Any suggestion is welcome.


Solution

  • I think you should be passing your data as an argument in your function. Normally, it is taken as default argument when you return the function directly.

    piePath[i].setAttribute("d", segover(*data associated with segment*));

    svg.append("g")
       .attr("class", "pieChart")
       .attr("transform", "translate(1250,570)")
       .selectAll("path")...
       .attr("d", seg) // this is same as : attr("d", seg(d))
       .on("mouseenter", function(d){
             d3.select(this)
               .transition(10)
               .duration(100)
               .attr("d", segover) // same here
    })