[Canvas绘图] 第07节 “星“心相映

本节目标:
(1) 绘制空心星形

实现步骤:

续前节,本节我想要绘制一些空心的星形。本来我想用点的递推法来绘制,这样就先封装了正多边形的绘制函数。

/**
* @usage  以顶点递推方式绘制正多边形
* @author  mw
* @date    2015年12月01日  星期二  09:42:33 
* @param  (x, y)图形中心坐标,r 外接圆半径 edge 边数
* @return
*
*/
	//{Shape类}
	this.nEdge = function(x, y, r, edge) {
		plot.save();
		//plot.translate(x, y);
		//strokeCircle(x, y, r);	

		var perAngle = Math.PI * 2 / edge;
		var a = r * Math.sin(perAngle / 2);
		var xOff = a;
		var yOff = r*Math.cos(perAngle / 2);
		plot.translate(-xOff , -yOff);				
				
		var x1 = x;
		var y1 = y;
		var x2 = x1 + 2 * a;
		var y2 = y1;

		var xArray = new Array(x1, x2);
		var yArray = new Array(y1, y2);
		
		var angle = 0;
		
		for (var i=0; i < edge; i++) {
			x2 = x1 + 2 * a * Math.cos(angle);
			y2 = y1 + 2 * a * Math.sin(angle);
			
			xArray.push(x2);
			yArray.push(y2);
			
			x1 = x2;
			y1 = y2;
			angle += perAngle;
			
		}
			
		plot.moveTo(xArray[0], yArray[0]);
		for (var i=1; i< xArray.length; i++) {
			plot.lineTo(xArray[i], yArray[i]);
		}
		plot.stroke()
			.restore();
	
	}

用一个Demo测试一下。

		var shape = new Shape();
		setSector(row, col, 1, 1);
		plot.fillText("图A", -width/col+10, -height/row+30, maxWidth);
		axis(0, 0, 80);
		shape.nEdge(0, 0, 50, 5);
		
		setSector(row, col, 1, 2);
		plot.fillText("图B", -width/col+10, -height/row+30, maxWidth);
		axis(0, 0, 80);
		shape.nEdge(0, 0, 50, 7);
		
		setSector(row, col, 1, 3);
		plot.fillText("图C", -width/col+10, -height/row+30, maxWidth);
		axis(0, 0, 80);
		shape.nEdge(50, -50, 40, 6);
		shape.nEdge(-50, 50, 30, 8);
		shape.nEdge(-50, -50, 40, 4);
		shape.nEdge(50, 50, 30, 3);


结果如图

[Canvas绘图] 第07节 “星“心相映_第1张图片

下来想从多边形顶点往外推星星角的顶点却遇到了很多的麻烦,尤其是同心和偏移这些方面,顶点很难算。所以采用了简单算法。

/**
* @usage   空心星形
* @author  mw
* @date    2015年12月01日  星期二  10:06:13 
* @param
* @return
*
*/	
		this.nStar = function(x, y, r, edge) {
			plot.save();
			plot.translate(x, y);
		
			var perAngle = Math.PI * 2 / edge;
			
			var r0 = r * 0.6;
			
			var xArray = new Array();
			var yArray = new Array();
			
			for (var i =0; i<edge; i++) {
				xArray.push(r0 * Math.cos(i * perAngle));
				yArray.push(r0 * Math.sin(i * perAngle));
				xArray.push(r * Math.cos(i * perAngle + perAngle));
				yArray.push(r * Math.sin(i * perAngle + perAngle));
			}
			
			plot.beginPath()
				.moveTo(xArray[0], yArray[0]);
			for (var i=0; i < xArray.length; i++) {
				plot.lineTo(xArray[i], yArray[i]);
			}
			plot.closePath()
				.stroke()
				.restore();		
		
		}
测试的Demo:

/**
* @usage   绘制空心星形
* @author  mw
* @date    2015年12月01日  星期二  08:26:53 
* @param
* @return
*
*/
	function myplot() {
		plot.init();
		setPreference();				
	
		var row = 1;
		var col = 3;
		var width = 300;
		var height = 200;
		var maxWidth = width/col;
		
		
		//<1>
		setSector(row, col, 1, 1);
		plot.fillText("第1步:起点A", -width/col+10, -height/row+30, maxWidth);
		axis(0,0,80);
		
		plot.fillText("A", -20,-10, 10);
		fillCircle(0,0,10);
		
		//<2>
		setSector(row, col, 1, 2);
		axis(0,0,80);
		plot.fillText("第2步:尖峰", -width/col+10, -height/row+30, maxWidth);
	
			
		plot.fillText("A", -20,-10, 10);
		fillCircle(0,0,10);
		
		plot.moveTo(0, 0)
			.lineTo(15, -50)
			.lineTo(30,0)
			.stroke();
		
		
		//<3>
		setSector(row, col, 1, 3);
		plot.fillText("第3步:衍化", -width/col+10, -height/row+30, maxWidth);
		axis(0,0,80);
	
			
		axis(0,0,80);

		var shape = new Shape();
		shape.nStar(50, 0, 50, 5);
		//shape.nEdge(50, 50, 50, 5);
	}


这个的结果是这样的。

[Canvas绘图] 第07节 “星“心相映_第2张图片

		var shape = new Shape();
		//<1>
		setSector(row, col, 1, 1);
		plot.fillText("图A", -width/col+10, -height/row+30, maxWidth);
		axis(0,0,80);
		
		shape.nStar(0, 0, 50, 5);
		
		//<2>
		setSector(row, col, 1, 2);
		axis(0,0,80);
		plot.fillText("图B", -width/col+10, -height/row+30, maxWidth);
		shape.nStar(0, 0, 50, 7);
		
		
		//<3>
		setSector(row, col, 1, 3);
		plot.fillText("图C", -width/col+10, -height/row+30, maxWidth);
		axis(0,0,80);
		shape.nStar(50, 0, 50, 5);
		shape.nEdge(0, 50, 50, 5);

这个的结果是这样的:

[Canvas绘图] 第07节 “星“心相映_第3张图片

部分时候这种非对称的星星最好看,但是怎样得到那种尖峰很正的星星呢?所以我就去改动绘制参数。当最终函数变成这样的时候。

/**
* @usage   空心星形
* @author  mw
* @date    2015年12月01日  星期二  10:06:13 
* @param
* @return
*
*/	
		this.nStar = function(x, y, r, edge) {
			plot.save();
			plot.translate(x, y);
		
			var perAngle = Math.PI * 2 / edge;
			
			//r0 = 0.6 * r;
			var r0 = r / 2 /(1 + Math.cos(perAngle));
			
			var xArray = new Array();
			var yArray = new Array();
			
			for (var i =0; i<edge; i++) {
				xArray.push(r0 * Math.cos(i * perAngle));
				yArray.push(r0 * Math.sin(i * perAngle));
				xArray.push(r * Math.cos(i * perAngle + 0.5 * perAngle));
				yArray.push(r * Math.sin(i * perAngle + 0.5 * perAngle));
			}
			
			plot.beginPath()
				.moveTo(xArray[0], yArray[0]);
			for (var i=0; i < xArray.length; i++) {
				plot.lineTo(xArray[i], yArray[i]);
			}
			plot.closePath()
				.stroke()
				.restore();		
		
		}

结果图是:

[Canvas绘图] 第07节 “星“心相映_第4张图片

个看上去好像就很正点了。


在这个过程中,还发现了其它有意思的图形。比如缩小r0的值,会得出这样的图:

放大旋转效应,会得到这样的图:

[Canvas绘图] 第07节 “星“心相映_第5张图片

于缩小旋转效应:

让旋转因子变得很大并且不让它们同步,比如设成这样:

				xArray.push(r * Math.cos(i * perAngle + 77 * perAngle));
				yArray.push(r * Math.sin(i * perAngle + 100 * perAngle));
会得到这种图

[Canvas绘图] 第07节 “星“心相映_第6张图片

如果让内外圆半径倒挂,比如

	//r0 = 0.6 * r;
			//var r0 = r / 2 /(1 + Math.cos(perAngle));
			var r0 = 2 * r;

得到

[Canvas绘图] 第07节 “星“心相映_第7张图片

其它的漂亮的图还有很多,只需要调整参数就行了。

比如

[Canvas绘图] 第07节 “星“心相映_第8张图片



你可能感兴趣的:([Canvas绘图] 第07节 “星“心相映)