粒子特效
效果:
先圖
為了實現粒子在運動軌跡上所留下的尾巴效果,在網上看見有一位網友是在上一幀的基礎之上,加上了一層半透明蒙層。也就是rgba(0,0,0,.1)。
下面開始實現拖尾的效果:
(1)需求分析:
1.粒子的生成 (繪制)
2.粒子的移動
3.粒子的拖尾完成
(2)代碼實現
1.Dot類的實現,為了生成一個點,我簡易封裝了dot
Dot Class
class Dot { constructor(canvas, context, r = 4) { this.canvas = canvas //canvas 標簽 this.ctx = context //canavs.getContext() this.x = this.canvas.width * Math.random() //點的坐標 this.y = this.canvas.width * Math.random() this.xa = (2 * Math.random() - 1) * 2 //點在每一帖在橫向方向的距離跨度 this.ya = (2 * Math.random() - 1) * 2 //點在每一幀在縱向方向上跨度 this.r = r } draw() { //繪制一個Dot 返回一個Dot的實例,就是本身this的指向當前的Dot this.ctx.beginPath() let grap = this.ctx.createRadialGradient(this.x, this.y, 0, this.x + this.r, this.y + this.r, 10) grap.addColorStop(0, "rgb(193,255,255)") grap.addColorStop(1, 'rgb(1,1,1)') this.ctx.fillStyle = grap this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI) this.ctx.fill() this.ctx.closePath() return this //返回自身 } }
在Dot的原型中,有一個draw的方法是用於繪制一個點,調用時,可以這樣,假設dot為實例 那么調用就是 dot.draw().move() move方法是用於dot的移動
move函數
move() { this.x += this.xa //每繪制一個dot之后,就會更新dot的坐標和速度 this.y += this.ya this.xa *= (this.x < 0 || this.x > this.canvas.width) ? -1 : 1 //碰壁了就會反彈 this.ya *= (this.y < 0 || this.y > this.canvas.height) ? -1 : 1 }
好了Dot類就基本完成了,下面是完成畫布的封裝CanvasDot
class DotCanvas { constructor(id, num = 300) { this.canvas = document.getElementById(id); // 我這里是在通過DOM操作獲得canvas畫布,需要自己在html自己加入canvas標簽 this.ctx = this.canvas.getContext('2d') this.dots = null this.dotnum = num //dot的數量 ,默認是300 this.initDot().render() //initDot 是dot的初始化,而render是畫布的渲染 } initDot() { //初始化dot集 this.dots = Array.from(Array(this.dotnum)).map((item, index, arr) => { return new Dot(this.canvas, this.ctx) }) return this } render() { this.dots.forEach((item) => { item ? item.draw().move() : null })//遍歷所有的dot 並繪制移動
//下面是重點,在繪制完dot后,為了完成拖尾的效果,所以需要我們去加上一層 this.ctx.fillStyle = 'rgb(0,0,0,.07)' //加上填充的顏色 this.ctx.rect(0, 0, this.canvas.width, this.canvas.height) //繪制的區域是整個canvas this.ctx.fill() //填充 window.requestAnimationFrame(this.render.bind(this)) //requestAnimationFrame實現每秒60幀,為啥在this.render之后加上個bind方法呢》
//實際在render中,有使用this的方法,且this的指向明確是CanvasDot的實例,而在回調函數中,往往this的Binding就變得尤為的不同,如在setTimeout()中的回調函數就是
//綁定在window上,因為setTimeout就是在window下的函數,而requestAnimationnFrame同樣也是。
} }
最后來總結一下,學習的經驗。
(1)實現拖尾,可以在繪制完點之后,加上一層半透明蒙層,在視覺上讓人覺得是有拖尾,注:這里沒有使用clearReact()方法清楚畫布,而是加上一層,讓原先點所在位置的那個點變得模糊,從而使用拖尾。
(2)關於回調函數的this綁定而言,可以通過bind方法將this顯示綁定,或者也可以用箭頭函數實現綁定父級this,在ES6中箭頭函數的this綁定,是綁定父級的this.
如function add(x,y){
console.log(this)
()=>(console.log(this))}這兩個this會是一樣的,將箭頭函數放在回調函數的位置上也是一樣的
以上就是今天想分享的學習心得
上面為希望最終可以實現的效果 flaging!!!!!!!!!!!!!!