博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象+模块化设计绘制canvas星空动画
阅读量:7041 次
发布时间:2019-06-28

本文共 6105 字,大约阅读时间需要 20 分钟。

hot3.png

require.js的相关内容已在我的博文

《requireJs的使用,以canvas绘制星空为例》中描述,

可查看:

下面说一下面向对象设计canvas绘制星空的各种对象。

1、静态元素

如背景(Backgound)、土地(Land)、房屋(House)、大树(Tree),这些元素的属性如坐标(x,y)、长度(width)、高度(height)等信息是固定不变,因此我们只用向其绘制函数内传入常量参数就可以维持其状态。

2、随机元素

所谓随机,是指元素的参数信息是随机生成的,在星空绘制的canvas中,存在大量五角星,我们不可能一个个为之赋属性(太过麻烦);也不可能用定步长迭代赋值得方法赋属性(这样会使得星空失去无序性)。

所以我们采用随机+迭代的方法为星星赋值属性。

如坐标可用(Math.random()*width,+Math.random()*height/2)使星星均匀且无序填充在canvas画布上半部分。

3、动画元素

动画元素是指在canvas画布中具有动画效果的元素。在本例中包含流星和上下摆动的文本。

在动画设计中,需要不断重画canvas画布,因此需要不断调用元素的绘制函数。由于随机元素的属性实际上是随机生成固定不变的,动画元素的属性需要在原属性的基础上不断改变,所以这两种元素都需要运用面向对象的封装来保存元素状态。

元素对象模块代码如下:

element.js

define(function(){	var TextNode=function(offUnitX,offUnitY,str,direction,offLimitY){		var x,y,str;		var fillStyle,font;		var zx,zy,offX,offY,offUnitX,offUnitY;		var speed,direction,topLimit,bottomLimit,offLimitY;		//direction标识上下波动的方向		//topLimit,bottomLimit标识上下波动的界限		//默认参数		this.zx=420;		this.zy=420;		this.offX=22;		this.offY=-5;		this.speed=1;		this.fillStyle="#70DBDB";		this.font="30px Georgia,Arial";		this.test=function(){			// alert(this.str.length+","+this.offY);			// alert(this.str.length*this.offY/4);			// alert(this.topLimit+","+this.bottomLimit);		}		//初始化变量		this.init=function(){			//接收参数			this.offUnitX=offUnitX;			this.offUnitY=offUnitY;			this.str=str;			this.direction=direction;			this.x=this.zx+offUnitX*this.offX;			this.y=this.zy-offUnitY*this.offY;			this.topLimit=this.zy+this.offY*offLimitY;			this.bottomLimit=this.zy-this.offY*offLimitY;		}		//初始化,创建即调用		this.init();		//摆动文本		this.wave=function(){			if(this.y+this.direction*this.speed
this.bottomLimit) this.direction=-this.direction; this.y+=this.direction*this.speed; } //绘制文本 this.draw=function(cxt){ cxt.font=this.font; cxt.fillStyle=this.fillStyle; cxt.fillText(this.str,this.x,this.y); } this.setZX=function(zx){ this.zx=zx; } this.setZY=function(zy){ this.zy=zy; } this.setOffX=function(offX){ this.offX=offX; } this.setOffY=function(offY){ this.offY=offY; } this.setSpeed=function(speed){ this.speed=speed; } this.setFillStyle=function(fillStyle){ this.fillStyle=fillStyle; } this.setFont=function(font){ this.font=font; } }; var Star=function(){ var x,y,R,rotate; var fillStyle; this.fillStyle="yellow"; this.init=function(){ this.x=Math.random()*780+10; this.y=(Math.random()*580+10)*3/5; this.R=Math.random()*5+3; this.rotate=Math.random()*72; } //创建即初始化 this.init(); this.draw=function(cxt){ // 设置填充样式为黄色 cxt.fillStyle=this.fillStyle; //beginPath()新建路径 cxt.beginPath(); //五角星有10个顶点,循环设置顶点 for(var i=0;i<5;i++){ cxt.lineTo(Math.cos((72*i+this.rotate)*Math.PI/180)*this.R+this.x, Math.sin((72*i+this.rotate)*Math.PI/180)*this.R+this.y); // 在这里使用小圆半径为大圆的一半 cxt.lineTo(Math.cos((72*i+36+this.rotate)*Math.PI/180)*this.R/2+this.x, Math.sin((72*i+36+this.rotate)*Math.PI/180)*this.R/2+this.y); } //closePath()闭合路径 cxt.closePath(); //绘制 cxt.fill(); } this.setFillStyle=function(fillStyle){ this.fillStyle=fillStyle; } }; var ShootStar=function(){ var x,y,R,angle,arc,rotate; var fillStyle; var speed,delay,counter,bottom; //arc为根据角度计算出的弧度,用以计算流星的运动轨迹 //bottom为流星下落的下边界,超界则重置流星属性 //设置delay并在类中初始化为常量,标识在多少次间隔后开始本流星对象的降落 //counter为计数器,每次间隔,counter自增,当counter>=delay时,流星开始降落 //isBegin标识是否开始降落 this.bottom=Math.random()*100+500; this.delay=Math.random()*500; this.counter=0; this.fillStyle="yellow"; this.init=function(){ this.x=Math.random()*600+200; this.y=Math.random()*100+20; this.R=Math.random()*5+3; this.angle=Math.random()*30+30; this.arc=this.angle*Math.PI/180; this.rotate=Math.random()*72; this.speed=Math.random()*1+1; } this.draw=function(cxt){ cxt.fillStyle=this.fillStyle; cxt.beginPath(); for(var i=0;i<5;i++){ cxt.lineTo(Math.cos((72*i+this.angle+this.rotate)*Math.PI/180)*this.R+this.x, Math.sin((72*i+this.angle+this.rotate)*Math.PI/180)*this.R+this.y); cxt.lineTo(Math.cos((72*i+36+this.angle+this.rotate)*Math.PI/180)*this.R/2+this.x, Math.sin((72*i+36+this.angle+this.rotate)*Math.PI/180)*this.R/2+this.y); } cxt.closePath(); cxt.fill(); } //判断是否开始降落流星 this.isBegin=function(){ return ++this.counter>this.delay; } this.move=function(){ //如果流星降到canvas距离顶部bottom之内的范围,继续下降,否则流星消失 if(this.y
=0){ this.x-=this.speed*Math.cos(this.arc); this.y+=this.speed*Math.sin(this.arc); this.rotate++; }else this.init(); } this.setFillStyle=function(fillStyle){ this.fillStyle=fillStyle; } }; var foo=function(){ alert(1); }; return { TextNode:TextNode, Star:Star, ShootStar:ShootStar, foo:foo };});

在本模块中为了方便外部调用,并未使用任何私有元素。

所有不是随机的变量和控制运动的变量全部设置了默认值,并添加了setter函数方便外部更改。

每种对象都包含draw(cxt)函数用于对象实例的绘制。

动画元素包含控制动画进行的函数。

 

程序主函数如下:

main.js

require.config({	paths:{		"jquery"	:"jquery.min",		"common"	:"common",		"element"	:"element"	}});require(['common','jquery'],function(common,$){	$(document).ready(function(){		var context=common.getContext("canvas",800,600);		common.run(context,"SO BEAUTIFUL A NIGHT!",200,10);	});});

元素绘制模块代码如下:

common.js

define(['element'],function(element){	var textSet=new Array();	var starSet=new Array();	var shootStarSet=new Array();	//获取文本对象	var getContext=function(id,width,height){		var canvas=document.getElementById(id);		canvas.width=width;		canvas.height=height;		var context=canvas.getContext("2d");		return context;	};	var initTextSet=function(str){		var lowMid=Math.floor(str.length/4);		var mid=Math.floor(str.length/2);		var highMid=Math.floor(str.length/4*3);		//创建中点文本节点		textSet[mid]=new element.TextNode(0,0,str[mid],1,str.length/4);		textSet[mid].test();		for(var i=1;i<=mid;i++){			//创建lowMid-highMid之间的节点			if(i
浅绿 var grd=cxt.createLinearGradient(0,2,0,0); grd.addColorStop(0,"#040"); grd.addColorStop(1,"#5a0"); cxt.fillStyle=grd; cxt.fill(); cxt.restore(); }; //绘制一个星星 var drawStar=function(cxt){ var star=new element.Star(); star.init(); star.draw(cxt); }; //绘制starSet中的所有星星 var drawStars=function(cxt){ for(var i=0;i

 

最后程序入口:

index.html

	Beautiful Night	

转载于:https://my.oschina.net/lonelydawn/blog/675506

你可能感兴趣的文章
全景制作
查看>>
在Windows7系统上重新安装Windows XP
查看>>
PhotoShop中让索引图片解锁使用
查看>>
【面试题】-RabbitMQ常见面试题(二)
查看>>
Spring框架使用ByName自动注入同名问题剖析
查看>>
HDOJ-2546 饭卡【DP】【01背包】
查看>>
币值转换
查看>>
POJ 2728 Desert King (算竞进阶习题)
查看>>
(转)heX——基于 HTML5 和 Node.JS 开发桌面应用
查看>>
通过腾讯地图api获取用户位置限制在指定位置区域
查看>>
Archlinux GRUB2 配置
查看>>
第二周作业
查看>>
团队事后分析
查看>>
mysql 关于列的语句
查看>>
博客作业2---线性表
查看>>
grub2引导安装kali2.0及安装ibus拼音输入法
查看>>
SQL常用命令
查看>>
Linux~Docker部分~
查看>>
Simple2D-15(音乐播放器)使用 glfw 库
查看>>
web.config 配置与获取
查看>>