-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
295 lines (261 loc) · 10.7 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>fireworks</title>
<style>
body,
html {
margin: 0;
padding: 0;
overflow: hidden;
background-color: black;
}
canvas {
display: block;
}
button {
position: absolute;
top: 10px;
left: 10px;
z-index: 100;
padding: 10px 20px;
background-color: rgba(255, 255, 255, 0.2);
color: rgb(38, 159, 101);
border: none;
cursor: pointer;
}
#message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #5f93d7;
font-size: 54px;
font-family: 'Pacifico', fantasy, sans-serif;
/* 添加具体字体名称 */
z-index: 101;
display: none;
}
#interactionPrompt {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 24px;
z-index: 102;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Monoton&family=Pacifico&display=swap" rel="stylesheet">
</head>
<body>
<canvas id="fireworksCanvas"></canvas>
<button id="pauseButton">暂停</button>
<div id="message">Happy New Year!
<br>
<br>
愿2025更美好!
<br>
</div>
<div id="interactionPrompt">点击屏幕以播放音乐</div> <!-- 添加提示信息 -->
<audio id="bgm" src="bgm.mp3" loop></audio> <!-- 添加背景音乐音频元素 -->
<audio id="fireworkSound" src="firebomb.mp3" preload="auto"></audio> <!-- 添加烟花音效音频元素 -->
<script>
const canvas = document.getElementById('fireworksCanvas');
const ctx = canvas.getContext('2d');
const messageDiv = document.getElementById('message');
const interactionPrompt = document.getElementById('interactionPrompt'); // 获取提示信息元素
const bgm = document.getElementById('bgm'); // 获取背景音乐音频元素
const fireworkSound = document.getElementById('fireworkSound'); // 获取烟花音效音频元素
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 预设静态的星光背景
function drawStaticBackground() {
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, 'rgba(0, 0, 100, 0.8)');
gradient.addColorStop(1, 'rgba(0, 0, 30, 1)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制星星
for (let i = 0; i < 200; i++) {
const starX = Math.random() * canvas.width;
const starY = Math.random() * canvas.height;
const starSize = Math.random() * 2;
const starOpacity = Math.random() * 0.5 + 0.5;
ctx.globalAlpha = starOpacity;
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(starX, starY, starSize, 0, Math.PI * 2);
ctx.fill();
}
ctx.globalAlpha = 1; // 重置透明度为1
}
//drawStaticBackground(); // 只绘制一次背景
// 烟花粒子类
class Particle {
constructor(x, y, color, speed, angle) {
this.x = x;
this.y = y;
this.speed = speed;
this.angle = angle + (Math.random() * 0.1 - 0.05);
this.color = color;
this.size = Math.random() * 3 + 2; // 增加粒子大小范围
this.gravity = 0.23; // 减小重力影响
this.opacity = 1;
this.life = Math.random() * 100 + 100; // 减少生命周期
this.trail = [];
}
update() {
this.speed *= 0.95; // 修改为更缓和的速度衰减
this.x += this.speed * Math.cos(this.angle);
this.y += this.speed * Math.sin(this.angle) + this.gravity;
// 自然透明度衰减
this.opacity -= 0.2 / this.life;
this.trail.push({ x: this.x, y: this.y, opacity: this.opacity });
if (this.trail.length > 18) {
this.trail.shift();
}
}
draw() {
for (let i = 0; i < this.trail.length; i++) {
const trail = this.trail[i];
ctx.globalAlpha = trail.opacity * (1 - i / this.trail.length);
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(trail.x, trail.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
ctx.globalAlpha = Math.max(this.opacity, 0);
const gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.size);
gradient.addColorStop(0, this.color);
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}
// 烟花类
class Firework {
constructor(startX, startY, targetX, targetY) {
this.x = startX;
this.y = startY;
this.targetX = targetX;
this.targetY = targetY;
this.speed = 4;
this.angle = Math.atan2(targetY - startY, targetX - startX);
this.particles = [];
this.exploded = false;
this.color = `hsl(${Math.random() * 360}, 100%, 80%)`;
}
update() {
if (!this.exploded) {
const distance = Math.hypot(this.targetX - this.x, this.targetY - this.y);
if (distance < this.speed) {
this.exploded = true;
this.explode();
} else {
this.x += this.speed * Math.cos(this.angle);
this.y += this.speed * Math.sin(this.angle);
}
}
this.particles.forEach((particle, index) => {
particle.update();
if (particle.opacity <= 0 || particle.life <= 0) {
this.particles.splice(index, 1);
}
});
}
draw() {
if (!this.exploded) {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, 2, 0, Math.PI * 2);
ctx.fill();
}
this.particles.forEach(particle => particle.draw());
}
explode() {
fireworkSound.currentTime = 0; // 重置音频播放时间
fireworkSound.play().catch(error => {
console.error('播放烟花音效失败:', error);
});
const particleCount = 55; // 减少粒子数量
const baseSpeed = 8; // 增加基础速度
for (let i = 0; i < particleCount; i++) {
const angle = (Math.PI * 2 * i) / particleCount + (Math.random() * 0.1 - 0.05);
const speed = baseSpeed * (Math.random() * 0.5 + 0.5);
const color = `hsl(${Math.random() * 360}, 100%, 80%)`;
this.particles.push(new Particle(this.x, this.y, color, speed, angle));
}
}
}
const fireworks = [];
let animationFrameId;
let startTime;
function animate(timestamp) {
if (!startTime) startTime = timestamp;
const elapsedTime = timestamp - startTime;
ctx.clearRect(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);
}
});
if (elapsedTime >= 10000) { // 10秒后显示消息
messageDiv.style.display = 'block';
}
animationFrameId = requestAnimationFrame(animate);
}
function launchFirework() {
const centerX = canvas.width / 2 + (Math.random() * 100 - 100);
const centerY = canvas.height;
const startX = centerX;
const startY = centerY;
// 设置烟花的目标位置在屏幕中央附近的一个随机范围内
const targetX = (Math.random() * (canvas.width / 2.5)) + 400; // 在中央左右100像素范围内
const targetY = 300 + (Math.random() * 300 - 200); // 在中央上下50像素范围内
fireworks.push(new Firework(startX, startY, targetX, targetY));
}
setInterval(launchFirework, 1500); // 减少烟花发射频率
animate();
// 添加暂停和恢复功能
let isPaused = false;
let bgmPlayed = false;
const pauseButton = document.getElementById('pauseButton');
pauseButton.addEventListener('click', () => {
if (!isPaused) {
cancelAnimationFrame(animationFrameId);
bgm.pause(); // 暂停背景音乐
pauseButton.textContent = '恢复';
} else {
animate();
bgm.play(); // 恢复背景音乐
pauseButton.textContent = '暂停';
}
isPaused = !isPaused;
});
// 用户交互触发背景音乐解除静音并播放
document.addEventListener('click', () => {
if (!bgmPlayed) {
bgm.muted = false; // 解除静音
bgm.play().catch(error => {
console.error('播放背景音乐失败:', error);
});
interactionPrompt.style.display = 'none'; // 隐藏提示信息
bgmPlayed = true; // 标记背景音乐已播放
}
});
// 尝试在页面加载后自动播放背景音乐(静音)
window.addEventListener('load', () => {
bgm.muted = true; // 初始静音
bgm.play().catch(error => {
console.error('自动播放背景音乐失败:', error);
});
});
</script>
</body>
</html>