話不多說直接上代碼
注意:背景圖路徑是picture/star.jpg,自己在同級目錄先創鍵picture目錄再下載一張圖片命名為star.jpg
HTML:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Fireworks Animation</title><link rel="stylesheet" href="style.css" /></head><body><canvas id="fireworksCanvas"></canvas><script src="script.js"></script></body>
</html>
JS:
// 獲取canvas元素const canvas = document.getElementById('fireworksCanvas');const ctx = canvas.getContext('2d');// 設置canvas寬度和高度為窗口寬度和高度canvas.width = window.innerWidth;canvas.height = window.innerHeight;let fireworks = [];// 創建煙花類class Firework {constructor() {this.x = Math.random() * canvas.width; // 隨機生成煙花的起始x坐標this.y = canvas.height; // 煙花起始y坐標為畫布底部this.radius = 2; // 煙花半徑this.speed = 7; // 煙花上升速度this.color = 'white'; // 煙花顏色this.exploded = false; // 煙花是否已經爆炸this.particles = []; // 煙花爆炸后的粒子數組this.explosionHeight = Math.random() * (canvas.height * 0.4) + (canvas.height * 0.1); // 生成隨機的爆炸高度this.initialAlpha = 1; // 初始透明度this.currentAlpha = this.initialAlpha; // 當前透明度}update() {if (!this.exploded) {this.y -= this.speed; // 煙花向上運動// 逐漸減少煙花的透明度this.currentAlpha -= 0.005;if (this.currentAlpha < 0) {this.currentAlpha = 0;}if (this.y <= this.explosionHeight) {this.explode();}} else {this.particles.forEach((particle, index) => {particle.update(); // 更新粒子的運動狀態if (particle.alpha <= 0) {this.particles.splice(index, 1);}});}}draw() {ctx.beginPath(); // 開始繪制路徑ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); // 繪制一個以(x, y)為中心,半徑為radius的圓ctx.fillStyle = this.color; // 設置填充顏色為煙花的顏色ctx.globalAlpha = this.currentAlpha; // 使用當前透明度ctx.fill(); // 填充圓ctx.closePath(); // 結束繪制路徑if (this.exploded) {this.particles.forEach(particle => {particle.draw(); // 繪制每個粒子});}}explode() {this.exploded = true; // 設置煙花為已經爆炸狀態for (let i = 0; i < 100; i++) {let particle = new Particle(this.x, this.y); // 創建一個新的粒子,位置為煙花的位置this.particles.push(particle); // 將新創建的粒子添加到煙花的粒子數組中}}}// 創建粒子類class Particle {constructor(x, y) { // 粒子類的構造函數,接收x和y坐標作為參數this.x = x; // 設置粒子的x坐標this.y = y; // 設置粒子的y坐標this.radius = 2; // 設置粒子的半徑this.speedX = Math.random() * 5 - 2; // 隨機生成粒子在x軸上的速度this.speedY = Math.random() * 5 - 2; // 隨機生成粒子在y軸上的速度this.color = `hsl(${Math.random() * 360}, 100%, 50%)`; // 隨機生成粒子的顏色this.alpha = 1.2; // 設置粒子的透明度為1.2this.fade = Math.random() * 0.02 + 0.01; // 隨機生成粒子透明度的減少速度}update() { // 更新粒子的位置和透明度this.x += this.speedX; // 更新粒子的x坐標this.y += this.speedY; // 更新粒子的y坐標this.alpha -= this.fade; // 減少粒子的透明度}draw() { // 繪制粒子ctx.beginPath(); // 開始繪制路徑ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); // 繪制一個以(x, y)為中心,半徑為radius的圓ctx.fillStyle = this.color; // 設置填充顏色為粒子的顏色ctx.globalAlpha = this.alpha; // 設置全局透明度為粒子的透明度ctx.fill(); // 填充圓ctx.closePath(); // 結束繪制路徑}}function animate() { // 動畫函數,更新畫布內容并繪制煙花和粒子ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // 設置畫布背景顏色及透明度ctx.fillRect(0, 0, canvas.width, canvas.height); // 填充矩形覆蓋畫布fireworks.forEach((firework, index) => { // 遍歷煙花數組firework.update(); // 更新煙花的位置和狀態firework.draw(); // 繪制煙花及其粒子if (firework.exploded && firework.particles.length === 0) { // 如果煙花已經爆炸且沒有粒子了fireworks.splice(index, 1); // 從煙花數組中移除該煙花}});requestAnimationFrame(animate); // 遞歸調用自身,實現連續動畫效果}function init() { // 初始化函數setInterval(() => { // 每隔2秒執行一次let firework = new Firework(); // 創建一個新的煙花對象fireworks.push(firework); // 將新創建的煙花對象添加到煙花數組中}, 100);//每次循環的時間不能太長animate(); // 調用動畫函數開始動畫}init();
CSS:
body {margin: 0;padding: 0;overflow: hidden;background: url('picture/star.jpg') no-repeat center center fixed;background-size: cover;
}
canvas {display: block;margin: auto;position: absolute;top: 0;left: 0;right: 0;bottom: 0;opacity: 0.5; /* 設置畫布的透明度為0.5 */
}