Transition not finishing if exit is called before the duration runs out

109 views
Skip to first unread message

Andriy Drozdyuk

unread,
Oct 30, 2012, 4:27:52 PM10/30/12
to d3...@googlegroups.com
Has anyone ever encountered the following problem.

Say you have a 
> dataset = [1,2,3,4]

and your draw function, that "animates" the removal of data points from the dataset with a delay of 1000:
> function drawScatterplot() {
>   circles = svg.select("circle").data(dataset)
>   circles.enter() //Logic for enter...
>   circles.exit().transition.delay(1000).attr("r", 0).remove()

now I run a callbck function, with a delay LESS than 1000, say 200:
> setInterval( function(){ dataset.splice(0,1); drawScatterplot();},  200 );

Now, my "exit" animation never finishes. It only does 200 ms worth of animation, and then stops there (because setInterval calls the "exit" condition again!)

What am I doing wrong? 
Any help appreciated.

Scott Cameron

unread,
Oct 30, 2012, 4:48:26 PM10/30/12
to d3...@googlegroups.com
Hi Andriy,

There can only be one transition running at a time on any given DOM element.  By invoking drawScatterplot again after only 200 ms you're replacing the running transition with a new transition.  Your 1000ms transition will never reach the end because you will continue to interrupt it every 200ms.

Check out Mike's excellent new Transitions tutorial for more detail.

Cheers,
scott

Andriy Drozdyuk

unread,
Oct 30, 2012, 4:53:50 PM10/30/12
to d3...@googlegroups.com
Thank you, Scott!
I understand what you are saying, and I've read the tutorial.
The problem I am having is imagine if the "drawScatterplot" is not actually controlled by me - say it's called in response to a data change on the server, or a user click. I would still like all my old circles to go through a complete cycle of animation and removal.

I just thought I'd ask if anyone had a similar "problem"; if it's not possible - I understand. I'll try to look for workarounds.

Thank you!

Scott Cameron

unread,
Oct 30, 2012, 5:07:54 PM10/30/12
to d3...@googlegroups.com

Actually, I missed the dataset.splice part when I read your original post.  I think the real problem is that you are not specifying a key when you bind the data so it is using the array index as a default key.  If you choose a more meaningful key to identify data points then your enter, exit and update selections will be meaningful in the context of your real data and the actions you take on each should be correct.  This explains how it works:  Object Constancy.

If your data doesn't really have an identity that is useful as a key (maybe it's randomly generated data, say) and you really want to just remove everything when an action like a user click happens, you can always play around with the selector to make sure you don't pick up the same points twice.  For example, if you use this as a selector:

circles = svg.select("circle.datapoint").data(dataset)

And then you add the "datapoint" class to your enter selection and remove it from your exit selection just before you start the exit transition you won't select the exiting points in the next iteration. 

scott

Andriy Drozdyuk

unread,
Oct 30, 2012, 5:59:53 PM10/30/12
to d3...@googlegroups.com
Thank you! What a wonderful suggestion to use CSS classes to keep track of recycled points! Brilliant.
I can't thank you enough, it works beautifully!
Reply all
Reply to author
Forward
0 new messages