canvas烟花炫酷效果,javascript烟花代码

  canvas烟花炫酷效果,javascript烟花代码

  快过年了,打算偷偷在后台埋个彩蛋过年,放烟花。项目基于react typescript,所以最后封装成一个组件,设置打开时间后就可以显示了。

  目录结构

  目录结构大致如下

  我们把烟花分为两个阶段,一个是爆炸前的持续上升期,一个是爆炸后的分散期。

  Vector代表坐标,Particle代表烟花的一个亮点,firewor代表烟花没有爆炸时一直上升的亮点。Index.tsx是组件,绘制画布并执行动画。

  Vector

  这个坐标非常简单,后面涉及位置的变化可以用它的add方法来抵消。

  导出默认类Vector { constructor(public x:number,public y:number){ } add(ve C2:{ x:number;y:number }){ this . x=this . x ve C2 . x;this . y=this . y vec 2 . y;}}Particle

  创建之初给个坐标,以后每次更新的时候控制Y坐标的下降。重力变量是下降值。TimeSpan用于控制焰火显示的持续时间。

  从导入向量。/Vector ;导出默认类粒子{ pos:Vector=null;vel:{ x:number;y:number }=null;dead:boolean=false;start:number=0;CTX:canvasrenderingcontext 2d=null;构造器(位置:{x:数字;y: number},vel:{ x:number;y: number},CTX:canvasrenderingcontext 2d){ this . pos=new Vector(pos . x,pos . y);this.vel=velthis.dead=falsethis . start=0;this.ctx=ctx}更新(time: number,gravity:number){ let timeSpan=time-this . start;if(timeSpan 500){ this . dead=true;}如果(!this . dead){ this . pos . add(this . vel);this.vel.y=this.vel.y重力;} } draw() { if(!this . dead){ this . draw dot(this . pos . x,this.pos.y,Math.random() 0.5?1 : 2);} } drawDot(x:数字,y:数字,size:数字){ this . CTX . begin path();this.ctx.arc(x,y,size,0,Math。PI * 2);this . CTX . fill();this . CTX . close path();}}Firework

  生成一个随机的hsl颜色,hsl( rndNum(360),100%,60%);每次烟火升起,距离都是一个递减的过程。我们最初设定了一个上升的距离,然后每画一次,这个距离就会因为重力而减少。当距离小于零时,意味着烟花该绽放了。

  从导入向量./Vector ;从导入粒子.粒子;设rnd=数学.随机函数rnd num(num:number){ return rnd()* num 1;}导出默认类firework { pos:Vector=null;vel:Vector=null;color:string=null;size:number=0;dead:boolean=false;start:number=0;CTX:canvasrenderingcontext 2d=null;重力:数字=空;ex粒子:粒子[]=[];ex len:number=100;root show:boolean=true;构造函数(x:数字,y:数字,重力:数字,CTX:canvasrenderingcontext 2d){ this。pos=新向量(x,y);this.vel=新向量(0,-rnd num(10)-3);this.color=hsl( rndNum(360),100%,60%);这个。大小=4;this.dead=falsethis。start=0;this.ctx=ctxthis.gravity=重力;}更新(时间:数字,重力:数字){如果(这个。死){返回;}这个。根秀=这个。维尔。y 0;如果(这个。根秀){这个。位置。补充(这个。vel);这一点重力;} else { if(这个。ex粒子。长度===0){ for(让I=0;I this . exp leni){ let randomR=rnd num(5);设randomX=-rnd num(数学。ABS(randomR)* 2)数学。ABS(randomR);设randomY=数学。sqrt(数学。ABS(数学。pow(randomR,2) - Math.pow(randomX,2))) * (Math.random() 0.5?1 : -1);这个。ex粒子。推(新粒子(这个。pos,新向量(randomX,randomY),这个。CTX));这个。ex粒子【这个。ex粒子。长度-1].开始=时间;} }设numOfDead=0;对于(设I=0;i this.exPLeni ) {设p=这个。ex粒子[I];p.update(时间,这个。重力);if(p . dead){ numOfDead;} } if(numOfDead===这个。{这个。死=真;} } } draw(){ if(这个。死){返回;}这个。CTX。填充样式=this。颜色;如果(这个。根秀){这个。画点(这个。位置。x,this.pos.y,this。尺寸);} else { for(设I=0;i this.exPLeni ) {设p=这个。ex粒子[I];p . draw();} } } drawDot(x:数字,y:数字,尺寸:数字){这个。CTX。begin path();this.ctx.arc(x,y,size,0,Math .PI * 2);这个。CTX。fill();这个。CTX。关闭路径();}}FireworkComponent

  组件本身就很简单了,生成和绘制烟火。我们在这里面可以额外加一些文字

  从“做出反应”导入做出反应;从导入烟花.烟火;从“核心装饰者”导入{自动绑定};设rnd=数学.随机函数rnd num(num:number){ return rnd()* num 1;}接口属性类型{ onClick?()=void} @ auto bind类烟火组件扩展做出反应.ComponentPropTypes { canvas:HTMLCanvasElement=null;CTX:canvasrenderingcontext 2d=null;snap time:number=0;fireworks:Firework[]=[];重力:数字=0.1;componentdimount(){ this。画布=文档。查询选择器(“# fireworks”);这个。画布。宽度=窗口。内部宽度;这个。画布。高度=窗口。内部高度;这个。CTX=这个。画布。获取上下文(“2d”);这个。init();这个。draw();} init(){ let numOfFireworks=20;对于(设I=0;我numOfFireworksI){ this。烟花。推(新烟花(rnd号(这个。画布。width),this.canvas.height,this.gravity,this。CTX));} }更新(time:number){ for(设I=0,len=this。烟花。长度;我lenI){让p=这个。烟花[I];p.update(时间,这个。重力);} }画(时间?数字){这个。更新(时间);this.ctx.fillStyle=rgba(0,0,0,0.3);this.ctx.fillStyle=rgba(0,0,0,0);this.ctx.clearRect(0,0,this.canvas.width,this。画布。身高);this.ctx.font=bold 30px草书;这个。CTX。填充样式= # e 91818let text=XX项目组给您拜个早年!;设文本宽度=this。CTX。测量文本(文本);this.ctx.fillText(text,this。画布。宽度/2-文本宽度。宽度/2200);text=在新年来临之际,祝您:;文本宽度=this。CTX。测量文本(文本);this.ctx.fillText(text,this。画布。宽度/2-文本宽度。宽度/2260);text=工作顺利,新春快乐!;这个。CTX。font= bold 48px STCaiyun这个。CTX。填充样式= orangered文本宽度=this。CTX。测量文本(文本);this.ctx.fillText(text,this。画布。宽度/2-文本宽度。宽度/2340);这个。CTX。填充样式=灰色;这个。CTX。font=" 18px Arial ";text=点击任意处关闭;文本宽度=this。CTX。测量文本(文本);this.ctx.fillText(text,this。画布。宽度-20-文本宽度。宽度,60);这个。快照时间=时间这个。CTX。填充样式=蓝色;对于(设i=0,len=this。烟花。长度;我lenI){让p=这个。烟花[I];if(p . dead){ p=this。fireworks[I]=新的烟火(rnd num(this。画布。width),this.canvas.height,this.gravity,this。CTX);p.start=时间;} p . draw();}窗口。requestanimationframe(this。画);} render(){ return(canvas id= fireworks onClick={ this。道具。onClick } style={ { position: fixed ,zIndex: 99,background: rgba(0,0,0,0.8) } } width= 400 height= 400 /canvas);} }导出默认消防工作组件大致效果

  以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: