HTML5中的canvas真是个很强大的东西呢!
这几天突发奇想想做一个气泡上升的动画,经过许久的思考和多次失败,终于做出了如下效果
由于是录制的gif图,看着会有点卡顿,实际演示是很自然的
想要做出这种效果需要用到大量的随机数
先上代码:
CSS+HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ margin: 0; padding: 0; } #canvas1{ display: block; position: absolute; bottom: 0; transition: all 0.2s ease; } </style> </head> <body> <canvas id="canvas1">您的浏览器不支持canvas</canvas> <script src="qipao.js"></script> </body> </html>
JS
let canvas1 = document.getElementById('canvas1'); let context1 = canvas1.getContext('2d'); let canvasH = 300; function resizeCanvas() { if (window.innerHeight > 1920) { canvas1.width = window.innerWidth; } else { canvas1.width = 1920; } canvas1.height = canvasH; }//设置canvas宽高 resizeCanvas(canvas1); let num = 100;//气泡数量 let ballX = [];//球心的横坐标 let ballY = [];//球心的纵坐标 let ballR = [];//球的半径 let ballF = [];//小球左右摆动幅度 let speed = [];//小球向上移动速度 let colours = ["rgb(91,155,213)","rgb(180,199,231)","rgb(0,0,255)","rgb(46,177,182)","rgb(68,114,196)"];//小球颜色 let finalCol=[]; //在随机位置产生num个随机半径的球,储存变量 for(let i = 0;i < num; i++) { let radius = Math.floor(Math.random() * 15 + 10); let x = Math.floor(Math.random() * canvas1.offsetWidth); let y = Math.floor(Math.random() * 300); let fudu = Math.floor(Math.random() * 10 + 5); let sp = Math.floor(Math.random() * 30 + 5); let color = colours[Math.floor(Math.random() * colours.length)]; ballX.push(x); ballY.push(y); ballR.push(radius); ballF.push(fudu); speed.push(sp); finalCol.push(color); } let reX; let reY; let ballK=[]; //使小球移动(向上做曲线运动) function move(){ context1.clearRect(0, 0, canvas1.offsetWidth, 300); for(let i = 0;i < num; i++) { (function (i) { if(ballK[i] == null){ ballK[i] = 0; } reX = ballK[i] * speed[i] + ballY[i]; reY = Math.sin(ballK[i]) * ballF[i] + ballX[i]; if(reX + ballR[i] <= 0){ ballY[i] = 320; ballK[i] = 0; reX = ballK[i] * speed[i] + ballY[i]; } context1.beginPath(); context1.fillStyle = finalCol[i]; context1.globalAlpha = 0.5; context1.arc(reY, reX, ballR[i], 0, Math.PI * 2); context1.fill(); ballK.splice(i,1,ballK[i]); ballK[i]-=0.1; })(i); } } setInterval(move,20);//定时器
整体思路:
首先定义几个数组,一个是装横坐标,一个装纵坐标,一个装半径,一个装圆的颜色
绘制若干个圆,圆心的横坐标、纵坐标、半径全部采用随机数的形式得到
用fill()方法填充圆,fillStyle()方法指定颜色,颜色也全部用随机数得到
用golbalAlpha设置透明度
这样每个圆都有了自己的初始位置,颜色,和透明度
然后开始绘制每个球的运动路线
绘制路线这里我用了sin函数,通过该变角度,振幅等来改变路线,因此又要定义两个数组,一个装振幅,另外一个装圆移动的速度,这两个变量也用随机数的形式得到
因为sin函数的轨迹总体是水平方向上的运动,因此如果想实现从下往上,就要把横坐标与纵坐标颠倒过来
当圆从下往上运动时,如果圆已经移出了canvas的范围也就是圆心的纵坐标-半径<=0,那么改变圆的坐标,这样就可以循环从下往上运动了
设置定时器,每过20毫秒,使用clearRect清除先前的圆的位置,并在新的位置上绘制圆
说了这么多,个人认为这个动画的核心是储存变量。
来源:https://www.cnblogs.com/FrankLongger/p/9359271.html