Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3.js: Stop transitions interrupting on mouseover?

Tags:

d3.js

I'm working with D3's enter/exit selections, and I want to add a transition on mouseover events too.

The problem is that if I mouseover the letters as they are moving, they freeze, because the position transition is interrupted.

Here is a JSFiddle demonstrating the problem: http://jsfiddle.net/uEuE4/1/ and this is the code I'm using to add mouseover events to the update and enter selections:

text
.on('mouseover', function(d) { 
  d3.select(this).transition().duration(100).style('fill', 'yellow');
});

How can I only add the mouseover event handlers once all other transitions are completed, in order to stop the letters freezing?

Any tips for making the code more DRY would be very welcome too.

like image 520
Richard Avatar asked Oct 15 '13 12:10

Richard


1 Answers

I upvoted and agree with @Jason answer, this will try to complete the previous with some clarifications and a simple demo that can be used as playground for multiple transition behaviour.

Inspecting your code you have various animations going on but only two of them need to be named to get rid of all your transitions "colisions",
the two event listeners:

text.on('mouseover', function(d) {
        d3.select(this).transition("texTr").duration(100).style('fill', 'yellow');
});

enter_text.on('mouseover', function(d) {
        d3.select(this).transition("enterTexTr").duration(100).style('fill', 'yellow');
});

The long story is that without names D3 thinks that all the transitions in your code are the same thus it stops the ongoing transition (an example can be a letter transitioning) and replaces it with a new one (for example a fill transition called by the event listener), because the transition name are the same.

But sometimes the desired behaviour is to explicitly stop transition on some elements; this can be done using .interrupt("transitionName"):

.on("mouseover", function() {
        d3.select(this).interrupt("fadeOut")
        .attr("fill", "orange")
})

.on("mouseout", function(d) {
        d3.select(this).transition("fadeOut")
            .duration(5000)
            .attr("fill", "rgb(0, 0, " + (d * 10) + ")");
})

In this case without the interrupt command we can't trigger the fill orange until the fadeOut ends (5 seconds!).

Here the FIDDLE that you can play with :)

like image 182
Daviz Avatar answered Oct 15 '22 15:10

Daviz