如何让元素在操作期间而不是之后显示?

问题描述 投票:0回答:1

我正在使用 JavaScript 制作排序算法可视化工具。我已经把大部分内容都放下了,但目前,在排序完成之前,条形图不会显示,此时,它确实显示已排序。

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sorting Algorithm Visualizer</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="controls">
        <select id="algorithm">
            <option value="bubble">Bubble Sort</option>
            <option value="selection">Selection Sort</option>
            </select>
        <input type="text" id="Size" value=10>
        <button onclick="gen()">Generate</button>
        <input type="number" id="delay" min="0" value="1"> (ms delay)
    </div>
        <div class="bars" id="setup"></div>
        <script src="script.js"></script>
</body>
</html>

CSS:

.bars{
  background-color: black;
  width: 10px;
  height: 10px;
  position: absolute;
  bottom: 100%;
  margin: 0px;
  visibility: hidden;
}

JavaScript:

var list;
var ind;
var size;
var sort;
var delay;
var count;
const content = document.getElementById("content");
var height = Math.floor(window.innerHeight * 0.9);
var width = Math.floor(window.innerWidth);

function swap(arr, a, b) {
  [arr[a], arr[b]] = [arr[b], arr[a]];
  update(a);
  update(b);
}

function bubbleSort(arr) {
  for (var i = 0; i < arr.length; i++) {
    for (var j = 0; j < (arr.length - i - 1); j++) {
      sleep(delay);
      if (arr[j] > arr[j + 1]) {
        swap(list, j, j + 1);
      }
    }
  }
  console.log(list);
}

function shuffle(arr) {
  ind = list.length - 1;
  for (var i = arr.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    swap(arr, i, j);
  }
}

function update(item) {
  const bar = document.getElementById("bar" + item);
  if (bar) {
    bar.style.visibility="visible";
    bar.style.height = (height / size) * list[item] + "px";
  }
}

function createBars(arr) {
  count = 0;
  while (count < arr.length) {
    var bar = document.createElement('div');
    bar.classList.add("bars");
    bar.setAttribute('id', "bar" + count);
    document.body.appendChild(bar);
    bar.style.width = Math.round(width / size) + "px";
    bar.style.visibility = "visible";
    bar.style.bottom = "0%";
    bar.style.left = count * width / size + "px";
    bar.style.height = (height / size) * arr[count] + "px";
    count++;
    updateAll();
  }
}

function gen() {
  if (list != undefined) {
    var element = document.getElementById("parent");
    element.textContent = "";
  }
  list = [];
  size = document.getElementById("Size").value;
  for (count = 1; count <= size; count++) {
    list.push(count);
  }
  shuffle(list);
  createBars(list);
  sleep(1000);
  sort = document.getElementById("algorithm").value;
  delay = document.getElementById("delay").value;
  if (sort == "bubble") {
    bubbleSort(list);
  }
}
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
function updateAll() {
  for (let i = 0; i < list.length; i++) {
    update(list, i); 
  }
}

抱歉长度太长了。

我期望发生的是在 createBars() 函数完成后会显示条形图,但这并没有发生。我希望能够看到条形变化高度以匹配“列表”数组的相应项目。这并没有发生。有谁知道这个问题的可能解决办法吗?

javascript sorting visualization
1个回答
0
投票

Javascript 是单线程环境(有一些超出范围的例外)。这意味着执行 js 的同一线程也用于渲染 html。这个单线程需要在某些点释放,以便发生视觉变化

这段代码中的

sleep
方法实际上做了与sleep相反的事情。它将线程捆绑在循环中进行不必要的计算

实现更好

sleep
的一种方法是使用
setTimeout
、promise 和
async
/
await

// create a promise that will "resolve" after milliseconds
function sleep(milliseconds) {
  return new Promise(resolve => {
    setTimeout(resolve, milliseconds)
  })
}

sleep 方法将立即返回一个 Promise,并且调用代码可以

await
该 Promise。
await
时间将是
milliseconds
时间。
await
的好处是释放了单线程,这样UI就可以开始渲染了

这是如何使用新功能的示例

sleep

// enable the await keyword by making this function async
async function bubbleSort(arr) {
  for (var i = 0; i < arr.length; i++) {
    for (var j = 0; j < (arr.length - i - 1); j++) {
      // await the sleep method
      await sleep(delay);
      if (arr[j] > arr[j + 1]) {
        swap(list, j, j + 1);
      }
    }
  }
  console.log(list);
}

async
await
具有传染性。这意味着每个使用
async
函数的函数本身也需要更改为
async
。所以很多代码需要异步化

async
/
await
一开始可能有点难以理解,所以如果您遇到困难,我建议您阅读一些有关该主题的内容

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

© www.soinside.com 2019 - 2024. All rights reserved.