canvas学习(六):五颜六色的星星之图形变换

效果图和前一篇一样,只是用的方法不一样。前一篇用代码直接设置偏移量和旋转角度,这一片使用canvas的函数进行绘制。废话不多说,直接上代码:

window.onload=function(){
	var myCanvas = document.getElementById("myCanvas");
	if(myCanvas.getContext("2d")){
		myCanvas.width = document.documentElement.clientWidth-20;;
		myCanvas.height = document.documentElement.clientHeight-20;;
		var context =myCanvas.getContext("2d");
		
		//绘制更多的星星
		var colors=["#33B5E5","#0099CC","#AA66CC","#9933CC","#99CC00","#669900","#FFBB33","#FF8800","#FF4444","#CC0000"];//绘制各种颜色的星星
		//colors="#fd5";//绘制一种颜色的星星
		drawMoreStars(context,200,10,colors);
	}else{
		return false;
	}
}

/**
*该方法用来绘制各种颜色的星星
*@param cxt:canvas的上下文环境
*@param num:绘制的星星的数量
*@param radius:星星半径,以后随机生成半径会在radius与2*radius之间
*@param colors:颜色,可能是数组,也可能只是一个颜色
**/
function drawMoreStars(cxt,num,radius,colors){
	//绘制一个背景色
	cxt.fillStyle="black";
	cxt.fillRect(0,0,myCanvas.width,myCanvas.height);//绘制一个与当前画布一样大的矩形,背景色为fillStyle设置的颜色		
	
	//绘制一片星空
	var color="white";//默认为白色的星星
	for(var i=0;i<num;i++){
		var R1 = Math.random()*radius+radius;//大圆直径20-40之间
		var x = Math.random()*myCanvas.width;//x轴的偏移量
		//左侧不出界
		if(x<R1)x=R1;
		//右侧不出界
		if(x>=myCanvas.width-R1){x=myCanvas.width-R1;}

		var y = Math.random()*myCanvas.height;//y轴的偏移量
		//上面不出界
		if(y<R1) y=R1;
		//下面不出界
		if(y>=myCanvas.height-R1){y=myCanvas.height-R1;}
		
		if(isArray(colors)){//给定的是数组,那么从数组中随机获取一个颜色
			color=colors[Math.floor(Math.random()*colors.length)];//星星的颜色
		}else{//只是一个颜色,直接设置就好
			color=colors;
		}
		//alert(x+"\t"+myCanvas.width+"\t"+R1+"\n"+y+"\t"+myCanvas.height);
		var rot = Math.random()*360;//旋转角度在0-360度之间
		drawStar(cxt,R1,x,y,color,rot);
	}
}

/**
*该方法用来绘制五角星(五角星的绘制可以理解成在两个大圆中绘图)
*@param cxt:canvas的上下文环境
*@param R:大圆的半径,用来绘制向外的五个点(小圆半径默认为大圆的一半)
*@param x:在x方向的偏移量,若是不设置,默认为0,做左上角进行绘制
*@param y:在y方向的偏移量,若是不设置,默认为0,做左上角进行绘制
*@param fillColor:五角星的填充色
*@param rot:旋转角度
*/
function drawStar(cxt,R,x,y,fillColor,rot){		
	//保存context的状态
	cxt.save();
	cxt.translate(x,y);//设置偏移量
	cxt.rotate(rot/180*Math.PI);//设置旋转弧度
	//将每个星星的宽度和高度都缩放R倍
	cxt.scale(R,R);//使用缩放让每个星星的大小不一样(因为scale会使lineWidth随着缩放,所以此处不再设置边框的一些属性)
	drawStarPath(cxt);//绘制一个大小相同的五角星

	cxt.fillStyle=fillColor;//填充色
	cxt.lineJoin="round";//边角

	//先填充,后描边
	cxt.fill();
	cxt.restore();//恢复保存之前的状态
}

/**
*该方法用来绘制一个没有偏移量的五角星的各条边
*@param cxt:canvas的上下文环境
*/
function drawStarPath(cxt){
	//绘制五角星
	cxt.beginPath();
	for(var i=0;i<5;i++){
		//绘制大圆中的五个角
		//第一个角为18度,以后大圆的每个角都是(18+72的倍数)度
		//(18+i*72)/180*Math.PI:将角度转换成弧度
		//因为绘制五角星的坐标系y轴与普通的坐标系相反,x轴以上为负数,x轴以下为正数,所以此处y轴的坐标为负数
		cxt.lineTo(Math.cos((18+i*72)/180*Math.PI),-Math.sin((18+i*72)/180*Math.PI));
		//绘制小圆中的五个角
		//与大圆的各个角一致,第一个角为54度,以后每个角都是(54+72的倍数)度
		//每个星星的小圆半径默认为大圆半径的一半
		cxt.lineTo(Math.cos((54+i*72)/180*Math.PI)*0.5,-Math.sin((54+i*72)/180*Math.PI)*0.5);
	}
	cxt.closePath();
}
//该方法用来判断是否为数组
var isArray = function(obj) { 
	return Object.prototype.toString.call(obj) === '[object Array]'; 
};

看代码可以知道,这个是用了canvas的translate(x,y)函数让原本中规中矩的图像产生偏移,使用rotate函数让图像旋转一定弧度,再使用scale对图像进行一定的缩放。此代码有以下几个注意点:

1、星星的大圆半径是参数传递过来的,小圆半径却是在drawStarPath方法中写死的,它永远是大圆半径的一半。若是不设置这个一半的关系,最后得到的图形不是五角星,而是标准的等边十边形。

2、scale进行缩放的时候有个副作用,就是边框线会随之缩放,所以此处没有设置边框线的样式,同时也没有使用stroke方法,若是调用了五角星会缺角,有兴趣的可以试试。

3、scale的两个参数是分别用来设置缩放的宽度和高度的,这里设置的是一样的以保证五角星不变形。大家可以试着调整一下来加深一下对“图形变换”的理解。

猜你喜欢

转载自1017401036.iteye.com/blog/2309789