Я пытаюсь запустить анимацию по порядку. Вот пример.
function rect1() {
d3.select("svg")
.append("rect")
.attr("id", "r1")
.attr("x", 300)
.attr("y", 100)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50);
}
function rect2() {
d3.select("svg")
.append("rect")
.attr("id", "r2")
.attr("x", 300)
.attr("y", 50)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50);
}
function highlightRect(id) {
d3.select(id)
.style("fill", "yellow")
}
Итак, я хочу создать такую функцию, чтобы я мог запускать их в порядке rect1(), rect2(), highlightRect() один за другим (после окончания каждой анимации).
function startAnim (f1, f2, f3, f3a) {
f1();
f2();
f3(f3a);
}
startAnim(rect1, rect2, highlightRect, "#r1");
Я пробовал что-то подобное, но когда появляется больше анимаций, все становится беспорядочно.
// rect1
d3.select("svg")
.append("rect")
.attr("id", "r1")
.attr("x", 300)
.attr("y", 100)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50)
.on("end", () => {
// rect2
d3.select("svg")
.append("rect")
.attr("id", "r2")
.attr("x", 300)
.attr("y", 50)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50)
.on("end", ....);
});;
Может быть, невежественный вопрос, можно ли это сделать с помощью обещаний?
Спасибо



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вероятно, вам не нужны обещания, поскольку кажется, что вы хотите дождаться завершения каждой анимации перед запуском следующей анимации, поэтому это не асинхронная операция. Мне сложно это проверить, но я думаю, что вы можете передать каждую последующую функцию в качестве параметра предыдущей функции. Это выглядело бы примерно так:
function rect1(next) {
d3.select("svg")
.append("rect")
.attr("id", "r1")
.attr("x", 300)
.attr("y", 100)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50);
next();
}
function rect2(next) {
d3.select("svg")
.append("rect")
.attr("id", "r2")
.attr("x", 300)
.attr("y", 50)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50);
next();
}
function highlightRect(id, next) {
d3.select(id)
.style("fill", "yellow")
next();
}
Потом...
function startAnim(f1, f2, f3, f3a) {
f1(f2(f3(f3a)));
startAnim(rect1, rect2, highlightRect, '#r1');
Честно говоря, я не уверен, что это сработает в вашей ситуации, но попробовать стоит.
Анимации d3 являются асинхронные. Это просто попытка уволить их всех сразу. Обратный вызов next необходимо передать обработчику .on("end", . . .).
Обещать это на самом деле было бы довольно просто:
Сначала мы заставим функции возвращать объект, с которым мы связываемся.
function rect1() {
return d3.select("svg")
.append("rect")
.attr("id", "r1")
.attr("x", 300)
.attr("y", 100)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50);
}
function rect2() {
return d3.select("svg")
.append("rect")
.attr("id", "r2")
.attr("x", 300)
.attr("y", 50)
.attr("height", 0)
.attr("width", 0)
.transition()
.duration(1000)
.attr("height", 30)
.attr("width", 50);
}
function highlightRect(id) {
return d3.select(id)
.style("fill", "yellow")
}
Затем мы можем использовать универсальную функцию более высокого порядка, чтобы обещать их нам.
// Returns a promise that resolves after the given
// animation function finishes. Can optionally take args as a second parameter
// obviously this could just take a function and allow consumers
// to use anonymous functions for parameter-binding, but this function
// relies on the return value, so this is, maybe, slightly less easy to
// break on accident.
function runAnimation(fn, ...args) {
return new Promise(resolve => fn(...args).on("end", resolve));
}
Тогда связать их в цепочку довольно просто:
runAnimation(rect1)
.then(() => runAnimation(rect2))
.then(() => runAnimation(highlightRect, "#r1"))
Здесь тоже будет довольно легко создать помощника, который принимает массив функций или что-то еще.
Не тестировал, но я думаю, что общая идея сработает.
создайте список этих функций анимации, пусть они возвращают
transitionи в основной функции анимации вызывают эти функции анимации по порядку и модифицируют возвращенныйtransitionдля вызова основной анимации наend