打造炫酷的動態閃爍發光粒子五角星效果
前言
在現代Web開發中,視覺效果的重要性不言而喻。今天我們將深入探討如何使用HTML5 Canvas和JavaScript創建一個令人驚艷的動態閃爍發光粒子五角星效果。這個項目不僅展示了Canvas的強大功能,還涉及了粒子系統、動畫循環、數學計算等多個技術要點。
項目概述
我們創建的效果包含以下特性:
- 🌟 自動旋轉的五角星
- ? 動態發光效果(呼吸燈效果)
- 🎆 粒子系統(從五角星邊緣發射粒子)
- 🎮 鼠標交互(靠近時產生更多粒子)
- 📱 響應式設計
技術架構
1. 基礎結構
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>動態閃爍發光粒子五角星</title><style>body {margin: 0;padding: 0;background: #000;overflow: hidden;display: flex;justify-content: center;align-items: center;height: 100vh;}canvas {border: 1px solid #333;}</style>
</head>
<body><canvas id="starCanvas"></canvas>
</body>
</html>
2. 核心類設計
Particle 類(粒子系統)
粒子類是整個效果的核心組件之一,負責創建和管理單個粒子的行為:
class Particle {constructor(x, y) {this.x = x; // 粒子位置this.y = y;this.vx = (Math.random() - 0.5) * 2; // 隨機速度this.vy = (Math.random() - 0.5) * 2;this.life = 1; // 生命值this.decay = Math.random() * 0.02 + 0.005; // 衰減速度this.size = Math.random() * 3 + 1; // 粒子大小this.color = { // 隨機顏色r: Math.random() * 100 + 155,g: Math.random() * 100 + 155,b: Math.random() * 100 + 155};}update() {this.x += this.vx; // 更新位置this.y += this.vy;this.life -= this.decay; // 減少生命值this.size *= 0.99; // 縮小粒子}draw() {// 繪制發光效果和粒子本體}
}
設計要點:
- 使用隨機值創建自然的粒子運動
- 生命周期管理確保粒子會自然消失
- 漸變發光效果增強視覺沖擊力
Star 類(五角星系統)
五角星類管理五角星的繪制、旋轉和粒子生成:
class Star {constructor(x, y, size) {this.x = x;this.y = y;this.size = size;this.rotation = 0; // 旋轉角度this.glowIntensity = 0; // 發光強度this.glowDirection = 1; // 發光方向this.particles = []; // 粒子數組this.lastParticleTime = 0; // 上次生成粒子的時間}getStarPoints() {// 計算五角星的10個頂點坐標const points = [];const outerRadius = this.size;const innerRadius = this.size * 0.4;for (let i = 0; i < 10; i++) {const angle = (i * Math.PI) / 5 + this.rotation;const radius = i % 2 === 0 ? outerRadius : innerRadius;const x = this.x + Math.cos(angle) * radius;const y = this.y + Math.sin(angle) * radius;points.push({ x, y });}return points;}
}
核心算法解析
1. 五角星頂點計算
五角星的繪制是基于數學計算的。一個標準五角星有10個頂點(5個外頂點和5個內頂點):
// 五角星頂點計算公式
for (let i = 0; i < 10; i++) {const angle = (i * Math.PI) / 5 + this.rotation; // 每個頂點間隔36度const radius = i % 2 === 0 ? outerRadius : innerRadius;const x = centerX + Math.cos(angle) * radius;const y = centerY + Math.sin(angle) * radius;
}
數學原理:
- 五角星的外角為36°(2π/10)
- 內外半徑比例約為0.4,創造最佳視覺效果
- 通過旋轉角度實現動態旋轉
2. 粒子生成策略
粒子的生成采用了多種策略來創造豐富的視覺效果:
generateParticles() {const points = this.getStarPoints();// 策略1:在五角星邊緣生成粒子for (let i = 0; i < points.length; i++) {const point = points[i];const nextPoint = points[(i + 1) % points.length];// 線性插值在邊緣隨機位置生成粒子const t = Math.random();const x = point.x + (nextPoint.x - point.x) * t;const y = point.y + (nextPoint.y - point.y) * t;if (Math.random() < 0.3) {this.particles.push(new Particle(x, y));}}// 策略2:在頂點生成更多粒子for (let i = 0; i < points.length; i += 2) {const point = points[i];if (Math.random() < 0.5) {this.particles.push(new Particle(point.x, point.y));}}
}
3. 發光效果實現
發光效果通過Canvas的陰影和漸變功能實現:
// 動態發光強度
this.glowIntensity += this.glowDirection * 0.02;
if (this.glowIntensity >= 1 || this.glowIntensity <= 0) {this.glowDirection *= -1; // 反向,創造呼吸效果
}// 應用發光效果
ctx.shadowColor = `rgba(255, 255, 100, ${this.glowIntensity})`;
ctx.shadowBlur = 20 + this.glowIntensity * 30;
性能優化技巧
1. 粒子生命周期管理
// 高效的粒子清理
this.particles = this.particles.filter(particle => {particle.update();return particle.life > 0; // 只保留活著的粒子
});
2. 時間控制的粒子生成
// 避免每幀都生成粒子,控制生成頻率
const now = Date.now();
if (now - this.lastParticleTime > 50) {this.generateParticles();this.lastParticleTime = now;
}
3. 漸進式畫布清理
// 使用半透明矩形而非完全清除,創造拖尾效果
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
交互設計
鼠標交互
canvas.addEventListener('mousemove', (e) => {const rect = canvas.getBoundingClientRect();const mouseX = e.clientX - rect.left;const mouseY = e.clientY - rect.top;stars.forEach(star => {const dx = mouseX - star.x;const dy = mouseY - star.y;const distance = Math.sqrt(dx * dx + dy * dy);if (distance < 150) {// 鼠標靠近時增加粒子生成for (let i = 0; i < 3; i++) {const angle = Math.random() * Math.PI * 2;const radius = Math.random() * star.size;const x = star.x + Math.cos(angle) * radius;const y = star.y + Math.sin(angle) * radius;star.particles.push(new Particle(x, y));}}});
});
響應式設計
window.addEventListener('resize', () => {canvas.width = window.innerWidth;canvas.height = window.innerHeight;// 重新定位五角星stars.forEach((star, i) => {star.x = canvas.width / 4 + (i * canvas.width / 4);star.y = canvas.height / 2 + Math.sin(i * 2) * 100;});
});
擴展可能性
1. 顏色主題
可以添加多種顏色主題,讓用戶選擇不同的視覺風格:
const themes = {golden: { r: 255, g: 215, b: 0 },blue: { r: 100, g: 150, b: 255 },purple: { r: 200, g: 100, b: 255 }
};
2. 音頻響應
可以集成Web Audio API,讓粒子效果響應音頻頻率:
// 偽代碼
const audioContext = new AudioContext();
// 根據音頻頻率調整粒子生成速度和五角星大小
3. 3D效果
使用WebGL或Three.js可以將效果擴展到3D空間。
總結
這個動態閃爍發光粒子五角星項目展示了現代Web技術的強大能力。通過合理的類設計、數學計算、性能優化和交互設計,我們創造了一個既美觀又高效的視覺效果。
關鍵技術點:
- Canvas 2D API的高級應用
- 面向對象的JavaScript設計
- 數學在圖形編程中的應用
- 性能優化策略
- 用戶交互設計
這個項目不僅可以作為學習Canvas和JavaScript的優秀案例,也可以作為更復雜視覺效果的基礎框架。希望這篇博客能夠幫助你理解現代Web圖形編程的精髓,并激發你創造更多令人驚艷的視覺效果!
源碼
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>動態閃爍發光粒子五角星</title><style>body {margin: 0;padding: 0;background: #000;overflow: hidden;display: flex;justify-content: center;align-items: center;height: 100vh;}canvas {border: 1px solid #333;}</style>
</head>
<body><canvas id="starCanvas"></canvas><script>const canvas = document.getElementById('starCanvas');const ctx = canvas.getContext('2d');// 設置畫布大小canvas.width = window.innerWidth;canvas.height = window.innerHeight;// 粒子類class Particle {constructor(x, y) {this.x = x;this.y = y;this.vx = (Math.random() - 0.5) * 2;this.vy = (Math.random() - 0.5) * 2;this.life = 1;this.decay = Math.random() * 0.02 + 0.005;this.size = Math.random() * 3 + 1;this.color = {r: Math.random() * 100 + 155,g: Math.random() * 100 + 155,b: Math.random() * 100 + 155};}update() {this.x += this.vx;this.y += this.vy;this.life -= this.decay;this.size *= 0.99;}draw() {ctx.save();ctx.globalAlpha = this.life;// 創建發光效果const gradient = ctx.createRadialGradient(this.x, this.y, 0,this.x, this.y, this.size * 3);gradient.addColorStop(0, `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 1)`);gradient.addColorStop(0.5, `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 0.5)`);gradient.addColorStop(1, `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 0)`);ctx.fillStyle = gradient;ctx.beginPath();ctx.arc(this.x, this.y, this.size * 3, 0, Math.PI * 2);ctx.fill();// 繪制核心粒子ctx.fillStyle = `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 1)`;ctx.beginPath();ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);ctx.fill();ctx.restore();}}// 五角星類class Star {constructor(x, y, size) {this.x = x;this.y = y;this.size = size;this.rotation = 0;this.glowIntensity = 0;this.glowDirection = 1;this.particles = [];this.lastParticleTime = 0;}// 計算五角星的頂點getStarPoints() {const points = [];const outerRadius = this.size;const innerRadius = this.size * 0.4;for (let i = 0; i < 10; i++) {const angle = (i * Math.PI) / 5 + this.rotation;const radius = i % 2 === 0 ? outerRadius : innerRadius;const x = this.x + Math.cos(angle) * radius;const y = this.y + Math.sin(angle) * radius;points.push({ x, y });}return points;}update() {this.rotation += 0.01;// 更新發光強度this.glowIntensity += this.glowDirection * 0.02;if (this.glowIntensity >= 1 || this.glowIntensity <= 0) {this.glowDirection *= -1;}// 生成粒子const now = Date.now();if (now - this.lastParticleTime > 50) {this.generateParticles();this.lastParticleTime = now;}// 更新粒子this.particles = this.particles.filter(particle => {particle.update();return particle.life > 0;});}generateParticles() {const points = this.getStarPoints();// 在五角星邊緣生成粒子for (let i = 0; i < points.length; i++) {const point = points[i];const nextPoint = points[(i + 1) % points.length];// 在邊緣隨機位置生成粒子const t = Math.random();const x = point.x + (nextPoint.x - point.x) * t;const y = point.y + (nextPoint.y - point.y) * t;if (Math.random() < 0.3) {this.particles.push(new Particle(x, y));}}// 在五角星頂點生成更多粒子for (let i = 0; i < points.length; i += 2) {const point = points[i];if (Math.random() < 0.5) {this.particles.push(new Particle(point.x, point.y));}}}draw() {const points = this.getStarPoints();// 繪制發光效果ctx.save();ctx.shadowColor = `rgba(255, 255, 100, ${this.glowIntensity})`;ctx.shadowBlur = 20 + this.glowIntensity * 30;// 繪制五角星主體ctx.fillStyle = `rgba(255, 255, 150, ${0.8 + this.glowIntensity * 0.2})`;ctx.strokeStyle = `rgba(255, 255, 200, ${0.9 + this.glowIntensity * 0.1})`;ctx.lineWidth = 2;ctx.beginPath();ctx.moveTo(points[0].x, points[0].y);for (let i = 1; i < points.length; i++) {ctx.lineTo(points[i].x, points[i].y);}ctx.closePath();ctx.fill();ctx.stroke();ctx.restore();// 繪制粒子this.particles.forEach(particle => particle.draw());}}// 創建多個五角星const stars = [];const numStars = 3;for (let i = 0; i < numStars; i++) {const x = canvas.width / 4 + (i * canvas.width / 4);const y = canvas.height / 2 + Math.sin(i * 2) * 100;const size = 50 + Math.random() * 30;stars.push(new Star(x, y, size));}// 動畫循環function animate() {// 清除畫布ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';ctx.fillRect(0, 0, canvas.width, canvas.height);// 更新和繪制所有五角星stars.forEach(star => {star.update();star.draw();});requestAnimationFrame(animate);}// 窗口大小調整window.addEventListener('resize', () => {canvas.width = window.innerWidth;canvas.height = window.innerHeight;// 重新定位五角星stars.forEach((star, i) => {star.x = canvas.width / 4 + (i * canvas.width / 4);star.y = canvas.height / 2 + Math.sin(i * 2) * 100;});});// 鼠標交互canvas.addEventListener('mousemove', (e) => {const rect = canvas.getBoundingClientRect();const mouseX = e.clientX - rect.left;const mouseY = e.clientY - rect.top;stars.forEach(star => {const dx = mouseX - star.x;const dy = mouseY - star.y;const distance = Math.sqrt(dx * dx + dy * dy);if (distance < 150) {// 鼠標靠近時增加粒子生成for (let i = 0; i < 3; i++) {const angle = Math.random() * Math.PI * 2;const radius = Math.random() * star.size;const x = star.x + Math.cos(angle) * radius;const y = star.y + Math.sin(angle) * radius;star.particles.push(new Particle(x, y));}}});});// 開始動畫animate();</script>
</body>
</html>
如果你覺得這個效果有趣,不妨嘗試修改參數,創造屬于你自己的獨特效果!