D3 версия 5, как связать обещание построить график - PullRequest
1 голос
/ 29 февраля 2020

Я хочу связать JS обещание построения диаграммы D3 v5 и хочу разрешить ее после анимации, но она не работает, код ниже также показывает различные типы попыток в комментариях, ни одна из них не работает, опция 3 вызывает исключение ( Uncaught (в обещании) TypeError: Невозможно прочитать свойство 'on' из неопределенного ), опция 2 и опция 1 просто молча терпят неудачу. Посоветуйте пожалуйста, спасибо, куча! PS: набор данных TrumpStatsFiltered правильный, так как я тестировал код без обещания.

var dur = 400;
var t = d3.transition().duration(dur);

var durR = 400;
var tR = d3.transition().duration(durR).ease(d3.easeBounce).delay(220);

var swingState1 = d3.select('#svgSwingStateGraph1');

var swingState1Promise = () => {
    return new Promise((resolve, reject) => {
        swingState1
            .selectAll('text')
            .data([TrumpStatsFiltered], d => d.swing_state_1)
            .join(
                enter => {
                    enter
                    .append('text')
                    .attr('x', -150)
                    .attr('y', 30)
                    .text(d => d.swing_state_1 == 'Trump' ? "Trump":"Hillary")
                    .attr("stroke", d => d.swing_state_1 == 'Trump' ? "green":"orange")
                    .transition(t)
                    .attr('x', 75)
                    //.on("end", response => resolve(response)) //- option 2
                },

                update => {
                    update
                    .transition(t)
                    .text(d => d.swing_state_1 == 'Trump' ? "Trump":"Hillary")
                    .attr("stroke", d => d.swing_state_1 == 'Trump' ? "green":"orange")
                    //.on("end", response => resolve(response)) //- option 2
                },

                exit => {
                    exit
                    .transition(tR)
                    .attr("stroke", "tomato")
                    .attr('x', 200)
                    .remove()
                    //.on("end", response => resolve(response)) //- option 2
                }
            )//.on("end", response => resolve(response)) //- option 3

        swingState1.on("end", response => resolve(response)) // option 1
    })
}

Promise.all([swingState1Promise()]).then(() => {

    ***I need to hit this point!***
});

1 Ответ

1 голос
/ 01 марта 2020

Вы можете использовать transition.end(), который

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

Поскольку у вас есть три выборки - а именно выборки ввода, обновления и выхода в .join() - вы можете создать массив для сбора этих обещаний и передать его в Promise.all(), чтобы дождаться разрешения этих обещаний, когда все соответствующие переходы завершатся. Следующий код показывает, как это можно сделать для выбора ввода; очевидно, тот же шаблон может быть применен для сбора обещаний из обновления и выбора выхода.

const transitions = [];                // Collect promises for enter, update, exit transitions.

someSelection.data(someData)
  .join(
    enter => enter.append("whatever")
      .attr("", "")                    // Modify some attributes.
      .call(enter => transitions.push( // Push the returned promise to the collector array.
        enter.transition()             // Create a new transition.
          .attr("", "")                // Attributes to be transitioned.
          .end()                       // Get the promise.
      ))
  );  

Promise.all(transitions)
  .then(() => {
    console.log("Done");               // This logs when all transitions have finished.
  });

Посмотрите на следующий фрагмент рабочего демо:

const svg = d3.select('body')
  .append("svg")
    .attr("width", 600)
    .attr("height", 200);

const transitions = [];

svg.selectAll(null)
  .data([500, 1500, 1000])
  .join(
    enter => enter.append('circle')
      .attr('cx', (_, i) => i * 50 + 100)
      .attr('cy', 100)
      .attr("r", 20)
      .attr("fill", "red")
      .call(enter => transitions.push(
        enter.transition()
          .duration(d => d)
          .attr('fill', "blue")
          .end()
      ))
  );  

Promise.all(transitions)
  .then(() => {
    console.log("Done");
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.15.0/d3.js"></script>
...