Domanda

I'm working on a proof of concept that depicts some circles inside an svg element that move and change colour when i click on the svg element. That all works fine. I also wanted to add a mouseover event which changed the colour of the circle to red for example. That worked too.

However, when i updated the position/colour of the circles (those were random-generated values) the mouseover event had disappeared. I figured it was because d3 replaced the old circles with new ones and i didn't define my mouseover eventlistener in the update function, so i just copied it from the 'initialize' code. But then something weird happened. I got an 'Uncaught TypeError: undefined is not a function' in the console, and the eventlistener didn't work. This is the code:

svg2.on("click", function(){
svg2["color"] = d3.rgb(Math.random()*256,Math.random()*256,Math.random()*256);

var circles = svg2.selectAll("circle");
console.log(circles);
circles.transition()
.duration(500)
.ease("circle")
.style("fill",svg2["color"])
.attr("cx",function(d,i){
  var val = (Math.random()<0.5)?-Math.random()*50:Math.random()*50;
  if(val+d[0]-d[2] >w2 || val+d[0]-d[2]<0) return d[0];
  else return d[0]+val;
})
.attr("cy",function(d,i){
  var val = (Math.random()<0.5)?-Math.random()*50:Math.random()*50;
  if(val+d[1]+d[2] > h2 || val+d[1]-d[2]< 0) return d[1];
  else return d[1]+val;
})
.attr("r",function(d){
return d[2];
})
///////// ERROR CAUSED BELOW //////////////
.on("mouseover",function(){
 d3.select(this).style("fill",svg2.color);   
 });
});

I did nothing wrong i thought, because i did exactly as i did before: i selected all my circles, set their attributes and defined an eventlistener with .on(), but it didn't work.

I was able to solve this by defining a function that does exactly as above and call it at the end of my 'update' code. This is the function:

function updateListeners(circles){
    circles.on("mouseover",function(){
         d3.select(this).style("fill","red");   
    })
    .on("mouseout",function(){
         d3.select(this).style("fill",svg2.color);   
    })
}

So it seems i can update eventlisteners of an object in a called function, but not in the callback function provided with the 'click' event?

Question: Why is that exactly? It's the exact same selection, but why does the 'hard' way work, and the 'easy' way doesn't?

È stato utile?

Soluzione

You are adding the event listener after the .transition() in the first case. In the 'hard' case you are assigning the event listener to the selection without a transition. I don't think it works to transition into an event listener.

Try registering the event listener before the call to .transition() and see if that works for you.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top