demo 地址:
https://lyf521.github.io/docs/blog/animation/meteorshower.html
要点一: canvas平面动画需要不断重复计算x,y的坐标位置
// 设定坐标类class Crood {// 创建类的属性、默认值constructor(x=0,y=0){this.x = xthis.y = y}// 重新设置值setCrood (x,y){this.x = xthis.y = y}// 复制当前坐标copy (){return new Crood(this.x, this.y)}}
要点二: 将数组中某个数据移除
remove(star){this.stars = this.stars.filter((s) => {return s !== star})}
要点三:requestAnimationFrame
requestAnimationFrame()的原理其实与setTimeout和setInterval类似,通过递归调用同一方法来不断更新画面以达到动画效果,但它优于setTimeout和setInterval的地方在于它是由浏览器专门为动画提供优化实现的API,并且充分利用显示器的刷新机制,比较节省系统资源。显示器有固定的刷新频率(60Hz或75Hz),也就是说,每秒最多只能重绘60次或75次,requestAnimationFrame的基本思想就是与这个刷新频率保持同步,利用这个刷新频率进行页面重绘。此外,使用这个API,一旦页面不处于浏览器的当前标签,就会自动停止刷新。这就节省了CPU、GPU和电力
不过有一点需要注意,requestAnimationFrame是在主线程上完成。这意味着,如果主线程非常繁忙,requestAnimationFrame的动画效果会大打折扣。
// 采用requestAnimationFrame() 帧动画tick(){if (this.playing) returnthis.playing = truelet now = (new Date()).getTime()let last = nowlet delta // 帧时间// 兼容性if (!window.requestAnimationFrame){window.requestAnimationFrame = (window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.pRequestAnimationFrame || function(callback){return setTimeout(callback,Math.floor(1000/60))})}// 帧执行 函数let _tick = () => {if (this.stop && this.stars.length === 0){cancelAnimationFrame(this.T)this,playing = falsereturn}// 获取帧时间,30到16之间delta = now - lastdelta = delta > 500 ? 30 : (delta < 16 ? 16 : delta)last = nowthis.T = window.requestAnimationFrame(_tick)ctx.save()ctx.fillStyle = 'rgba(0,0,0,0.2)' // 每一帧用 半透明 覆盖一次画布ctx.restore()this.updata(delta)}}
要点四: 同时画20个流星
updata(delta){if (!this.stop && this.stars.length < 20) {this.stars.push(this.createStar())}this.stars.forEach((star) => {star.draw(this.ctx,delta)})}
