d3 запускать анимации внутри функции по порядку - PullRequest
0 голосов
/ 27 декабря 2018

Я пытаюсь запустить анимацию по порядку.Вот пример.

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", ....);
    });;

Может быть, неосведомленный вопрос, может ли это быть сделано с обещаниями?

Спасибо

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Обещать их было бы довольно просто:

Сначала мы сделаем так, чтобы функции возвращали объект, к которому мы подключаемся.

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"))

Создание помощника, который принимает массив функций или что-то в этом роде, тоже будет довольно просто.

Не проверено, но я думаю, что общая идея сработает.

0 голосов
/ 27 декабря 2018

Скорее всего, вам не нужны обещания, поскольку кажется, что вы хотите дождаться окончания каждой анимации, прежде чем начинать следующую анимацию, поэтому это не асинхронная операция.Мне сложно это проверить, но я думаю, что вы можете передать каждую последующую функцию в качестве параметра предыдущей функции.Это будет выглядеть примерно так:

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');

Честно говоря, я не уверен, сработает ли это с вашей ситуацией, но стоит попробовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...