Canvas制作排序算法演示動畫


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()函數進行頁面刷新

效果

初始界面

排序過程

gif演示

小結

做動畫都是一個原理,不短刷新更新坐標,擦除,繪制,之前用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;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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM