<style>
  * {
    transition: x 0.5s;
  }
</style>
<svg
  id="container"
  width="100%"
  height="250"
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
>
  <rect
    id="template"
    x="10"
    y="10"
    width="5"
    height="10"
    fill="black"
    display="none"
  ></rect>
</svg>
<script>
  function generateTestArr(start, end, length) {
    let arr = new Array(length);

    for (let i = 0; i < length; i++) {
      arr[i] = (end - start) * Math.random() + start;
    }

    return arr;
  }

  Array.prototype.bubbleSort = async function bubbleSort(fn, animation) {
    let arr = this;
    let len = arr.length;

    for (let i = 0; i < len; i++) {
      for (let j = 1; j < len - i; j++) {
        let left = j - 1;
        let right = j;

        let res = fn(arr[left], arr[right]);
        if (res > 0) {
          swap(arr, left, right);
          if (animation) await animation(arr, left, right, i);
        }
      }
    }
  };

  function swap(arr, i, j) {
    [arr[i], arr[j]] = [arr[j], arr[i]];
  }

  function drawRect(arr) {
    let container = document.querySelector("#container");
    let template = container.querySelector("#template");

    let width = 10;

    for (let i = 0; i < arr.length; i++) {
      let clone = template.cloneNode(false);
      clone.id = "rect" + i;

      let x = i * 12;

      clone.setAttribute("x", x);
      clone.setAttribute("height", arr[i]);
      clone.setAttribute("width", width);
      clone.setAttribute("display", "");

      container.appendChild(clone);
    }
  }

  function animation(arr, left, right, i) {
    return new Promise((resolve, reject) => {
      let leftId = "#rect" + left;
      let rightId = "#rect" + right;

      let leftDom = document.querySelector(leftId);
      let rightDom = document.querySelector(rightId);

      leftDom.setAttribute("fill", "blue");
      rightDom.setAttribute("fill", "red");

      leftDom.setAttribute("x", right * 12);
      rightDom.setAttribute("x", left * 12);

      setTimeout(() => {
        rightDom.setAttribute("fill", "black");
        leftDom.setAttribute("fill", "black");

        leftDom.id = rightId.slice(1);
        rightDom.id = leftId.slice(1);

        resolve();
      }, 500);
    });
  }

  let arr = generateTestArr(0, 250, 50);
  drawRect(arr);
  arr.bubbleSort((a, b) => b - a, animation);

  console.log(arr);
</script>

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.