Цепочка переходов с использованием обещания transition.end () - PullRequest
2 голосов
/ 13 июня 2019

Я пытаюсь связать переходы, вызывая мою функцию update, когда обещание transition.end() разрешается.Следующий фрагмент находится внутри этой функции update.Полный пример, частью которого является этот фрагмент, можно найти по адресу https://jsfiddle.net/fmgreenberg/1npLeguh/10/.

let t = d3
    .transition()
    .duration(3000)
    .end()
    .then(() => update(newData));

. Проблема в том, что переход происходит почти мгновенно, тогда визуализация остается там в течение ~ 3 секунд, пока не произойдет обновление.позвонил снова.Почему это?Если я закомментирую последние две строки фрагмента, переход займет ожидаемые 3 секунды.(Конечно, в этом случае есть только один переход, так как я удалил цикл.)

1 Ответ

4 голосов
/ 13 июня 2019

Вместо наименования экземпляра перехода используйте обещание в самом выделении перехода:

d3.select("#figure")
    .selectAll("circle")
    .data(newData, d => d)
    .transition()
    .duration(3000)
    .attr("cx", (_, i) =>
      i < N ? (i + 1) * (2 * r + s) : 300 - (i - N + 1) * (2 * r + s)
    )
    .end()
    .then(() => update(newData));

Вот обновленный JSFiddle: https://jsfiddle.net/k9gf8ybL/

и соответствующий С.О. фрагмент кода:

let N = 5;
let r = 5;
let s = 2;

let data = d3.range(2 * N);

d3.select("#figure")
  .selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cx", (_, i) =>
    i < N ? (i + 1) * (2 * r + s) : 300 - (i - N + 1) * (2 * r + s)
  )
  .attr("cy", 26)
  .attr("r", r)
  .attr("stroke", "blue")
  .attr("fill", d => (d < N ? "white" : "black"));

update(data);

function update(data) {
  let I = data.slice(0, N);
  let J = data.slice(N, 2 * N);
  let i = randInt(N);
  let x = I[i];
  let j = randInt(N);
  let y = J[j];
  let newData = [
    ...I.slice(0, i),
    ...I.slice(i + 1),
    y,
    ...J.slice(0, j),
    ...J.slice(j + 1),
    x
  ];

  d3.select("#figure")
    .selectAll("circle")
    .data(newData, d => d)
    .transition()
    .duration(3000)
    .attr("cx", (_, i) =>
      i < N ? (i + 1) * (2 * r + s) : 300 - (i - N + 1) * (2 * r + s)
    )
    .end()
    .then(() => update(newData));
}

function randInt(n) {
  return Math.floor(Math.random() * n);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.0/d3.min.js"></script>
<svg id="figure" viewBox="0 0 300 50" style="background-color: papayawhip; border-radius: 1rem" xmlns="http://www.w3.org/2000/svg"></svg>

Однако, если по какой-либо причине вы все еще хотите использовать именованный экземпляр перехода, просто используйте более общий метод on("end"...) вместо обещания end():

let t = d3
    .transition()
    .duration(3000)
    .on("end", () => {
      update(newData)
    });

А потом:

selection.transition(t)
    //etc...

Вот JSFiddle с таким подходом: https://jsfiddle.net/8od3vkc1/

...