实现步骤:
续前节,本节我想要绘制一些空心的星形。本来我想用点的递推法来绘制,这样就先封装了正多边形的绘制函数。
/** * @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);
结果如图
接下来想从多边形顶点往外推星星角的顶点却遇到了很多的麻烦,尤其是同心和偏移这些方面,顶点很难算。所以采用了简单算法。
/** * @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); }
这个的结果是这样的。
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);
大部分时候这种非对称的星星最好看,但是怎样得到那种尖峰很正的星星呢?所以我就去改动绘制参数。当最终函数变成这样的时候。
/** * @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(); }
结果图是:
这个看上去好像就很正点了。
在这个过程中,还发现了其它有意思的图形。比如缩小r0的值,会得出这样的图:
而放大旋转效应,会得到这样的图:
至于缩小旋转效应:
让旋转因子变得很大并且不让它们同步,比如设成这样:
xArray.push(r * Math.cos(i * perAngle + 77 * perAngle)); yArray.push(r * Math.sin(i * perAngle + 100 * perAngle));会得到这种图
而如果让内外圆半径倒挂,比如
//r0 = 0.6 * r; //var r0 = r / 2 /(1 + Math.cos(perAngle)); var r0 = 2 * r;
会得到
其它的漂亮的图还有很多,只需要调整参数就行了。
比如