Canvas實現特效(一):粒子拖尾


  粒子特效

  效果:   

      先圖

                         

      為了實現粒子在運動軌跡上所留下的尾巴效果,在網上看見有一位網友是在上一幀的基礎之上,加上了一層半透明蒙層。也就是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!!!!!!!!!!!!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM