问题
I've looked for over 3 hours now trying to find a way to chain transitions indefinitely...
My only solution is wrapping the code in a function, then repeatedly calling the function with setInterval or waiting for the transition 'end' event
Example one liner:
d3.selectAll('circle').data([1,2,3]).enter().append('circle').attr('cy':function(d){return d * 100},'cx':function(){Math.random() * window.innerWidth},'r':'10px')
//sets initial locations for circles that are created to match data array
.transition().attr('cy':function(){Math.random() * window.innerHeight},'cx':function(){Math.random() * window.innerWidth}})
.transition().attr('cy':function(){Math.random() * window.innerHeight},'cx':function(){Math.random() * window.innerWidth}})
.transition().attr('cy':function(){Math.random() * window.innerHeight},'cx':function(){Math.random() * window.innerWidth}})
.transition().attr('cy':function(){Math.random() * window.innerHeight},'cx':function(){Math.random() * window.innerWidth}})
.transition().attr('cy':function(){Math.random() * window.innerHeight},'cx':function(){Math.random() * window.innerWidth}})
//I'm looking for something that can repeat the transition without using setInterval)
回答1:
One way or another, I think you're going to have to wrap your transition settings in a function, so that you can call it recursively. However, @Jon S. is right, you can use the transition's "end" event instead of a separate timer.
The complication is that the callback function in transition.each("end", callback)
is (as the method name suggests) called for each element in the array. A simple check can make sure the recursion only happens once, for the first element, and doesn't branch indefinitely.
Here's an example: http://fiddle.jshell.net/UD9ng/1/
Key code:
var moving = false;
function move(selection) {
moving = true;
selection.transition().duration(5000).ease("sin-in-out")
.attr("cx", function(){return Math.random()*width;})
.attr("cy", function(){return Math.random()*height;})
//.call(move); //stack overflow error!
.each("end", function(d,i){
if (!i) circles.call(move); //only run for i==0
});
}
As you can see from the comments, I tried using the transition's .call()
method (which invokes a function once for the entire transition object), but there is no way currently to delay that call until the end of the transition, so repeated sub-transition calls were being added to a queue until the console spit out an error with a huge stack trace behind it. The weird thing was, it didn't look like anything was wrong, since all the queued-up transitions were still moving smoothly -- but they would have run out of transitions eventually.
The each/end approach -- with the recursive function called on the original selection -- replaces the finished transition instead of chaining to it, so it can continue indefinitely without consuming increasing resources.
来源:https://stackoverflow.com/questions/21211560/d3-data-driven-documents-transition-repetition