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

本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!css

漫天的煙火送給遙遠的你

🎉我裁一段星河送給你,好叫你不遜色這漫天煙火html

漫天的煙火,在這璀璨的星空中閃耀,成就了這片星空的絢麗,更散發出了本身無限的光芒,今天就使用canvas來作一個煙花效果吧!✨前端

實現效果gif3

實現的效果仍是很不錯的,漫天的煙火肆意綻開html5

實現過程

1. 簡單的 Html 和 CSS

簡單的寫點基礎樣式,背景黑色,定義個canvas標籤web

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <style> * { margin: 0; padding: 0; } body { background-color: black; } canvas { position: absolute; z-index: 0; } </style>
</head>

<body>
    <canvas>您的瀏覽器不支持</canvas>
    <script src="index.js"></script>
</body>

</html>
複製代碼

2. 建立 canvas畫布

在js中先獲取標籤,設置畫布大小,採用resize監聽頁面的調整,及時的改變畫布的大小算法

// 元素獲取
const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d");
// 設定畫布大小
function resizeCanvas() {
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
}
resizeCanvas();
// 頁面縮放改變畫布大小
window.addEventListener("resize", resizeCanvas)
複製代碼

3. 獲取鼠標點擊位置

經過e.clientXe.clientY來獲取鼠標點擊的位置,用於在後面實如今鼠標點擊的位置,產生煙花canvas

function clickSite(e) {
    // 獲取當前鼠標的座標
    let x = e.clientX;
    let y = e.clientY;
    // 繪製
    addFires(x, y);
}
document.addEventListener('click', clickSite);
複製代碼

4. 實現鼠標點擊產生煙花的初級形態

咱們一步一步來實現,這是實現煙花效果的第一步,經過在點擊位置添加一個煙花雛形後端

,這是一個單純的靜態,在後面咱們慢慢的讓它動起來數組

function drawFires() {
    // 初始半徑,以及粒子數量
    let count = 10;
    let radius = 10;
    for (let i = 0; i < count; i++) {
        // 渲染出當前數據
        // 下面是點數學題
        // moveX,moveY是粒子開始的座標,畫個三角形,角度半徑知道很容易就得出方程
        let angle = 360 / count * i;
        let radians = angle * Math.PI / 180;
        let moveX = x + Math.cos(radians) * radius
        let moveY = y + Math.sin(radians) * radius
        // 開始路徑
        ctx.beginPath();
        ctx.arc(moveX, moveY, 2, Math.PI * 2, false);
        // 結束
        ctx.closePath();
        ctx.fillStyle = '#ff0000'
        ctx.fill();
    }
}
複製代碼

1

當前效果瀏覽器

5. 實現煙花散開

有了上面的鋪墊,每個小圓點都是即將要散開的煙花,那麼咱們只須要更新畫布讓它的半徑不斷的增大便可,實現散開的效果很簡單,那部分代碼就不貼了(節省篇幅),對於更新畫布,採用的一個html5中的新方法requestAnimationFrame官方文檔

它相比於使用定時器實現動畫有什麼優勢呢?

  1. 在隱藏或不可見的元素中,requestAnimationFrame將不會進行重繪或迴流,會減小對內存的使用
  2. requestAnimationFrame 會把每一幀中的全部DOM操做集中起來,在一次重繪或迴流中就完成

動畫實現代碼

// 渲染,更新粒子的信息
function tick() {
    // 更新畫布
    drawFires();
    requestAnimationFrame(tick);
}
tick()
複製代碼

gif1當前實現效果

6. 實現拖尾效果以及隨機顏色

從上面的效果圖能夠看出,爆炸的效果咱們已經能基本實現了,可是煙花不是一個個的小球,咱們須要添加拖尾的效果,而且給每一個小球隨機顏色,這樣會更加的炫麗

拖尾效果代碼

在繪製完一幀後,繪製下一幀以前,添加一個半透明的蒙層就能實現一個拖尾的效果

function tick() {
    // 設置拖影
    ctx.globalCompositeOperation = 'destination-out';
    ctx.fillStyle = 'rgba(0,0,0,' + 10 / 100 + ')';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.globalCompositeOperation = 'lighter';
    // 更新畫布
    drawFires();
    requestAnimationFrame(tick);
}
複製代碼

隨機顏色代碼

採用的是hsla函數來設定顏色,由於煙花的色彩都是接近的,因此咱們能夠經過調節色相值,來選擇煙花顏色。這裏採用的是固定飽和度爲100%,亮度顏色隨機在必定範圍內,使得顏色不會過於離譜

hsla() 函數使用色相、飽和度、亮度、透明度來定義顏色。

let hue = Math.random() * 360;
let hueVariance = 60;
function setColors(firework) {
    firework.hue = Math.floor(Math.random() * ((hue + hueVariance) - (hue - hueVariance))) + (hue - hueVariance);
    firework.brightness = Math.floor(Math.random() * 21) + 50;
    firework.alpha = (Math.floor(Math.random() * 60) + 40) / 100;
}
複製代碼

gif2

當前效果

7. 實現煙花重力下墜

從上面的效果圖,咱們能夠認識到咱們還差兩部,煙花的下墜以及煙花的消失

咱們經過從新調整煙花路徑的算法,來實現煙花的下墜,在初始的代碼中對於煙花的爆炸路徑,採用的是普通的直線運動,咱們須要在這個基礎上讓它的y方向加大一點,這樣就會實現了一個拋物線的效果,同時,對於煙花的爆炸應當還要有個殆盡的效果,咱們經過改變透明度來實現,對於透明度小於0的咱們將它從數組中移除

let moveX = Math.cos(firework.radians) * firework.radius;
let moveY = Math.sin(firework.radians) * firework.radius + 1;
firework.x += moveX;
firework.y += moveY;
// 更新數據,讓圓擴散開來
firework.radius *= 1 - firework.speed / 120
firework.alpha -= 0.01;
// 若是透明度小於0就刪除這個粒子
if (firework.alpha <= 0) {
    fireworks.splice(i, 1);
    // 跳過此次循環,不進行繪製
    continue;
}
複製代碼

改變了算法

每次畫布的更新都要讓透明度下降,同時每一個粒子的移動半徑不斷地減少,這樣會造成向中間合攏的趨勢,因爲每一個粒子都存放在數組當中,當粒子透明度小於0,從數組移除

8. 實現自動煙花效果

只須要經過定時器,不斷的添加煙花便可

setInterval(() => {
    // 能夠多調用幾回用來增長煙花的數量
    addFires(Math.random() * canvas.width, Math.random() * canvas.height)
    addFires(Math.random() * canvas.width, Math.random() * canvas.height)
}, 500)
複製代碼

自定義文字

能夠在頁面中加一些標籤,好比文字,實現的效果都是不錯的噢~ gif4 本次的煙花效果就到這裏了,喜歡的話就本身嘗試的作一個吧~~

相關文章
相關標籤/搜索