tips: 形象化演示排序算法能夠讓初學者快速理解,比較好的例子:jun-lu的SortAnimate,舊金山大學的David Galles教授的算法演示課件。最近在看canvas,試着用js+canvas本身作了一個。javascript
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的小遊戲也是一樣的原理。css
<!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>
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); }
input#tin{ margin-bottom: 5px; background-color: #fff;opacity:0.85;8 width: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; }