简体   繁体   中英

How to animate elements for every swap in a array using d3.js

I have a function that does the bubble sort Algorithm for a given array. How can I animate the swaps for every iteration using the d3.js library

Ive tried with a function that should swap the x-coordinates of the given elements that are swapping but it did not work as expected. Probably a bad idea anyways, what is the correct way or the better way of doing this? Thanks!

 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>

There are animations happening but not as I wished, the swapping rects (indexes of the array) should change/swap there position in the animation.

Transitions on the same element will just overwrite previous transition.
https://bost.ocks.org/mike/transition/#per-element :

Starting a new transition on the element stops any transition that is already running.

To resolve this, I have used async/await , and I have upgraded d3 to the latest version which has added transition.end (which makes it easier to sequence transitions using Promises).

Another problem is that you are using index positions for selecting rects, rather than the actual values, and so swapAnimation is moving the wrong elements. It is swapping positions based on the initial positions, rather than the updated positions in the bubble sort. eg:
Iteration:

  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

     ^^^^^ ^^^^^

    Notice that rect2, which contains the value 5, is now in the first position.
    So instead of using index positions, I have changed the ids to be rect${value}

Another way, which is technically more accurate, would be to store the <text> elements in an array, and swap them along with the bubbleSort of the data array. And then animate on index positions on the <text> element array.
However, for purpose of demonstration, it was shorter to just have the id locked to the values instead of initial index.

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM