Canvas實(shí)現(xiàn)文字粒子效果

最終實(shí)現(xiàn)效果

文字粒子

實(shí)現(xiàn)思路:

獲取到canvas繪制后屏幕上像素點(diǎn)的數(shù)組渗钉,在目標(biāo)像素點(diǎn)上繪制粒子替換掉原來的內(nèi)容

  • 繪制文字
  • 通過API獲取畫布的二進(jìn)制數(shù)組
  • 設(shè)置粒子的填充步長
  • 添加粒子
  • 循環(huán)的遍歷粒子,更新粒子的狀態(tài)

代碼實(shí)現(xiàn)

繪制文字

   context.textAlign = "center";
   context.font = this.size + "px arial";
   context.fillText(this.text, this.x, this.y);

獲取二進(jìn)制數(shù)組

   let idata = context.getImageData(0, 0, canvas.width, canvas.height); // 獲取 canvas指定范圍內(nèi)的 像素?cái)?shù)組
   let buffer32 = new Uint32Array(idata.data.buffer); // 轉(zhuǎn)成32位的數(shù)組

這里使用的getImageData()方法是獲取畫布內(nèi)所有的像素點(diǎn)的二進(jìn)制表示冗酿,在JS中使用Uint32Array來接收丸卷,已數(shù)組形式展現(xiàn),沒有渲染的地方數(shù)組值是0弟翘,有渲染的地方為一個(gè)非0的數(shù)字

填充粒子

// 遍歷所有的數(shù)組 
for (var j = 0; j < canvas.height; j += gridY) {//步長
  for (var i = 0; i < canvas.width; i += gridX) {//步長
      if (buffer32[j * canvas.width + i]) {
            // 放入粒子對象
            var ball = new Particle(i, j);
            this.placement.push(ball);
      }
    }
 }

這里的意思是在二進(jìn)制數(shù)組中某一個(gè)范圍內(nèi)的粒子的密度箩做,其中步長越小越密集

更新粒子狀態(tài)

(function drawFrame() {
    window.requestAnimationFrame(drawFrame);
    context.clearRect(0, 0, canvas.width, canvas.height);

    for (var i = 0; i < word.placement.length; i++) {
        //調(diào)用particle對像的drawParticle方法莽红,開始畫布上畫
        word.placement[i].drawParticle();
    }
}())
            this.drawParticle = function () {
                // 當(dāng)前粒子變小到一定程度之后,每次將它的半徑+0.1邦邦,使其慢慢變大
                if (this.radius < this.futurRadius && this.dying === false) {
                    this.radius += durVal;
                } else { //粒子已經(jīng)到達(dá)最大狀態(tài)
                    this.dying = true; //表示粒子還處于show狀態(tài)
                }

                //每次-0.1
                if (this.dying) {
                    this.radius -= durVal;
                }
                // 畫粒子形狀
                context.save();
                context.fillStyle = this.color;
                context.beginPath();
                context.fillRect(this.x, this.y, this.futurRadius, this.futurRadius)
                context.closePath();
                context.fill();
                context.restore();

                //將消失的粒子重置最初的狀態(tài)
                if (this.y < 0 || this.radius < 1) {
                    this.x = this.base[0];
                    this.y = this.base[1];
                    this.dying = false;
                    this.futurRadius = randomInt(1.1, 5.1);
                }
            }

完整代碼

<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
    <canvas id="dir" width="800" height="800" style="border:1px solid #ccc">
    </canvas>

    <script>
        var canvas = document.getElementById("dir");
        var context = canvas.getContext("2d");

        var gridY = 10,
            gridX = 10,
            colors = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5',
                '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4CAF50',
                '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800',
                '#FF5722'
            ],
            durVal = 0.1;


        // 粒子
        function Particle(x, y) {
            this.x = x;
            this.y = y;
            this.color = colors[Math.floor(Math.random() * colors.length)]; //'bleack'//
            this.futurRadius = randomInt(1.1, 5.1);
            this.radius = 1.1;
            this.dying = false;
            this.base = [x, y];

            this.drawParticle = function () {

                // 當(dāng)前粒子變小到一定程度之后安吁,每次將它的半徑+0.1,使其慢慢變大
                if (this.radius < this.futurRadius && this.dying === false) {
                    this.radius += durVal;
                } else { //粒子已經(jīng)到達(dá)最大狀態(tài)
                    this.dying = true; //表示粒子還處于show狀態(tài)
                }

                //每次-0.1
                if (this.dying) {
                    this.radius -= durVal;
                }
                // 畫粒子形狀
                context.save();
                context.fillStyle = this.color;
                context.beginPath();
                context.fillRect(this.x, this.y, this.futurRadius, this.futurRadius)
                context.closePath();
                context.fill();
                context.restore();

                //將消失的粒子重置最初的狀態(tài)
                if (this.y < 0 || this.radius < 1) {
                    this.x = this.base[0];
                    this.y = this.base[1];
                    this.dying = false;
                    this.futurRadius = randomInt(1.1, 5.1);
                }
            }
        }

        function Shape(x, y, texte) {
            this.x = x;
            this.y = y;
            this.size = 200;
            this.text = texte;
            this.placement = [];
        }


        Shape.prototype.getValue = function () {
            context.textAlign = "center";
            context.font = this.size + "px arial";
            context.fillText(this.text, this.x, this.y);

            let idata = context.getImageData(0, 0, canvas.width, canvas.height); // 獲取 canvas指定范圍內(nèi)的 像素?cái)?shù)組
            let buffer32 = new Uint32Array(idata.data.buffer); // 轉(zhuǎn)成32位的數(shù)組

            // 遍歷所有的數(shù)組 
            for (var j = 0; j < canvas.height; j += gridY) {
                for (var i = 0; i < canvas.width; i += gridX) {
                    if (buffer32[j * canvas.width + i]) {
                        // 放入粒子對象
                        var ball = new Particle(i, j);
                        this.placement.push(ball);
                    }
                }
            }

            context.clearRect(0, 0, canvas.width, canvas.height);
        }

        function randomInt(min, max) {
            return min + Math.random() * (max - min + 1);
        }

        var word = new Shape(canvas.width / 2, canvas.height / 2, '文字粒子')
        word.getValue

        (function drawFrame() {
            window.requestAnimationFrame(drawFrame);
            context.clearRect(0, 0, canvas.width, canvas.height);

            for (var i = 0; i < word.placement.length; i++) {
                //調(diào)用particle對像的drawParticle方法燃辖,開始畫布上畫
                word.placement[i].drawParticle();
            }

        }())
    </script>
</body>

</html>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鬼店,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子黔龟,更是在濱河造成了極大的恐慌薪韩,老刑警劉巖确沸,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異俘陷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)观谦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門拉盾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人豁状,你說我怎么就攤上這事捉偏。” “怎么了泻红?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵夭禽,是天一觀的道長。 經(jīng)常有香客問我谊路,道長讹躯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任缠劝,我火速辦了婚禮潮梯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惨恭。我一直安慰自己秉馏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布脱羡。 她就那樣靜靜地躺著萝究,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锉罐。 梳的紋絲不亂的頭發(fā)上帆竹,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機(jī)與錄音氓鄙,去河邊找鬼馆揉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛抖拦,可吹牛的內(nèi)容都是我干的升酣。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼态罪,長吁一口氣:“原來是場噩夢啊……” “哼噩茄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起复颈,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤绩聘,失蹤者是張志新(化名)和其女友劉穎沥割,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凿菩,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡机杜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衅谷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椒拗。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖获黔,靈堂內(nèi)的尸體忽然破棺而出蚀苛,到底是詐尸還是另有隱情,我是刑警寧澤玷氏,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布堵未,位于F島的核電站,受9級特大地震影響盏触,放射性物質(zhì)發(fā)生泄漏渗蟹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一耻陕、第九天 我趴在偏房一處隱蔽的房頂上張望拙徽。 院中可真熱鬧,春花似錦诗宣、人聲如沸膘怕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岛心。三九已至,卻和暖如春篮灼,著一層夾襖步出監(jiān)牢的瞬間忘古,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工诅诱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留髓堪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓娘荡,卻偏偏與公主長得像干旁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子炮沐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容