laxexue 2019-11-04
最近在实现一些动效较多的可视化页面,需要一个气泡生成的动画,就写了这段代码。
首先需要传入一个canvas dom,获取其宽高,初始化声明一个特定长度的气泡数组(长度可由外部传入),每个气泡有半径,速度,初始化所在位置等属性。
然后需要执行绘制方法,每次绘制前调用clearRect()清空画布,然后window.requestAnimationFrame()循环调用绘制方法。
绘制气泡初始化时,可以让位置随机,也可以全在底部生成.每次气泡的高度位置变化,当到达画布顶部时,重新从底部出现。
class BubbleAnimate { constructor(canvas, number=20,radius=6,color=[255,255,255],speed=0.2,speedRandomPercent=0.5,startFull=true) { try{ this.canvas = canvas; }catch{ throw("please provide canvas dom"); return ; } this.ctx = canvas.getContext('2d'); this.width=canvas.width; this.height=canvas.height; this.radius=radius; this.color=color; this.speed=speed; this.bubbles = []; this.speedRandomPercent=speedRandomPercent; this.startFull=startFull; for(let i=0; i<number;i++) { this.bubbles.push({ isReborn:true, speed: speed+(Math.random()*2-1)*speedRandomPercent*speed, }); } this.renderCanvas(); }; renderCanvas() { this.ctx.clearRect(0,0,this.width,this.height); this.renderBubbles(); window.requestAnimationFrame(() => this.renderCanvas()); }; renderBubbles() { //气泡 let initPoint = [this.width/2,this.height]; for(let i = 0;i<this.bubbles.length;i++) { let bubble = this.bubbles[i]; if(bubble.isReborn) { let x = (Math.random()-0.5)*this.width*0.96 + initPoint[0]; //气泡半径在一定范围内随机生成 let bubbleRadius = this.radius+ Math.floor(Math.random()*2-1)*0.5; //判断气泡初始化时是否铺满 let y = this.startFull?this.height*Math.random():(initPoint[1] - bubbleRadius); bubble.radius = bubbleRadius; bubble.currentLocation = [x, y]; let opacity = 0.2 + 0.4* Math.random(); bubble.color = `rgba(${this.color[0]}, ${this.color[1]},${this.color[2]}, ${opacity})`; bubble.isReborn = false; }else { this.renderBubble(bubble); if(bubble.currentLocation[1]<= bubble.radius){ bubble.isReborn = true; }![图片描述][1] bubble.currentLocation[1] = bubble.currentLocation[1] -bubble.speed; } } } renderBubble(item) { this.ctx.beginPath(); this.ctx.arc(...item.currentLocation, item.radius, 0, 2*Math.PI); this.ctx.fillStyle = item.color; this.ctx.fill(); } }