精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-12-22
最后修改:2011-12-28
在往上查了些资料,于是就写了一个下雪的原理!拿出来分享下!一些代码是网上找的! 本人又进行了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(); 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-12-23
学习了,有效果
|
|
返回顶楼 | |
发表时间:2011-12-23
说好的朦胧水雾效果呢????
|
|
返回顶楼 | |
发表时间:2011-12-23
使用ActionScript还是用什么语言开发呢??
|
|
返回顶楼 | |
发表时间:2011-12-24
最后修改:2011-12-24
google的效果的确强大
|
|
返回顶楼 | |
发表时间:2011-12-24
强!!!!!!!
|
|
返回顶楼 | |
发表时间:2011-12-24
本人会更新后面的效果的
|
|
返回顶楼 | |
发表时间:2011-12-25
老机跑起来`吃力球子的``
风扇噢噢的 |
|
返回顶楼 | |
发表时间:2011-12-26
不错,继续改善
|
|
返回顶楼 | |
发表时间:2011-12-26
IE貌似不支持.
|
|
返回顶楼 | |