论坛首页 Web前端技术论坛

让google下雪变成现实 let it snow(更新了雾气)

浏览 11540 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-12-22   最后修改:2011-12-28
看了google的下雪觉的很不错!于是就想自己做下!
在往上查了些资料,于是就写了一个下雪的原理!拿出来分享下!一些代码是网上找的!
本人又进行了2次修改!给雪花加入了生命周期,过期的将被销毁!
/////////////////////////////////////
	/////////////////////////////////////
	/**
	 * 精灵对象类似flash中的精灵
	 * 所有的动画元素都必须继承自此对象,继承之后自动拥有move、speed等方法和属性
	 * 每个动画元素都必须拥有一个自己的特殊的draw()方法的实现,这个方法用来在渲染每一帧的时候指定自己如何实现在canvas帧画布上
	 * 注意这里的“帧画布”不是指原生的canvas元素,而是指下面定义的一个Canvas对象
	 * ,此对象的意义就是一个帧,他负责把需要在这一帧上呈现的图像画到canvas上,然后每一帧开始的时候清除上次画得,类似flash中的帧的概念
	 */
	//创建精灵
	EasyJs.Sprite=function(config){
		EasyJs.Sprite.superclass.constructor.call(this,config);
	}
	EasyJs.extend(EasyJs.Sprite,EasyJs.Component,{
		speed:{x:1,y:1},
		/**
		 * 每个精灵都有自己的draw实现
		 */
		draw:function(){},
		/**
		 * 精灵移动
		 */
		move:function(datatime){
			this.x+=((this.speed.x/40)*datatime);
			this.y+=((this.speed.y/40)*datatime);
			if(this.childs!=null&&this.childs.length>0){
				for(var i=0;i<this.childs.length;i++){
					this.childs[i].speed=this.speed;
					this.childs[i].move();
				}
			}
		},
		/**
		 * 添加一个子精灵
		 */
		appendChild:function(childSprite){
			if(this.childs==null){
				this.childs=[];
			}
			this.childs.push(childSprite);
		},
		/**
		 * 渲染子精灵
		 */
		drawChilds:function(){
			if(this.childs!=null&&this.childs.length>0){
				for(var i=0;i<this.childs.length;i++){
					this.childs[i].draw();
				}
			}
		},
		/**
		 * 生命周期(生成日期和存活时间),单位是毫秒
		 */
		lifeCycle:{productionTime:(new Date()).getTime(),survivalTime:10000},
		/**
		 * 消失
		 */
		disappear:function(){
			this.death=true;
			//由继承子类改写
		},
		/**
		 * 标注是否死亡,如死亡将被回收
		 */
		death:false
		
		
	});
	/**
	 * 帧对象,没隔一段时间重画自己一次,累世flash中的帧概念
	 * 原理就是每到一定时间就清除canvas,然后调用当前帧里的所有的动画元素的draw()方法,
	 * 将所有的动画元素按照新的配置重画
	 * 从而生成动画,之后程序无需关心元素的重画,只需要调整元素属性即可,
	 * 这个对象会自动管理元素的渲染
	 */
	EasyJs.Canvas=function(config){
		EasyJs.Canvas.superclass.constructor.call(this,config);
	}
	EasyJs.extend(EasyJs.Canvas,EasyJs.Component,{
		/**
		 * 刷新时间
		 */
		FPS:40,
		/**
		 * 刷新器
		 */
		interval:null,
		/**
		 * 精灵数组
		 */
		sprites:[],
		/**
		 * 上一次刷新时间,毫秒
		 */
		lastFrame:(new Date()).getTime(),
		/**
		 * 开始画图
		 */
		begin:function(factory){
			this.interval=setInterval((function(param){
				return function(){param.render(factory);}
			})(this),this.FPS);
		},
		/**
		 * 渲染   factory调用的精灵工厂
		 */
		render:function(factory){
			this.ctx.clearRect(-800,-800,1600,1600);
			/**
			 * 当期帧时间(毫秒)
			 */
			var thisFrame = new Date().getTime();
			/**
			 *和上一帧的时间间隔 (毫秒)
			 */
			var dt = (thisFrame - this.lastFrame);
			this.lastFrame=thisFrame;
			/**
			 * 先让精灵工厂生成精灵
			 */
			factory.output(this,5,1000);
			for (var i in this.sprites  ) {
			  if(typeof(this.sprites[i])=="function"){
			  		continue;
			  }
			  this.sprites[i].draw();
			  this.sprites[i].move(dt);
			};
		},
		stop:function(){
			clearInterval(this.interval);
		},
		addSprite:function(name,sprite){
			this.sprites[name]=sprite;
		}
	});
	
	/**
	 * 雪花
	 * @param ctx canvas的实例
	 * @param x x坐标
	 * @param y y坐标
	 * @param radius 半径
	 */
	EasyJs.Snowflake=function(config){
		EasyJs.Snowflake.superclass.constructor.call(this,config);
	}
	EasyJs.extend(EasyJs.Snowflake,EasyJs.Sprite,{
		draw:function(){
			var ctx=this.ctx;
			ctx.beginPath(); 
			for (var i=0; i < 6; i++) {
				var hd=i*(Math.PI*2/6)
				ctx.strokeStyle=this.strokeStyle;
				ctx.moveTo(this.x,this.y);
			  	ctx.lineTo(this.x+Math.cos(hd)*this.radius,this.y+Math.sin(hd)*this.radius); 

			};
			ctx.stroke();
			this.drawChilds();
		},
		strokeStyle:"#000",
		lineWidth:"1",
		disappear:function(){
			EasyJs.Snowflake.superclass.disappear.call(this); 
			this.strokeStyle="#CCCCCC";
			this.lineWidth="0.5";
		}
	});
	/**
	 * 雪花的生产工厂,设置雪花的大小,速度,初始位置等
	 */
	EasyJs.SnowflakeFactory=function(config){
		EasyJs.SnowflakeFactory.superclass.constructor.call(this,config);
	}
	EasyJs.extend(EasyJs.SnowflakeFactory,EasyJs.Component,{
		spriteNameFactor:1,
		/**
		 * 上一次精灵生成的时间 lastTime
		 * 输出精灵  canvas(渲染面板) max 每次生成的数量  time多久生成一次
		 */
		output:function(canvas,max,time){
			var thisTime = new Date().getTime();
			if(this.lastTime==null){
				this.lastTime=0;
			}
			if((thisTime-this.lastTime)>(time-1)){			
				this.lastTime=thisTime;
				if(max==null){
					max=10;
				}
				this.recover(canvas,800,800);
				var factor={x:800,y:-10};
				for(var i=0;i<max;i++){
					var location=this.initSpriteLocation(factor);
					var life=this.initLife();
					var snowflake=new EasyJs.Snowflake({ctx:canvas.ctx,x:location.x,y:location.y,radius:this.initRadius(),lifeCycle:life});
					snowflake.speed={x:Math.random()*2,y:Math.random(10)*2};
					canvas.addSprite(this.spriteNameFactor+"sprite+"+i,snowflake);
				}			
				this.spriteNameFactor++;
			}
		},
		initSpriteLocation:function(factor){
			factor.x=Math.floor(Math.random()*factor.x);
			factor.y=Math.floor(Math.random()*factor.y);
			return factor;
		},
		initRadius:function(){
			var r=Math.random()*10;
			if(r<2){
				r=2;
			}
			return r;
		},
		initLife:function(){
			var left={};
			left.productionTime=(new Date()).getTime();
			left.survivalTime=Math.floor(Math.random()*5000)+5000;
			return left;
		},
		/**
		 * 雪花回收
		 */
		recover:function(canvas,xMax,yMax){
			var sprites=canvas.sprites;
			if(sprites.length>50){
				//alert(5);
			}
			for(var i in sprites){
				var sprite=sprites[i];
				if(typeof(sprites[i])=="function"){
					continue;
				}
				if(sprite.x>xMax&&sprite.y>yMax){
					sprites[i].death=true;
				}
				if(sprite.death==true){
					delete sprites[i];
					continue;
				}
				var currentTime=(new Date()).getTime();
				if(currentTime-sprite.lifeCycle.productionTime>sprite.lifeCycle.survivalTime){
					sprites[i].disappear();
				}
			}	

		}
	});
	
	var c=document.getElementById("myCanvas");
	var context=c.getContext("2d");
	var can=new EasyJs.Canvas({ctx:context,FPS:40});
	var fc=new EasyJs.SnowflakeFactory({canvasObj:c});
	can.begin(fc);

再次更新雾气效果,我把2个效果给分开了!google的下雪是div做的(原理就是我的哪个下雪原理),雾气是用canvas做的(原理和我差不多)!雾气效果代码见下边
EasyJs.extend(EasyJs.FogCanvas,EasyJs.Component,{
		/**
		 * 刷新器
		 */
		interval:null,
		/*
		 * 获取canvas的dom对象
		 */
		getDom:function(){
			if(this.dom==null){
				this.dom=document.getElementById(this.id);
			}
			return this.dom;
		},
		/**
		 * 获取画板的CanvasRenderingContext2D 对象
		 */
		getCtx:function(){
			if(this.ctx==null){
				this.ctx=this.getDom().getContext('2d');
			}
			return this.ctx;
		},
		/**
		 * 获取画笔的CanvasRenderingContext2D 对象
		 */
		getPointerCtx:function(){
			if(this.pointerCtx==null){
				this.pointerCtx=this.getCtx();
			}
			return this.pointerCtx;
		},
		/**
		 * 获取CanvasGradient 对象 ,返回一个圆形的渐变
		 */
		getCtxGradient:function(x,y){
			var ctxGradient=this.getPointerCtx().createRadialGradient(x,y,0,x,y,50);
			ctxGradient.addColorStop(0, '#F0F6F6');
			ctxGradient.addColorStop(1, '#fff');
			return ctxGradient;
		},		
		//outAreaWidth:this.width,
		outAreaHeight:50,
		/**
		 * 画雾气
		 */
		draw:function(ctx){
			var x=Math.floor(Math.random()*this.outAreaWidth),y=Math.floor(Math.random()*this.outAreaHeight);
			ctx.fillStyle=this.getCtxGradient(x,y);
			ctx.beginPath();
			ctx.arc(x,y,50,0,Math.PI*2,true)
			ctx.fill();
		},
		begin:function(){
			this.interval=setInterval((function(param){
				return function(){param.render();}
			})(this),100);
		},
		recorder:1,
		//data类型的格式(data:image/gif;base64,AAAA):
		image:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHYAAAAcAQMAAACOBtluAAAAA3NCSVQICAjb4U/gAAAABlBMVEUA AAD///+l2Z/dAAAACXBIWXMAAAsSAAALEgHS3X78AAAAFnRFWHRDcmVhdGlvbiBUaW1lADEyLzI2 LzExdF/7vAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAEdSURBVBiV TdHNSsNAEAfwf6lQhcJeFQp5kWIuPkjfwBcIprlYD0KuPUjzKpUeepH6BpIQsBfBrHtwF8eMM+mX A7Pkxw6bmV2wxI8ut5oE/fS65JILQgmkPt17nnS2uj+TfBqDA3MDtEBf6hNMgag8uKDOa+Y2ZUfA EEXg4r/nV1mR7631et4lBu0EcWd/MSUxl+rFrr+YuyB+k/9Lb+nBmxEIPd4H9TZjVLzmKYz2I06w ivKjw0uCz/tISl+ZHIvl/GV68lJtTi4Jk3OYoyuZz1Gk9o59qAlyF1K/5eC+Q1aptZ93ts6G1fMHeBvUce2sXT+U4Jn6K1652rajG5DR222SQdOv/fUZyjjTF7kz3jhKh7Ayj4zWape//PgHvbo00SZP BHcAAAAASUVORK5CYII=',
		render:function(){
			var ctx=this.getCtx();
			ctx.globalAlpha=0.2;
			for(var i=0;i<20;i++){
				this.draw(ctx);
			}
			if(this.recorder==6){
				this.outAreaWidth=this.width;
				this.outAreaHeight=this.height;
			}
			if(this.recorder==100){
				this.removeInterval();
				var image=new Image();
				image.src=this.image;
				ctx.fillStyle="red";
				ctx.globalAlpha=1.0;
				ctx.drawImage(image, 400, 400);
				var drop=false,xy={},th=this;				
				EasyJs.Event.addEventHandler(this.dom,"mousedown",function(e){					
					th.erase(ctx,{x:e.clientX,y:e.clientY},e);          			
					drop=true;
					xy.y=e.clientY;
					xy.x=e.clientX;
				});
				EasyJs.Event.addEventHandler(this.dom,"mouseup",function(){
					drop=false;
					xy={};
					
				});
				EasyJs.Event.addEventHandler(this.dom,"mousemove",function(e){
					if(drop==true&&xy.y!=null){
						th.erase(ctx,xy,e);
						xy.y=e.clientY;
						xy.x=e.clientX; 					
					}
				});
				
			}			
			this.recorder++;
		},
		//擦除雾气
		erase:function(ctx,next,e){
			var b=ctx.globalCompositeOperation;
			//globalCompositeOperation 属性说明了绘制到画布上的颜色是如何与画布上已有的颜色组合
			ctx.globalCompositeOperation="destination-out";
			ctx.lineWidth = 20;
            ctx.lineCap = "round";
            ctx.lineJoin = "round";
			ctx.beginPath();
			ctx.moveTo(next.x, next.y);
			ctx.lineTo(e.clientX, e.clientY);
            ctx.stroke();
           	ctx.globalCompositeOperation=b; 
		},
		/**
		 * 删除刷新器
		 */
		removeInterval:function(){
			if(this.interval!=null)
				clearInterval(this.interval);
		},
		/**
		 * 初始对象加载的方法
		 */
		init:function(){
			if(this.outAreaWidth==null){
				this.outAreaWidth=this.width;
			}
		}
});
	var w=new EasyJs.FogCanvas({id:"myCanvas",width:800,height:800});
	w.begin();

   发表时间:2011-12-23  
学习了,有效果
0 请登录后投票
   发表时间:2011-12-23  
说好的朦胧水雾效果呢????
0 请登录后投票
   发表时间:2011-12-23  
使用ActionScript还是用什么语言开发呢??
0 请登录后投票
   发表时间:2011-12-24   最后修改:2011-12-24
google的效果的确强大
0 请登录后投票
   发表时间:2011-12-24  
强!!!!!!!
0 请登录后投票
   发表时间:2011-12-24  
本人会更新后面的效果的
0 请登录后投票
   发表时间:2011-12-25  
老机跑起来`吃力球子的``

风扇噢噢的
0 请登录后投票
   发表时间:2011-12-26  
不错,继续改善
0 请登录后投票
   发表时间:2011-12-26  
IE貌似不支持.
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics