一尘不染

使用Canvas为JS中的排序算法制作动画

algorithm

出于娱乐目的,我试图创建一个可视化的不同排序算法,但是我遇到了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>

阅读 250

收藏
2020-07-28

共1个答案

一尘不染

一种解决方案是ES6 Generatorfunction*及其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">
2020-07-28