<!DOCTYPE html>
<html>
<head>
<title>烟花动画</title>
<style>
body, html { height: 100%; margin: 0; }
canvas { position: absolute; }
</style>
</head>
<body>
<canvas id="fireworks"></canvas>
<audio id="background-music" loop>
<source src="YOUR_MUSIC_FILE.mp3" type="audio/mp3">
Your browser does not support the audio element.
</audio>
<script>
const canvas = document.getElementById('fireworks');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const backgroundMusic = document.getElementById("background-music");
backgroundMusic.play();
class Particle {
constructor(x, y, color, velocity, size) {
this.x = x;
this.y = y;
this.color = color;
this.velocity = velocity;
this.size = size;
this.alpha = 1;
this.friction = 0.95;
this.gravity = 0.03;
}
draw() {
ctx.save();
ctx.globalCompositeOperation = 'lighter';
ctx.globalAlpha = this.alpha;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
ctx.restore();
}
update() {
this.velocity.x *= this.friction;
this.velocity.y *= this.friction;
this.velocity.y += this.gravity;
this.x += this.velocity.x;
this.y += this.velocity.y;
this.alpha -= 0.02;
}
}
class Firework {
constructor(x, y, targetY, color, size) {
this.x = x;
this.y = y;
this.size = size;
this.color = color;
this.targetY = targetY;
this.particles = [];
this.exploded = false;
this.velocity = {
x: 0,
y: -Math.random() * 3 - 9
};
}
explode() {
for (let i = 0; i < 500; i++) {
const angle = Math.random() * Math.PI * 2;
const speed = Math.random() * 6 + 1;
this.particles.push(new Particle(this.x, this.y, this.color, {
x: Math.cos(angle) * speed,
y: Math.sin(angle) * speed
}, this.size / 2));
}
}
draw() {
if (!this.exploded) {
ctx.save();
ctx.globalCompositeOperation = 'lighter';
ctx.globalAlpha = 0.8;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
ctx.restore();
}
for (const particle of this.particles) {
particle.draw();
}
}
update() {
if (!this.exploded) {
this.velocity.y += 0.1;
this.x += this.velocity.x;
this.y += this.velocity.y;
if (this.y < this.targetY || this.velocity.y >= 0) {
this.exploded = true;
this.explode();
}
}
for (let i = this.particles.length - 1; i >= 0; i--) {
const p = this.particles[i];
p.update();
if (p.alpha <= 0) {
this.particles.splice(i, 1);
}
}
}
}
let fireworks = [];
let timer = 0;
function randomColor() {
const hue = Math.floor(Math.random() * 360);
const saturation = 100;
const lightness = 60;
return `hsl(${hue},${saturation}%,${lightness}%)`;
}
const greetings = ['Happy New Year !', 'Welcome 2024 !', 'Celebration !'];
let currentGreeting = 0;
let colorHue = 0;
function drawText() {
ctx.font = '50px Arial';
ctx.fillStyle = `hsl(${colorHue}, 100%, 50%)`;
ctx.textAlign = 'center';
ctx.fillText(greetings[currentGreeting], canvas.width / 2, canvas.height / 2 - 100);
}
function animate() {
requestAnimationFrame(animate);
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (timer % 10 === 0) {
const x = Math.random() * canvas.width;
const targetY = Math.random() * (canvas.height * 0.3) + 50;
fireworks.push(new Firework(x, canvas.height, targetY, randomColor(), Math.random() * 4 + 1));
}
timer++;
for (let i = fireworks.length - 1; i >= 0; i--) {
fireworks[i].update();
fireworks[i].draw();
if (fireworks[i].exploded && fireworks[i].particles.length === 0) {
fireworks.splice(i, 1);
}
}
colorHue += 1;
if (colorHue > 360) { colorHue = 0; }
if (timer % 300 === 0) {
currentGreeting = (currentGreeting + 1) % greetings.length;
}
drawText();
}
window.addEventListener('resize', function() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
animate();
</script>
</body>
</html>