繁体   English   中英

使用Canvas动画化JS中的排序算法

[英]Using Canvas to animate a sorting algorithm in JS

出于娱乐目的,我试图创建一个可视化的不同排序算法,但是我遇到了Canvas动画的问题。

我以为我只能在sorter方法中调用draw函数,但这会导致浏览器锁定,直到数组被完全排序,然后绘制一些中间框架。

我将如何从排序方法中进行动画制作? 下面是我到目前为止的代码,我不会运行此代码段,因为它将使选项卡挂起几秒钟。

 N = 250; // Array Size XYs = 5; // Element Visual Size Xp = 1; // Start Pos X Yp = 1; // Start Pos Y var canvas; var l = Array.apply(null, { length: N }).map(Number.call, Number); Array.prototype.shuffle = function() { var i = this.length, j, temp; if (i == 0) return this; while (--i) { j = Math.floor(Math.random() * (i + 1)); temp = this[i]; this[i] = this[j]; this[j] = temp; } return this; } function map_range(x, in_min, in_max, out_min, out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } function rainbow(x) { var m = map_range(x, 0, N, 0, 359); return 'hsl(' + m + ',100%,50%)'; } function init() { canvas = document.getElementById('canvas'); l.shuffle(); draw(); bubbleSort(l); } function draw() { if (canvas.getContext) { var ctx = canvas.getContext('2d'); for (var i = 0; i < l.length; i++) { ctx.fillStyle = rainbow(l[i]); ctx.fillRect((Xp * i) * XYs, Yp * XYs, XYs, XYs); } } } function bubbleSort(a) { var swapped; do { swapped = false; for (var i = 0; i < a.length - 1; i++) { if (a[i] > a[i + 1]) { var temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; swapped = true; draw(); setTimeout(function() {}, 10); } } } while (swapped); } 
 <html> <body onload="init();"> <canvas id="canvas" width="1500" height="1500"></canvas> </body> </html> 

一种解决方案是ES6 Generator function*及其yield语句。

这样一来,您就可以暂停功能,并在暂停的位置重新启动它:

 N = 100; // Array Size XYs = 5; // Element Visual Size Xp = 1; // Start Pos X Yp = 1; // Start Pos Y var canvas; var l = Array.apply(null, { length: N }).map(Number.call, Number); Array.prototype.shuffle = function() { var i = this.length, j, temp; if (i == 0) return this; while (--i) { j = Math.floor(Math.random() * (i + 1)); temp = this[i]; this[i] = this[j]; this[j] = temp; } return this; } function map_range(x, in_min, in_max, out_min, out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } function rainbow(x) { var m = map_range(x, 0, N, 0, 359); return 'hsl(' + m + ',100%,50%)'; } function init() { canvas = document.getElementById('canvas'); l.shuffle(); var sort = bubbleSort(l); // an anim function triggered every 60th of a second function anim(){ requestAnimationFrame(anim); draw(); sort.next(); // call next iteration of the bubbleSort function } anim(); } function draw() { if (canvas.getContext) { var ctx = canvas.getContext('2d'); for (var i = 0; i < l.length; i++) { ctx.fillStyle = rainbow(l[i]); ctx.fillRect((Xp * i) * XYs, Yp * XYs, XYs, XYs); } } } function* bubbleSort(a) { // * is magic var swapped; do { swapped = false; for (var i = 0; i < a.length - 1; i++) { if (a[i] > a[i + 1]) { var temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; swapped = true; yield swapped; // pause here } } } while (swapped); } init(); 
 <canvas id="canvas" width="500" height="20"> 

您需要一个渲染循环。 requestAnimationFrame()是您的朋友。 使用此方法,您可以给浏览器一个回调,该回调在下一帧绘制之前被调用。

在该回调中,绘制您的东西,并使用相同的回调再次调用requestAnimationFrame(),如下所示:

requestAnimationFrame(renderLoop);
function renderLoop()
{
    // visualize your array `l` at this point

    // call the render callback for the next frame draw
    requestAnimationFrame(renderLoop);
}

https://developer.mozilla.org/de/docs/Web/API/window/requestAnimationFrame

您可以获得通常为60 fps帧速率的平滑动画。

要将这种方法集成到您的代码中:

  1. 删除行

     draw(); setTimeout(function() {}, 10); 
  2. 叫首字母

    requestAnimationFrame(renderLoop);

    当您的程序启动时。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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