Как анимировать элементы для каждого свопа в массиве с помощью d3. js - PullRequest
0 голосов
/ 16 июня 2020

У меня есть функция, которая выполняет алгоритм пузырьковой сортировки для данного массива. Как я могу анимировать свопы для каждой итерации с помощью библиотеки d3. js

Я пробовал использовать функцию, которая должна менять местами x-координаты заданных элементов, которые меняются местами, но это не сработало, как ожидалось. В любом случае, возможно, это плохая идея, как это правильно или лучше? Спасибо!

function bubbleSort() {
  let len = dataArray.length;
  let swapped;
  do {
    swapped = false;
    for (let i = 0; i < len; i++) {
      if (dataArray[i] > dataArray[i + 1]) {

        let temp = dataArray[i];
        dataArray[i] = dataArray[i + 1];
        dataArray[i + 1] = temp;
        swapped = true;
        // call function here for swap animation...
        swapAnimation(dataArray[i], i, dataArray[i + 1], i + 1); / did not work
      }
    }
  } while (swapped);
  return console.log(dataArray);
}

function swapAnimation(d, i, d1, i1) {
  d3.select("#rect" + i)
    .transition()
    .duration(durationTime)
    .attr("x", d3.select("#rect" + i1).attr("x"));

      d3.select("#rect" + i1)
    .transition()
    .duration(durationTime)
    .attr("x", d3.select("#rect" + i).attr("x"));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

Есть анимация, но не так, как я хотел, прямоугольники подкачки (индексы массива) должны изменить / поменять местами позицию в анимации.

1 Ответ

0 голосов
/ 17 июня 2020

Переходы в том же элементе просто перезапишут предыдущий переход.
https://bost.ocks.org/mike/transition/#per -элемент :

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

Чтобы решить эту проблему, я использовал async / await , и я обновил d3 до последней версии, которая добавила transition.end (что упрощает последовательность переходов с помощью обещаний).

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

  1. swap (0,1) [1,9,5 ...] rect0.x = 20, rect1.x = 10, rect2.x = 30
  2. swap (1,2) [1,5,9 ...] rect0.x = 20, rect1.x = 30, rect2.x = 10

                                 ^^^^^      ^^^^^
    

    Обратите внимание, что rect2, который содержит значение 5, теперь находится в первой позиции.
    Поэтому вместо использования позиций индекса я изменил идентификаторы на rect $ {value}

Другой способ, который технически более точен, - это сохранить элементы <text> в массиве и поменять их местами вместе с пузырьковой сортировкой массива данных. А затем анимируйте позиции индекса в массиве элементов <text>.
Однако в целях демонстрации было короче просто привязать id к значениям вместо начального индекса.

dataArray = [9, 1, 5, 7, 2, 4, 3]

for (var i = 0; i < dataArray.length; i++)
  document.querySelector('svg').innerHTML += `<text class="rects" id="rect${dataArray[i]}" x="${i*10}" y="10" >${dataArray[i]}</text>`

var durationTime = 1000
bubbleSort()

async function bubbleSort() {
  let len = dataArray.length;
  let swapped;
  do {
    swapped = false;
    for (let i = 0; i < len; i++) {
      if (dataArray[i] > dataArray[i + 1]) {

        let temp = dataArray[i];
        dataArray[i] = dataArray[i + 1];
        dataArray[i + 1] = temp;
        swapped = true;
        // call function here for swap animation...
        await swapAnimation(dataArray[i], i, dataArray[i + 1], i + 1); // did not work

      }
    }
  } while (swapped);
  return console.log(dataArray);
}

function swapAnimation(d, i, d1, i1) {
  var sel = `#rect${d}`, sel1 = `#rect${d1}`
  var x1 = d3.select(sel1).attr("x")
  var x  = d3.select(sel).attr("x")
  return Promise.all([
    d3.select(sel)
    .transition()
    .duration(durationTime)
    .attr("x", x1)
    .end(),

    d3.select(sel1)
    .transition()
    .duration(durationTime)
    .attr("x", x)
    .end()
  ])
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.js" integrity="sha256-LHLWSn9RC2p119R1eT2pO3Om+Ir2G0kTZOJmWQ2//pw=" crossorigin="anonymous"></script>
<svg></svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...