放爱心烟花
<!DOCTYPE html>
<html>
<head>
<title>心形烟花特效</title>
<style>
body { margin: 0; overflow: hidden; background: #000; }
#modeBtn {
position: fixed; top: 20px; left: 20px;
padding: 10px; background: rgba(255,255,255,0.2);
color: white; border: none; cursor: pointer;
}
</style>
</head>
<body>
<button id="modeBtn">自动模式</button>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let isAutoMode = false;
const modeBtn = document.getElementById('modeBtn');
// 心形生成算法优化(增强粒子密度与尺寸)
function generateHeartPoints(centerX, centerY) {
const points = [];
for(let t=0; t < Math.PI*2; t += 0.03) { // 增加采样密度
const x = 16 * Math.pow(Math.sin(t),3);
const y = -13*Math.cos(t) + 5*Math.cos(2*t) + 2*Math.cos(3*t) + Math.cos(4*t);
points.push({
x: centerX + x*12, // 放大系数提升至12
y: centerY + y*12,
size: Math.random()*4 + 2, // 粒子尺寸增大
hue: Math.random()*360
});
}
return points;
}
// 粒子类(增加运动阻尼与颜色动态)
class Particle {
constructor(x, y, target) {
this.x = x;
this.y = y;
this.target = target;
this.speed = { x: 0, y: 0 };
this.alpha = 1;
this.friction = 0.93; // 增加运动阻尼
}
update() {
// 向心形目标点加速
const dx = this.target.x - this.x;
const dy = this.target.y - this.y;
this.speed.x += dx * 0.02;
this.speed.y += dy * 0.02;
// 物理模拟
this.x += this.speed.x;
this.y += this.speed.y;
this.speed.x *= this.friction;
this.speed.y *= this.friction;
this.alpha -= 0.006; // 延长显示时间
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.target.size, 0, Math.PI*2);
ctx.fillStyle = `hsla(${this.target.hue},100%,60%,${this.alpha})`;
ctx.fill();
}
}
// 烟花发射器(增加上升轨迹)
class Firework {
constructor(targetX, targetY) {
this.x = Math.random()*canvas.width;
this.y = canvas.height;
this.targetY = targetY || canvas.height/3;
this.particles = [];
this.speed = -12; // 提升上升速度
this.exploded = false;
}
update() {
if (!this.exploded) {
this.y += this.speed;
if (this.y <= this.targetY) this.explode();
} else {
this.particles.forEach(p => p.update());
this.particles = this.particles.filter(p => p.alpha > 0);
}
}
explode() {
this.exploded = true;
const heartPoints = generateHeartPoints(this.x, this.y);
heartPoints.forEach(point => {
this.particles.push(new Particle(this.x, this.y, point));
});
}
draw() {
if (!this.exploded) {
// 绘制上升轨迹
ctx.beginPath();
ctx.arc(this.x, this.y, 3, 0, Math.PI*2);
ctx.fillStyle = `hsla(${Math.random()*360},100%,60%,1)`;
ctx.fill();
} else {
this.particles.forEach(p => p.draw());
}
}
}
// 控制系统(优化自动模式)
let fireworks = [];
modeBtn.addEventListener('click', () => {
isAutoMode = !isAutoMode;
modeBtn.textContent = isAutoMode ? '手动模式' : '自动模式';
});
canvas.addEventListener('click', e => {
fireworks.push(new Firework(e.clientX, e.clientY));
});
// 动画循环(性能优化)
function animate() {
ctx.fillStyle = 'rgba(0,0,0,0.08)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 自动模式生成(限制最大数量)
if(isAutoMode && fireworks.length < 4 && Math.random() < 0.04) {
fireworks.push(new Firework());
}
fireworks.forEach((fw, index) => {
fw.update();
fw.draw();
if (fw.exploded && fw.particles.length === 0) {
fireworks.splice(index, 1);
}
});
requestAnimationFrame(animate);
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
animate();
// 画布尺寸自适应
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
</script>
</body>
</html>