在用JavaScript重新绘制某些内容之前,如何创建延迟



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

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

我制作的功能按预期工作。问题是,我不知道如何在每次重新绘制之间创建延迟。目前它会立即排序,并且您看不到动画。我想应该使用java中的sleep之类的东西吗?我想不通。

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

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, 0, c.width, c.height);
repaint(list);
}
}
}
}
function repaint(list) {
ctx.clearRect(0, 0, c.width, c.height);
let k = 4;
for (let i = 0; i < 38; i++) {
ctx.fillRect(k, 4, 20, 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, 0, c.width, c.height);
repaint(list);
await delay(200);
}
}
}
}
function repaint(list) {
ctx.clearRect(0, 0, c.width, c.height);
let k = 4;
for (let i = 0; i < 38; i++) {
ctx.fillRect(k, 4, 20, 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>

如果你不想使用asyncawait等,这里有一个相当简单的方法


仅供参考,如果你不能将函数更改为async,你仍然可以通过这样阻止线程来实现它,但它可能会将你的CPU调到100%,这是不推荐的:

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

最新更新