Canvas 放煙花合集 -- 用粉絲頭像做成煙花綻放?

小丞同學發表於2021-11-06

?“我對著煙花許願,希望你永遠在我身邊

? “湊不夠滿天星辰那就去看看煙花吧,人間煙火氣,最撫凡人心

?小tips:喜歡的可以關注博主私信程式碼噢~

也可以看看前面兩篇煙花噢
歡迎訪問博主的個人網站:一口奶蓋

? 邀你看一場浪漫的煙火 -- canvas放煙花

gif4
? 你還在用canvas畫愛心嗎?看我讓你的名字在星空綻放

name

本文實現效果

圖片

今天要實現的效果是將圖片做成煙花綻放,非常感謝大家的支援~

實現效果

這個小demo實現的方法和文字煙花實現的方法大致是相同的~

1. 將圖片繪製在畫布上

首先我們需要將需要製作成煙花的圖片繪製在畫布上

特別注意

  1. 由於這種圖片是用來取色用的底圖所以我們並不希望這張圖片被使用者看到,因此我們可以將這張圖片渲染在新的畫布上,煙花渲染在不同的畫布上,這樣上面畫布就可以蓋住下面的畫布,這張底圖也不會被看見
  2. 由於圖片的載入需要一定的時間,所以我們對圖片操作的程式碼需要寫在回撥函式裡面,不然圖片可能會未載入而報錯
let img1 = new Image();
//隨機取一張圖片
img1.src = Math.floor(Math.random()*9 +1) + '.jpg'
// 等待圖片載入完畢後繪製圖片
img1.onload = function () {
    let imgWidth = 400
    let imgHeight = 400
    inCtx.drawImage(img1, 0, 0, imgWidth, imgHeight)
}

2. 獲取畫素點資訊

這一步的目的是獲取到圖片每個畫素的顏色,這樣我們就可以通過這些畫素點合成一張圖片,也可以排除掉一些畫素點,篩出想要的圖形

let imgData = inCtx.getImageData(0, 0, imgWidth, imgHeight)

在前面的程式碼中我們在 (0,0) 的位置繪製了圖片,我們通過getImageData將這塊區域的畫素資訊取出來,返回結果是包含畫素點資訊的物件,類似於下圖,詳細可看上篇文章

物件

3. 給煙花粒子新增屬性

我們需要實現的煙花效果由許許多多的煙花粒子組成,每個粒子都有它自己的顏色和它的運動軌跡,實現圖片煙花的關鍵就在於它的顏色需要正確,我們可以通過遍歷畫素點資訊imageData物件,將該畫素點的顏色作為煙花粒子顏色儲存起來,也就是將圖片一點點複製的過程

for (let h = 0; h < imgHeight; h += 8) {
    for (let w = 0; w < imgWidth; w += 8) {
        let position = (imgWidth * h + w) * 4;
        // 返回的陣列是rgba的方式儲存
        let r = imgData.data[position],
            g = imgData.data[position + 1],
            b = imgData.data[position + 2],
            a = imgData.data[position + 3];
        if (r + g + b == 0) {
            continue
        }
        let firework = {};
        firework.x = x;
        firework.y = y;
        firework.fx = x + w - imgWidth / 2;
        firework.fy = y + h - imgHeight / 2;
        firework.size = 1; // Math.floor(Math.random() * 2) + 1
        firework.speed = 5;
        firework.alpha = 1;
        firework.r = r
        firework.g = g
        firework.b = b
        firework.color = "rgba(" + r + "," + g + "," + b + "," + a + ")"
        fireworks.push(firework)
    }
}

在遍歷的過程中因為我們需要實現粒子的效果,因此需要隔幾個畫素點在取一個,這樣繪製出來影像就是粒子狀的,我們將煙花粒子渲染即可

image-20210623212834848

4. 渲染煙花粒子

渲染的方法就是在粒子該在的位置上畫個小圓就可!顏色,位置,半徑等資訊利用先前給粒子新增的屬性,特別需要顏色的書寫格式噢~

ctx.beginPath();
ctx.arc(firework.x, firework.y, firework.size, Math.PI * 2, false);
// 結束
ctx.closePath();
ctx.fillStyle = "rgba(" + firework.r + "," + firework.g + "," + firework.b + "," + firework.alpha + ")"
ctx.fill();

5. 實現煙花粒子動畫

我們需要在每次渲染時將煙花粒子當前的位置向下偏移,透明度降低實現煙花降落殆盡的效果,當透明度將低於0時移出粒子

firework.x += (firework.fx - firework.x) / 10;
firework.y += (firework.fy - firework.y) / 10 -(firework.alpha - 1.8)*firework.speed;
firework.alpha -= 0.02;
// 如果透明度小於0就刪除這個粒子
if (firework.alpha <= 0) {
    fireworks.splice(i, 1);
    // 跳過這次迴圈,不進行繪製
    continue;
}

6. 實現拖尾效果

為了讓煙花更加的真實,我們需要給煙花粒子新增拖尾的效果,在每一次重新渲染之前給新建一個蒙層從而實現拖尾的效果

ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = 'rgba(0,0,0,' + 10 / 100 + ')';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'lighter';

煙花合集

邀你看一場浪漫的煙火 -- canvas放煙花

還在用canvas畫格子嗎?文字煙花效果更不錯噢

這兩篇文章都是實現不同的煙花效果噢,大家可以一起學習一下噢!需要原始碼可以關注私信博主噢~


煙花的幾篇文章就到這裡了,期待博主的下個專題吧~

一起學習,共同進步!

相關文章