tips: 形象化演示排序算法可以让初学者快速理解,比较好的例子:jun-lu的SortAnimate,旧金山大学的David Galles教授的算法演示课件。最近在看canvas,试着用js+canvas自己做了一个。
实现思路
- 获取输入字符串
- 存入数组
S[]
中 - 新建一个对象数组
Rect[]{ x , y , target_x , target_y , text:S[i]}
(注:x , y
是当前坐标,target_x , target_y
是目的坐标,text
记录字符) - 排序
- 使用插入排序进行顺序排序,当数值有交换行为时, 用
track_insert[]
记录进行交换的元素在数组中的位置(方便在绘制动画时进行坐标定位) - 因为我用的是插入排序,属于
arr[i]
和arr[i+1]
进行交换,所以只需要记录i
就可以。 - 绘制
- 图片绘制
function Draw(){}
- 图片坐标更新
function Update(){}
- 使用
setInterval()
定时调用Draw()
和Update()
函数进行页面刷新
效果
小结
做动画都是一个原理,不短刷新更新坐标,擦除,绘制,之前用opencv做的2d的小游戏也是同样的原理。
Source code
.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><link rel="stylesheet" type="text/css" href="css/demo.css"/><script type="text/javascript"src="js/demo2.js"></script><title>Demo</title>
</head>
<body> <div id="container"><div><p>Input String:<input name="string" id="tin" type="text"/></p> </div><div><p> <input type="button" onclick="showDemo()"id="bin" value="Show"/></p><canvas id="mycanvas" ></canvas></div></div>
</body>
</html>
.js
var S;
var Coordinate_y = 40;
var Rect = new Array();
var track_insert = new Array();
var cons = 0;
var cnt;function func() {
//获取字符串,存入数组S = document.getElementsByName("string")[0].value.split("");
//依据数组元素,完成对象数组for (var i = 0; i < S.length; i++) {var rect = {x: 30 * i,y: Coordinate_y,target_x: 30 * i,target_y: Coordinate_y,text: S[i]}Rect.push(rect);}insertSort(S);
}function insertSort(arr) {var i = 1,j, key, temp;for (; i < arr.length; i++) {j = i;key = arr[i];while (--j >= 0) {if (arr[j] > key) {arr[j + 1] = arr[j];arr[j] = key;
//当数据有交换时,记录下标track_insert.push(j);} else {break;}}}
}
//坐标更新
function update() {if (cons > track_insert.length) {return;}if (cons == 0) {cnt = track_insert[cons];Rect[cnt].target_x = Rect[cnt + 1].x;Rect[cnt + 1].target_x = Rect[cnt].x;cons += 1;console.log(cnt);}if (Rect[cnt].x == Rect[cnt].target_x) {if (cons == track_insert.length) {cons += 1;return;}var tem = Rect[cnt];Rect[cnt] = Rect[cnt + 1];Rect[cnt + 1] = tem;cnt = track_insert[cons];Rect[cnt].target_x = Rect[cnt + 1].x;Rect[cnt + 1].target_x = Rect[cnt].x;cons += 1;console.log(cnt);} else {Rect[cnt].x += 1;Rect[cnt + 1].x -= 1;}
}
//绘制图像
function draw(context) {context.clearRect(0, 0, context.canvas.width, context.canvas.height);for (var i = 0; i < Rect.length; i++) {if ((Rect[i].x - Rect[i].target_x) >= 2 || (Rect[i].x - Rect[i].target_x) < -2) {context.fillStyle = "yellow";context.fillRect(Rect[i].x, Rect[i].y, 25, 25);context.fillStyle = "blue";context.fillText(Rect[i].text, Rect[i].x + 10, Rect[i].y + 15);} else {context.strokeStyle = "blue";context.strokeRect(Rect[i].x, Rect[i].y, 25, 25);context.fillStyle = "blue";context.fillText(Rect[i].text, Rect[i].x + 10, Rect[i].y + 15);}}context.fillText("插入排序", 40, 80);
}
function showDemo() {func();var c = document.getElementById("mycanvas");c.width = 600;c.height = 300;var context = c.getContext("2d");
//40ms调用一次函数setInterval(function() {draw(context);update();}, 40);
}
.css
input#tin{margin-bottom: 5px;background-color: #fff;opacity:0.85;8width:20px;height:25px; border-width: 1;font-size: 17px; color: #000; font-weight: 500; border-radius: 5px;cursor:pointer;
}
input#bin{background-color: gray;width:80; height:25; border-width: 2; font-size: 20px; color: #FFFFFF; font-weight: 500;cursor:pointer; border-radius: 5px;
}
canvas#mycanvas{border:1px solid;width: 600px;height: 300px;margin-top: 5px;border-radius: 5px;
}
div#container{margin-left: 70px;
}