• 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
    	20px;
    	height:25px; 
    	border- 1;
    	font-size: 17px; 
    	color: #000; 
    	font-weight: 500; 
    	border-radius: 5px;
    	cursor:pointer; 
    }
    input#bin{
    	background-color: gray;
    	80; 
    	height:25; 
    	border- 2; 
    	font-size: 20px; 
    	color: #FFFFFF; 
    	font-weight: 500;
    	cursor:pointer; 
    	border-radius: 5px;
    }
    canvas#mycanvas{
    	border:1px solid;
    	 600px;
    	height: 300px;
    	margin-top: 5px;
    	border-radius: 5px;
    }
    div#container{
    	margin-left: 70px;
    }
    
  • 相关阅读:
    【Android】4.1 UI设计器
    【Android】4.0 Android项目的基本结构
    【Android】3.25 示例25--调启百度地图
    【Android】3.24 示例24--OpenGL绘制功能
    【Android】3.23 示例23--瓦片图功能
    【Android】3.22 示例22--LBS云检索功能
    【Android】3.21 示例21—兴趣点收藏功能
    【Android】3.20 示例20—全景图完整示例
    【Android】3.19 示例19--全景图HelloWorld
    Java并发编程之happens-before
  • 原文地址:https://www.cnblogs.com/coderleon/p/4784095.html
Copyright © 2020-2023  润新知