Closed ElPsyCongro closed 5 years ago
This is something I have to do sometimes too and I always end up doing something like this:
const size = selection.size();
const done = 0;
const finalFunction = () => {
console.log('all done');
}
selection
.transition()
.delay(d => {
// return a delay that depends on d
})
.duration(d => {
// return a duration that depends on d
})
.on('end', d => {
// ...
done += 1;
if (done === size) {
finalFunction()
}
}
but I too would like something cleaner.
It would be nice to have something generic so that we can detect if a particular transition is the first or the last one like:
const transition = selection.transition();
transition
.delay(d => {
// return a delay that depends on d
})
.duration(d => {
// return a duration that depends on d
})
.on('start', d => {
if (transition.isFirst) { // ... }
if (transition.isLast) { // ... }
})
.on('end', d => {
if (transition.isFirst) { // ... }
if (transition.isLast) { // ... }
})
so keeping that count on the transition object. Or it could be something like:
.on('start', (d, i, event) => {
if (event.isFirst) { // ... }
if (event.isLast) { // ... }
})
This new event
object would have properties like:
isFirst
isLast
size
of the transitionindex
in time (so that you would be able to execute code, say, only on 'end' events of transitions with even index)delay
and duration
of the executed transition (the ones calculated in .delay()
and .duration()
to avoid recomputing them in the start/end listeners) *()**I'm not sure this would be good design, just throwing ideas here, but sure this is something I'd use.
EDIT
(*) we could attach delay
and duration
as attributes to the datum like in the snippet below but sometimes we need the datum to be immutable, or simply we don't want to pollute it with temporary values, as that would require us to clean it up at the end of the transition.
.duration(d => {
d.duration = 2 * d.value;
return d.duration;
})
.on('end', d => {
// use d.duration
delete d.duration;
})
On second thought, supposing to have the transition index
in time we wouldn't need isFirst
and isLast
, we could just compare index
and size
; on the other hand, I'm not sure what it should happen if 2 or more elements end the transition concurrently as if they get the same index, comparing index
and size
becomes useless. :thinking: Maybe index
should be a count
instead 😄
Here's a quite naïve example of what I mean: https://bl.ocks.org/mindrones/123832bbf5b08ce4b28dab66fae21a69
Now that await-async is a thing, I’ve been thinking that transitions could have some Promise-based APIs. One such idea that would address this issue is a transition.end method #77.
Folding into #77.
Hi, I would like to know if it's posible to somehow group certain concurrent transitions and execute a function when all of them are finished. The thing is that I needed to do a transition to animate the modification of two attributes for the same d3 selection so I needed to use concurrent transitions the way that is here: https://bl.ocks.org/mbostock/5348789
But now I need to execute a specific function after all transitions are finished. Anyone know a way to achieve this?