当前位置: 首页 > 科技观察

Canvas学习笔记:小滴公式,大滴乐趣

时间:2023-03-23 10:47:30 科技观察

最近想做一个网页,把自己在学习HTML5过程中做的一些demo做个合集。但是,如果我只是做一个网页,把所有的demo都一一排列,又太丑了。就想,既然学会了canvas,那就折腾一下浏览器,做个小小的开场动画吧。想了想开场动画的效果,我决定用粒子,因为我觉得粒子更好玩。还记得之前写的第一篇技术博文,是关于文本和图像的粒子化:文本和图像的粒子化。当时只做直线运动,顺便加了一点3D效果。练习公式很简单。所以我想让这个开场动画更有动感。先去DEMO:http://2.axescanvas.sinaapp.com/demoHome/index.html效果是不是比直线运动更有动感?而且它真的很简单,别忘了这篇博文的标题,小公式,大乐趣。做出这样的效果,只用到了我们初中。.还是高中的物理知识,加速运动和减速运动的公式。所以这真的是小液滴配方。楼主很喜欢折腾一些很酷的东西。虽然在日常工作中可能用不到,但是其中的乐趣着实让人着迷。而且,做这些还可以加强编程的思维能力。话不多说,进入正题。简单说明一下原理吧~~~粒子运动的核心代码就是这样:update:function(time){this.x+=this.vx*time;this.y+=this.vy*时间;如果(!this.globleDown&&this.y>0){varyc=this.toy-this.y;varxc=this.tox-this.x;this.jl=Math.sqrt(xc*xc+yc*yc);瓦尔扎=20;varax=za*(xc/this.jl),ay=za*(yc/this.jl),vx=(this.vx+ax*time)*0.97,vy=(this.vy+ay*time)*0.97;这个.vx=vx;这个.vy=vy;}else{vargravity=9.8;varvy=this.vy+重力*时间;if(this.y>canvas.height){vy=-vy*0.7;}这个.vy=vy;}},粒子一共有两种状态,一种是自由落体,一种是吸力。更不用说自由落体了。在说吸力之前先贴出粒子的属性:varDot=function(x,y,vx,vy,tox,toy,color){this.x=x;这个.y=y;这个.vx=vx;这个.vy=vy;this.nextox=毒素;this.nextoy=玩具;this.color=颜色;这个。可见=真;this.globleDown=false;this.setEnd(毒物,玩具);}setEnd:function(tox,toy){this.tox=tox;这个.toy=玩具;varyc=this.toy-this.y;varxc=this.tox-this.x;},x,y是粒子的位置,vx是粒子的水平速度,vy是粒子的垂直速度,知道不知道nexttox无所谓,只是暂时保存这个变量。tox和toy是粒子的目标位置。首先,给所有的粒子一个目的地,这个目的地后面会讲到。即粒子应该到达的地方,然后定义一个变量za作为加速度。如果取值具体,可以自己测试得到一个大概的参数。我设置为20,感觉差不多。za是粒子和目的地之间的连接线的加速度。因此,我们可以通过简单的三角函数,通过粒子的位置和目的地的位置,计算出粒子的水平加速度和垂直加速度。这段varax=za*(xc/this.jl),ay=za*(yc/this.jl),有了水平加速度和垂直加速度,下一步就更简单了,直接计算水平速度和垂直的增量velocity,从而改变水平速度和垂直速度的值vx=(this.vx+ax*time)*0.97,vy=(this.vy+ay*time)*0.97;之所以乘以0.97是为了模拟能量损失,粒子会减速。time是每帧的时间差,计算速度后,只需更新粒子位置。this.x+=this.vx*时间;this.y+=this.vy*时间;因为粒子与目的地的连接方向在飞行过程中不断变化,所以每一帧都要重新计算粒子的水平和垂直加速度。运动的原理是这样的,是不是很简单?说完运动原理,再来说说上面动画的具体实现:动画初始化,在离屏画布上绘制需要的文字或图片,然后通过getImageData方法获取离屏画布的像素点.然后用循环找出离屏画布中的绘制区域,因为imageData中的数据值是一个rgba数组,所以我们判断最后一个值,即透明度大于128,就是绘制区域.然后得到这个区域的xy值。为了防止粒子对象过多导致页面卡住,我们限制了粒子的数量。取像素时,x值和y值每次增加2,从而减少粒子数。this.osCanvas=document.createElement("canvas");varosCtx=this.osCanvas.getContext("2d");this.osCanvas.width=1000;this.osCanvas.height=150;osCtx.textAlign="中心";osCtx.textBaseline="中间";osCtx.font="70px微软雅黑,黑体bold";osCtx.fillStyle="#1D181F"osCtx.fillText("WelCome",this.osCanvas.width/2,this.osCanvas.height/2-40);osCtx.fillText("TowAxes'HOME",this.osCanvas.width/2,this.osCanvas.height/2+40);varbigImageData=osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height);点=[];for(varx=0;x128){vardot=newDot(Math.random()>0.5?Math.random()*20+10:Math.random()*20+canvas.width-40,-Math.random()*canvas.height*2,0,0,x+(canvas.width/2-this.osCanvas.width/2),y+(canvas.height/2-this.osCanvas.height/2),"rgba(";+bigImageData.data[i]+","+bigImageData.data[i+1]+","+bigImageData.data[i+2]+",1)");dot.setEnd(canvas.width/2,canvas.height/2)dots.push(点);}}}通过循环得到粒子位置的xy值后,将位置赋值给粒子,成为粒子的目的地然后开始动画,然后就可以做文字图片粒子效果了。#p#下面贴出动画实现的js代码。如果你对其他代码也感兴趣,可以直接看控制台,没有压缩。varpart_1=(函数(w){vardots=[],DOT_SIZE=2,cube=null;varDot=function(x,y,vx,vy,tox,toy,color){this.x=x;this.y=y;this.vx=vx;this.vy=vy;this.nextox=tox;this.nextoy=toy;this.color=color;this.visible=true;this.globleDown=false;this.setEnd(tox,玩具);}Dot.prototype={paint:function(){ctx.fillStyle=this.color;ctx.fillRect(this.x-DOT_SIZE/2,this.y-DOT_SIZE/2,DOT_SIZE,DOT_SIZE);},setEnd:function(tox,toy){this.tox=tox;this.toy=toy;varyc=this.toy-this.y;varxc=this.tox-this.x;//this.initjl=Math.sqrt(xc*xc+yc*yc);},update:function(time){this.x+=this.vx*time;this.y+=this.vy*time;if(!this.globleDown&&this.y>0){varyc=this.toy-this.y;varxc=this.tox-this.x;this.jl=Math.sqrt(xc*xc+yc*yc);varza=20;varax=za*(xc/this.jl),ay=za*(yc/this.jl),vx=(this.vx+ax*time)*0.97,vy=(this.vy+ay*time)*0.97;this.vx=vx;this.vy=vy;//if(Math.abs(this.vx)<1&&Math.abs(this.vy)<1){//this.y=this.toy//this.x=this.tox//}}别的{变重力=9.8;varvy=this.vy+重力*时间;if(this.y>canvas.height){vy=-vy*0.7;}这个.vy=vy;}},loop:function(time){this.update(time);这个。油漆();}}varanimate=function(){this.state="before"}varap=animate.prototype;ap.init=function(){this.osCanvas=document.createElement("画布");varosCtx=this.osCanvas.getContext("2d");this.osCanvas.width=1000;this.osCanvas.height=150;osCtx.textAlign="中心";osCtx.textBaseline="中间";osCtx.font="70px微软雅黑,黑体bold";osCtx.fillStyle="#1D181F"osCtx.fillText("WelCome",this.osCanvas.width/2,this.osCanvas.height/2-40);osCtx.fillText("TowAxes'HOME",this.osCanvas.width/2,this.osCanvas.height/2+40);varbigImageData=osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height);点=[];for(varx=0;x128){vardot=newDot(Math.random()>0.5?Math.random()*20+10:Math.random()*20+canvas.width-40,-Math.random()*canvas.height*2,0,0,x+(canvas.width/2-this.osCanvas.width/2),y+(canvas.height/2-this.osCanvas.height/2),"rgba("+bigImageData.data[i]+","+bigImageData.data[i+1]+","+bigImageData.data[i+2]+",1)");dot.setEnd(canvas.width/2,canvas.height/2)点.推(点);}}}console.log(dots.length)}ap.changeState=function(){varosCtx=this.osCanvas.getContext("2d");osCtx.clearRect(0,0,this.osCanvas.width,this.osCanvas.height);this.osCanvas.width=460;this.osCanvas.height=100;osCtx.fillStyle="#5C5656"osCtx.fillRect(20,20,60,60)drawLogo(this.osCanvas,osCtx);varbigImageData=osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height);变量索引=0;dots.sort(function(a,b){returnMath.random()-Math.random();})for(varx=0;x128){vard=dots[index];if(d){d.setEnd(x+(canvas.width/2-300),y+50)d.color="rgba("+bigImageData.data[i]+","+bigImageData.data[i+1]+","+bigImageData.data[i+2]+",1)";index++}}}}setTimeout(function(){varendindex=index;for(vari=0;i=5*dots.length/6){if(this.state==="before"){this.state="first";dots.forEach(function(dot){dot.setEnd(dot.nextox,dot.nextoy);});}else{this.state="second";这个.changeState();}}}elseif(this.state==="second"){varcompleteNum=0,allnum=0;dots.forEach(function(dot){if(dot.visible)dot.loop(time);if(dot.globleDown){allnum++;if(Math.abs(dot.y-canvas.height)<2){completeNum++}}});if(completeNum===allnum&&allnum!==0){this.state="third";部分_2.动画();结束状态();}}elseif(this.state==="third"){cube.update();drawLogo(画布,ctx);}}returnnewanimate();})(window)原链接:https://img.ydisp.cn/news/20220914/ap40t2fsbq4.html