I am trying to run animations in order. Here is an example.
JavaScript
x
31
31
1
function rect1() {
2
d3.select("svg")
3
.append("rect")
4
.attr("id", "r1")
5
.attr("x", 300)
6
.attr("y", 100)
7
.attr("height", 0)
8
.attr("width", 0)
9
.transition()
10
.duration(1000)
11
.attr("height", 30)
12
.attr("width", 50);
13
}
14
function rect2() {
15
d3.select("svg")
16
.append("rect")
17
.attr("id", "r2")
18
.attr("x", 300)
19
.attr("y", 50)
20
.attr("height", 0)
21
.attr("width", 0)
22
.transition()
23
.duration(1000)
24
.attr("height", 30)
25
.attr("width", 50);
26
}
27
function highlightRect(id) {
28
d3.select(id)
29
.style("fill", "yellow")
30
}
31
So i want to create a function like this so i can run them in the order rect1()
, rect2()
, highlightRect()
one after another (after each animation ends).
JavaScript
1
7
1
function startAnim (f1, f2, f3, f3a) {
2
f1();
3
f2();
4
f3(f3a);
5
}
6
startAnim(rect1, rect2, highlightRect, "#r1");
7
I have tried something like this but it gets messy when there are more animations.
JavaScript
1
28
28
1
// rect1
2
d3.select("svg")
3
.append("rect")
4
.attr("id", "r1")
5
.attr("x", 300)
6
.attr("y", 100)
7
.attr("height", 0)
8
.attr("width", 0)
9
.transition()
10
.duration(1000)
11
.attr("height", 30)
12
.attr("width", 50)
13
.on("end", () => {
14
// rect2
15
d3.select("svg")
16
.append("rect")
17
.attr("id", "r2")
18
.attr("x", 300)
19
.attr("y", 50)
20
.attr("height", 0)
21
.attr("width", 0)
22
.transition()
23
.duration(1000)
24
.attr("height", 30)
25
.attr("width", 50)
26
.on("end", .);
27
});;
28
Might be an ignorant question can this be done with promises?
Thanks
Advertisement
Answer
Promisifying these would actually be pretty easy:
First we’ll make the functions return the object we’re chaining on.
JavaScript
1
33
33
1
function rect1() {
2
return d3.select("svg")
3
.append("rect")
4
.attr("id", "r1")
5
.attr("x", 300)
6
.attr("y", 100)
7
.attr("height", 0)
8
.attr("width", 0)
9
.transition()
10
.duration(1000)
11
.attr("height", 30)
12
.attr("width", 50);
13
}
14
15
function rect2() {
16
return d3.select("svg")
17
.append("rect")
18
.attr("id", "r2")
19
.attr("x", 300)
20
.attr("y", 50)
21
.attr("height", 0)
22
.attr("width", 0)
23
.transition()
24
.duration(1000)
25
.attr("height", 30)
26
.attr("width", 50);
27
}
28
29
function highlightRect(id) {
30
return d3.select(id)
31
.style("fill", "yellow")
32
}
33
Then we can use a generic higher order function to promisify those for us.
JavaScript
1
10
10
1
// Returns a promise that resolves after the given
2
// animation function finishes. Can optionally take args as a second parameter
3
// obviously this could just take a function and allow consumers
4
// to use anonymous functions for parameter-binding, but this function
5
// relies on the return value, so this is, maybe, slightly less easy to
6
// break on accident.
7
function runAnimation(fn, args) {
8
return new Promise(resolve => fn(args).on("end", resolve));
9
}
10
Then chaining them is pretty easy:
JavaScript
1
4
1
runAnimation(rect1)
2
.then(() => runAnimation(rect2))
3
.then(() => runAnimation(highlightRect, "#r1"))
4
Making a helper that takes an array of functions or something would be pretty easy here too.
Untested, but I think the general idea would work out.