一直想写一个静态的放烟花网页,用来表达对某人的表白或者祝福,网上参考了寻找了一些,都是代码不全的或者需要VIP的,所以结合自己的创意和想法写了一款包含多个特效烟花的网页,现在附上源码,如果杜宇特效不满意,可以借助豆包AI工具进行调整。
你可以自行修改标题,和祝福文字。将以下代码保存为xx.html文件,浏览器打开就能看到效果了。
全部源代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>写你的title</title>
<link rel="icon" type="image/png" href="https://tanqiao.top/file-service/file/download?filePath=/fileServiceRoot/uploads/yh-logo.png">
<style>
html,
body {
overflow: hidden;
height: 100%;
margin: 0;
padding: 0;
background-color: black;
/* 使用图片作为背景并铺满整个页面 */
background: url('https://tanqiao.top/file-service/file/download?filePath=/fileServiceRoot/uploads/stars.jfif') no-repeat center center fixed;
background-size: cover;
}
.moon {
position: absolute;
top: 50px;
right: 50px;
width: 100px;
height: 100px;
border-radius: 50%;
box-shadow: 15px 15px 0 0 white;
}
.dynamic-text {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
font-size: 48px;
font-weight: bold;
text-align: center;
background: linear-gradient(90deg, #ff00ff, #ff8800, #ff00ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: gradient-flow 5s infinite linear, glow-pulse 1s infinite ease-in-out;
text-shadow:
0 0 5px #ff00ff,
0 0 10px #ff00ff,
0 0 20px #ff00ff,
0 0 40px #ff8800,
0 0 80px #ff8800;
letter-spacing: 5px;
}
@keyframes gradient-flow {
0% {
background-position: 0% 50%;
}
100% {
background-position: 100% 50%;
}
}
@keyframes glow-pulse {
0%, 100% {
text-shadow:
0 0 5px #ff00ff,
0 0 10px #ff00ff,
0 0 20px #ff00ff,
0 0 40px #ff8800,
0 0 80px #ff8800;
opacity: 0.7;
}
50% {
text-shadow:
0 0 10px #ff00ff,
0 0 20px #ff00ff,
0 0 40px #ff00ff,
0 0 60px #ff8800,
0 0 100px #ff8800;
opacity: 1;
}
}
canvas {
display: block;
}
</style>
</head>
<body>
<div class="dynamic-text" id="dynamicText">写你自己的标题!</div>
<!--<div class="moon"></div>-->
<canvas id="fireworkCanvas"></canvas>
<script>
const canvas = document.getElementById('fireworkCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const fireworks = [];
const particles = [];
const text = document.getElementById('dynamicText').textContent;
const textX = canvas.width / 2;
const textY = canvas.height / 2;
const fontSize = 100;
function getRandomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
class Firework {
constructor(x, y, targetY) {
this.x = x;
this.y = y;
this.targetY = targetY;
this.color = getRandomColor();
this.speed = 5;
// 加载火箭图片
this.rocketImage = new Image();
this.rocketImage.src = 'https://tanqiao.top/file-service/file/download?filePath=/fileServiceRoot/uploads/yh-rocket.png';
}
update() {
this.y -= this.speed;
if (this.y <= this.targetY) {
this.explode();
const index = fireworks.indexOf(this);
if (index!== -1) {
fireworks.splice(index, 1);
}
}
}
draw() {
if (this.rocketImage.complete) {
// 绘制火箭图片
ctx.drawImage(this.rocketImage, this.x - this.rocketImage.width / 2, this.y - this.rocketImage.height / 2,30,50);
}
}
explode() {
const particleCount = 150;
const types = [
"circle", "heart", "star", "spiral", "six-pointed", "flower", "burst", "ring", "zigzag", "diamond",
"double-circle", "triple-star", "spiked-ball", "wave", "cross", "swirl", "triangle", "pentagon", "hexagon",
"arrow", "lightning", "dandelion", "confetti", "ribbon", "chain", "web", "teardrop", "comet", "fireball"
];
const type = types[Math.floor(Math.random() * types.length)];
for (let i = 0; i < particleCount; i++) {
let dx, dy;
if (type === "circle") {
const angle = (i / particleCount) * Math.PI * 2;
dx = Math.cos(angle) * 200;
dy = Math.sin(angle) * 200;
} else if (type === "heart") {
const angle = (i / particleCount) * Math.PI * 2;
dx = 16 * Math.pow(Math.sin(angle), 3) * 10;
dy = -(13 * Math.cos(angle) - 5 * Math.cos(2 * angle) - 2 * Math.cos(3 * angle) - Math.cos(4 * angle)) * 10;
} else if (type === "star") {
const angle = (i % 5) * (Math.PI * 2) / 5;
const distance = i % 2 === 0? 150 : 80;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "spiral") {
const angle = (i / particleCount) * Math.PI * 8;
const radius = i * 2;
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "six-pointed") {
const angle = (i % 6) * (Math.PI * 2) / 6;
const distance = i % 2 === 0? 180 : 120;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "flower") {
const angle = (i / particleCount) * Math.PI * 10;
const radius = 150 + 50 * Math.sin(5 * angle);
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "burst") {
dx = (Math.random() - 0.5) * 300;
dy = (Math.random() - 0.5) * 300;
} else if (type === "ring") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 200;
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "zigzag") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + (i % 2 === 0? 50 : -50);
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "diamond") {
const angle = (i % 4) * (Math.PI * 2) / 4;
const distance = i % 2 === 0? 180 : 120;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "double-circle") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = i % 2 === 0? 150 : 200;
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "triple-star") {
const angle = (i % 15) * (Math.PI * 2) / 15;
const distance = [80, 120, 150][i % 3];
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "spiked-ball") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + (Math.random() * 50);
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "wave") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + 30 * Math.sin(10 * angle);
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "cross") {
const angle = (i % 4) * (Math.PI * 2) / 4;
const distance = i % 2 === 0? 180 : 120;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "swirl") {
const angle = (i / particleCount) * Math.PI * 12;
const radius = i * 1.5;
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "triangle") {
const angle = (i % 3) * (Math.PI * 2) / 3;
const distance = i % 2 === 0? 180 : 120;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "pentagon") {
const angle = (i % 5) * (Math.PI * 2) / 5;
const distance = i % 2 === 0? 180 : 120;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "hexagon") {
const angle = (i % 6) * (Math.PI * 2) / 6;
const distance = i % 2 === 0? 180 : 120;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "arrow") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150;
if (i < particleCount / 2) {
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else {
dx = Math.cos(angle + Math.PI) * (radius / 2);
dy = Math.sin(angle + Math.PI) * (radius / 2);
}
} else if (type === "lightning") {
const angle = (Math.random() - 0.5) * Math.PI;
const distance = Math.random() * 200;
dx = Math.cos(angle) * distance;
dy = Math.sin(angle) * distance;
} else if (type === "dandelion") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + Math.random() * 50;
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "confetti") {
dx = (Math.random() - 0.5) * 200;
dy = (Math.random() - 0.5) * 200;
} else if (type === "ribbon") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + 20 * Math.sin(20 * angle);
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "chain") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + (i % 10) * 10;
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "web") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + (Math.random() * 50);
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "teardrop") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + 50 * Math.sin(3 * angle);
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "comet") {
const angle = (i / particleCount) * Math.PI * 2;
const radius = 150 + i * 2;
dx = Math.cos(angle) * radius;
dy = Math.sin(angle) * radius;
} else if (type === "fireball") {
dx = (Math.random() - 0.5) * 250;
dy = (Math.random() - 0.5) * 250;
}
particles.push(new Particle(this.x, this.y, dx, dy, getRandomColor()));
}
}
}
class Particle {
constructor(x, y, dx, dy, color) {
this.x = x;
this.y = y;
this.dx = dx / 50;
this.dy = dy / 50;
this.color = color;
this.alpha = 1;
this.fadeSpeed = 0.01;
}
update() {
this.x += this.dx;
this.y += this.dy;
this.alpha -= this.fadeSpeed;
if (this.alpha <= 0) {
const index = particles.indexOf(this);
if (index!== -1) {
particles.splice(index, 1);
}
}
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, 5, 0, Math.PI * 2);
ctx.fillStyle = `rgba(${parseInt(this.color.slice(1, 3), 16)}, ${parseInt(this.color.slice(3, 5), 16)}, ${parseInt(this.color.slice(5, 7), 16)}, ${this.alpha})`;
ctx.fill();
}
}
function createFirework() {
const x = Math.floor(Math.random() * (canvas.width - 100 - 100 + 1)) + 100;
const y = canvas.height;
const targetY = Math.floor(Math.random() * (800 - 100 + 1)) + 100;
fireworks.push(new Firework(x, y, targetY));
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = fireworks.length - 1; i >= 0; i--) {
const firework = fireworks[i];
firework.update();
firework.draw();
}
for (let i = particles.length - 1; i >= 0; i--) {
const particle = particles[i];
particle.update();
particle.draw();
}
requestAnimationFrame(animate);
}
// 提高创建烟花的频率,确保持续发射
setInterval(createFirework, 1000);
animate();
</script>
</body>
</html>