Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
308 views
in Technique[技术] by (71.8m points)

javascript - Using Canvas to animate a sorting algorithm in JS

For fun I am trying to create a visualization of different sorting algorithms, but I've run into an issue with Canvas animations.

I assumed I would just be able to call a draw function within the sorter method, but this causes the browser to lock up until the array is fully sorted and then draws some middle frame.

How would I go about animating from within the sorting methods? Below is the code I have so far, I wouldn't run this snippet as it will hang the tab for a few seconds.

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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One solution is the ES6 Generator function* along with its yield statement.

That allows you to pause a function and restart it later where it has been paused:

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">

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...