[Canvas绘图] 第09节 迷图档案

本节目标:
(1) 封装图形档案类ShapeProfile类,用于存放常用及漂亮图形。
(2) 实现图形顶点运算与绘制部分的分离。

实现步骤:

把图形顶点计算和绘制放在一块纠缠不清是一个糟糕的主意,所以我打算把它们分离出来,所以我封装了这个ShapeProfile类,专门计算坐标信息。

/**
* @usage   封装常用及精美图形
* @author  mw
* @date    2015年12月02日  星期三  09:22:00 
* @param   每个图形中参数
*          (xCenter, yCenter)作为路径旋转中心,
*		   r作为外接圆半径来限定范围, 
*		   angle作为初始旋转值,为0时默认x轴为起始或作为尖角对称轴,
*	       edge为图形系列边数。
* @return  路径中顶点按顺序存储的数组[x1, y1, x2, y2,...,xn, yn]。
*
*/

function ShapeProfile() {
	this.retArray = new Array();
/**
* @usage   调用接口 
* @author  mw
* @date    2015年12月02日  星期三  09:55:31 
* @param   index是图形在档案中的序号
* @return
*
*/
	this.draw = function(index, xCenter, yCenter, r, edge, angle){
		
		index = Math.abs(Math.round(index));
		xCenter = xCenter ? xCenter:0;
		yCenter = yCenter ? yCenter:0;
		r = r? r : 100;
		edge = edge? edge : 5;
		angle = angle ? angle : 0;
		
		
		switch (index) {
			//正多边形
			case 1: this.nEdge(xCenter, yCenter, r, edge, angle); break;
			//空心星形
			case 2: this.nStar(xCenter, yCenter, r, edge, angle); break;
			case 201: this.nStar(xCenter,yCenter, r, edge, angle, 0.2);break;
			case 202: this.nStar(xCenter,yCenter, r, edge, angle, 0.3, 3.0); break;
			//其它
			default:break;
		}
	
	};
	
	
/**
* @usage  以顶点递推方式绘制正多边形 #1
* @author  mw
* @date    2015年12月01日  星期二  09:42:33 
* @param  (x, y)图形中心坐标,r 外接圆半径 edge 边数
* @return
*
*/

	this.nEdge = function(x, y, r, edge, angle0) {
		this.retArray.length = 0;
		
		var perAngle = Math.PI * 2 / edge;
		
		var a = r * Math.sin(perAngle / 2);
		
		var angle = -angle0 ;
		var xOffset = r * Math.sin(perAngle / 2 - angle0);
		var yOffset = r * Math.cos(perAngle / 2 - angle0);
					
				
		var x1 = x-xOffset;
		var y1 = y+yOffset;		
		
		for (var i=0; i < edge; i++) {			
			this.retArray.push(x1);
			this.retArray.push(y1);
			x1 = x1 + 2 * a * Math.cos(angle);
			y1 = y1 + 2 * a * Math.sin(angle);
			angle -= perAngle;
			
		}
	
		return this.retArray;
	
	};	
		
/**
* @usage   空心星形   #2 #201 #202
* @author  mw
* @date    2015年12月01日  星期二  10:06:13 
* @param
* @return
*
*/	
		this.nStar = function(x, y, r, edge, angle0, arg0, arg1) {
			this.retArray.length = 0;
			
			var perAngle = Math.PI * 2 / edge;
			
			
			var r0 = arg0 ? arg0 * r : r / (2 * (1 + Math.cos(perAngle)));
			var scale = arg1 ? arg1 : 0.5;
			var angle = 0.5 * perAngle -angle0;
			var xOffset = x;
			var yOffset = y;
			
			for (var i =0; i< edge; i++) {
				this.retArray.push(r0 * Math.cos(angle) + xOffset);
				this.retArray.push(r0 * Math.sin(angle) + yOffset);
				this.retArray.push(r * Math.cos(angle - scale * perAngle) + xOffset);
				this.retArray.push(r * Math.sin(angle - scale * perAngle) + yOffset);
				
				angle -= perAngle;
			}	

			return this.retArray;

		}

}
我把前几节中的绘制多边形和星型的函数给封装了进去,这样可以很方便的调用。

下面是几个Demo:

(1)

/**
* @usage   ShapeProfile使用例
* @author  mw
* @date    2015年12月02日  星期三  12:06:47 
* @param
* @return
*
*/
	function myplot() {
		plot.init();
		setPreference();				

		setSector(1,1,1,1);
		axis(0, 0, 180);
		
		var shape = new ShapeProfile();
		//偏移
		shape.draw(1,100,100);
		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("A", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
		//逆时针为正向,角度以弧度计算
		shape.draw(1,0,0,100, 4, Math.PI/8);
		/*
				X	Y
			-38.268	-92.388
			92.388	-38.268
			38.268	92.388
			-92.388	38.268
		*/
		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("B", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
		//缺省实现
		shape.draw(1);
		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("C", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
	}
	
结果:



(2) 

/**
* @usage   ShapeProfile使用例
* @author  mw
* @date    2015年12月02日  星期三  12:06:47 
* @param
* @return
*
*/
	function myplot() {
		plot.init();
		setPreference();				

		setSector(1,1,1,1);
		axis(0, 0, 180);
		
		var shape = new ShapeProfile();
		//偏移
		shape.draw(2,100,100,50, 5, Math.PI/2);
		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("A", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot//.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot//.closePath()
				.stroke();
		}
		
		//逆时针为正向,角度以弧度计算
		shape.draw(2,0,100,100, 4, Math.PI/8);

		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("B", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
		//缺省实现
		shape.draw(2);
		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("C", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
	}
结果:

(3)

/**
* @usage   ShapeProfile使用例
* @author  mw
* @date    2015年12月02日  星期三  12:06:47 
* @param
* @return
*
*/
	function myplot() {
		plot.init();
		setPreference();				

		setSector(1,1,1,1);
		axis(0, 0, 180);
		
		var shape = new ShapeProfile();
		//偏移
		shape.draw(201,100,100,50, 5, 0);
		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("A", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
		//逆时针为正向,角度以弧度计算
		shape.draw(202,-200,100,100, 4, Math.PI/8);
		/*
					X	Y
			-172.284	-111.481
			-238.268	-192.388
			-188.519	-72.284
			-107.612	-138.268
			-227.716	-88.519
			-161.732	-7.612
			-211.481	-127.716
			-292.388	-61.732
		*/

		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("B", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
		//缺省实现
		shape.draw(2, 0, 0, 100, 7, Math.PI/2);
		fillCircle(shape.retArray[0], shape.retArray[1], 10);
		plot.fillText("C", shape.retArray[0]+20, shape.retArray[1]-20, 30);
		if (shape.retArray.length > 2 && shape.retArray.length % 2 == 0) {
			plot.beginPath()
				.moveTo(shape.retArray.shift(), shape.retArray.shift());
			while (shape.retArray.length > 0) {
				plot.lineTo(shape.retArray.shift(), shape.retArray.shift());
			}
			plot.closePath()
				.stroke();
		}
		
	}
结果:

见调用是非常的方便。

并且可以用这个函数看坐标:

/**
* @usage  查看顶点坐标
* @author  mw
* @date    2015年11月29日  星期日  12:58:09 
* @param
* @return
*
*/
	function mytable() {
		var table = $$("table");
		var caption = table.createCaption();
		caption.innerHTML="顶点映射" +"<p>";
		//找<tbody>
		var node = table.firstChild;

		while (null != node) {
		/*
			想知道都有哪些子节点,用这个
				var text = document.createTextNode(node.nodeName);
				document.body.appendChild(text);
		*/
				
			if ("TBODY" == node.nodeName) 
				break;			

			node = node.nextSibling;
		}
		
		var shape = new ShapeProfile();
		
		shape.draw(1,0,0,100, 4, Math.PI/8);

		//单元格插入
		while (shape.retArray.length > 0) {
				
			//插入<tr>			
			var tr = document.createElement("tr")	
			//插入<td> x
			var td = document.createElement("td");
			var x = document.createTextNode(shape.retArray.shift().toFixed(3));
			td.appendChild(x);
			tr.appendChild(td);
					
			//插入<td> y
			var td = document.createElement("td");
			var y = document.createTextNode((-shape.retArray.shift()).toFixed(3));
			td.appendChild(y);
			
			tr.appendChild(td);

			
			node.appendChild(tr);
		}		
	}
	
这节就到这里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值