如何在重新绘制JavaScript中的内容之前产生延迟?

问题描述

我是JavaScript的新手,我正在尝试创建一个可视化气泡排序算法的程序。

这个想法是通过fillRect(x,y,x,y)生成不同大小的矩形,并将高度保存到数组中。会调用bubble-sort函数,并且数组会通过比较高度来对自身进行排序,并且每次在数组中移动高度时画布都会重新绘制自身。

我使功能正常工作。问题是我不知道如何在每次重涂之间创建延迟。目前,它会立即排序,您看不到动画。我想应该使用从java睡眠之类的东西?我不知道。

到目前为止,这是我的代码

var list = [];
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();

var x = 4;
for (i = 0; i < 38; i++) {
    var random = Math.floor(Math.random() * (400 - 10) + 10);
    bar = ctx.fillRect(x,4,20,random);
    list.push(random);
    x += 21;
}

function bubbleSort() {
    for (let i = 0; i < list.length - 1; i++) {
        for (let j = 0; j < list.length - i - 1; j++) {
            if (list[j] > list[j + 1]) {
                let temp = list[j];
                list[j] = list[j + 1];
                list[j + 1] = temp;
                ctx.clearRect(0,c.width,c.height);
                repaint(list);
            }
        }
    }
}

function repaint(list) {
    ctx.clearRect(0,c.height);
    let k = 4;
    for (let i = 0; i < 38; i++) {
        ctx.fillRect(k,list[i]);
        k += 21;
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <Meta charset="UTF-8">
    <Meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>bubble-sort</title>
</head>
<body>
    
    <canvas id="myCanvas" width="805px" height="550px" style="border:2px solid #000000; margin-left:100px; margin-top: 100px; background: gray"></canvas>
    <br><br>
    <button type="button" onclick="bubbleSort()" style="margin-left: 100px">bubble sort</button>
    <script src="bubble.js"></script>
</body>
</html>

解决方法

您可以使用以下延迟功能:

const delay = ms => new Promise(resolve => setTimeout(resolve,ms));

然后将bubbleSort函数更改为async,然后在每次迭代后几毫秒内将await更改为>

var list = [];
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();

const delay = ms => new Promise(resolve => setTimeout(resolve,ms));

var x = 4;
for (i = 0; i < 38; i++) {
    var random = Math.floor(Math.random() * (400 - 10) + 10);
    bar = ctx.fillRect(x,4,20,random);
    list.push(random);
    x += 21;
}

async function bubbleSort() {
    for (let i = 0; i < list.length - 1; i++) {
        for (let j = 0; j < list.length - i - 1; j++) {
            if (list[j] > list[j + 1]) {
                let temp = list[j];
                list[j] = list[j + 1];
                list[j + 1] = temp;
                ctx.clearRect(0,c.width,c.height);
                repaint(list);
                await delay(200);
            }
        }
    }
}

function repaint(list) {
    ctx.clearRect(0,c.height);
    let k = 4;
    for (let i = 0; i < 38; i++) {
        ctx.fillRect(k,list[i]);
        k += 21;
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>bubble-sort</title>
</head>
<body>
    
    <canvas id="myCanvas" width="805px" height="550px" style="border:2px solid #000000; margin-left:100px; margin-top: 100px; background: gray"></canvas>
    <br><br>
    <button type="button" onclick="bubbleSort()" style="margin-left: 100px">bubble sort</button>
    <script src="bubble.js"></script>
</body>
</html>

如果您不想使用async await等,这是一种非常简单的方法。


仅供参考,如果您不能将函数更改为async,则仍然可以通过阻塞这样的线程来实现它,但是可能会使CPU占用100%的内存,因此不建议这样做:

function delay(ms) {
  const target = performance.now() + ms;
  while(performance.now() < target) {
  }
}