Как связать JS-функцию с d3.transition

#javascript #d3.js

#javascript #d3.js

Вопрос:

Я создал гистограмму с помощью d3, которая извлекает размеры столбцов из массива. Итак, я пытаюсь анимировать переключение между соседними столбцами с помощью функции swapper, которая работает, но только один раз. Бары меняются местами при первом вызове, но игнорируют второй вызов. Я думаю, что проблема в том, что второй вызов функции выполняется до завершения первого перехода. Как мне выполнить второй вызов, чтобы дождаться завершения первого?

 const data = utils.generateRandomArray(25,45);
const width = "500px";
const height = "300px";

const graph1 = d3.select("#graph1").append("svg")
                  .attr("height", height)
                  .attr("width", width)
                  .attr("style", "border: 1px solid black");

utils.renderGraph(graph1, data);
utils.renderGraph(graph2, data);

const bar1 = graph1.select(".bar-1");
const bar2 = graph1.select(".bar-2");
const bar3 = graph1.select(".bar-3");
const bar4 = graph1.select(".bar-4");

    function swapper(bar1,bar2){
        bar1.transition()
            .delay(1000)
            .duration(2000)
            .attr("x", `${bar2.attr("x")}`);
            
        bar2.transition()
            .delay(1000)
            .duration(2000)
            .attr("x", `${bar1.attr("x")}`);
    }
    
    swapper(bar1,bar2);
    swapper(bar1,bar2);

 

Комментарии:

1. Вы можете добавить название к своим переходам, чтобы они не мешали друг другу — bar1.transition(«firstone») и bar2.transition («secondone»).

Ответ №1:

Взгляните на .end()

Возвращает обещание, которое разрешается, когда каждый выбранный элемент завершает переход. Если переход какого-либо элемента отменяется или прерывается, обещание отклоняется.

Так что, возможно, что-то вроде

 async function swapper(bar1,bar2){
    const bar1Transition = bar1.transition()
        .delay(1000)
        .duration(2000)
        .attr("x", `${bar2.attr("x")}`);
        
    const bar2Transition = bar2.transition()
        .delay(1000)
        .duration(2000)
        .attr("x", `${bar1.attr("x")}`);

    return Promise.all([bar1Transition.end(), bar2Transition.end()]);
}

swapper(bar1,bar2).then( () => {
  return swapper(bar1,bar2);
});
 

Комментарии:

1. Это действительно сработало, с небольшой настройкой — async должен был быть перед функцией (он также работал без ключевого слова async) и .end() для Promise.all(как в предыдущем комментарии) или добавлением .end() непосредственно к переходам внутри функции. Я также заставил ее работать, вернув bar2Transition.end() , поскольку оба перехода выполняются одновременно. Спасибо вам, ребята, за то, что помогли мне.