@mar7th/firework 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/404.html +25 -0
- package/LICENSE +21 -0
- package/advanced-guide.html +135 -0
- package/api-download.html +164 -0
- package/demo.html +83 -0
- package/dist-lib/spark-fireworks.js +875 -0
- package/dist-lib/spark-fireworks.umd.cjs +1 -0
- package/docs/api-guide.md +750 -0
- package/docs/performance-optimization-plan.md +396 -0
- package/examples/production.html +203 -0
- package/favicon.jpg +0 -0
- package/guide.html +89 -0
- package/index.html +60 -0
- package/package.json +38 -0
- package/script/script1.js +34 -0
- package/script/script2.js +38 -0
- package/script/script3.js +63 -0
- package/script/script4.js +51 -0
- package/script/script5.js +55 -0
- package/scripts/copy-dist-lib.mjs +4 -0
- package/src/app.js +49 -0
- package/src/config/defaults.js +302 -0
- package/src/core/Firework.js +213 -0
- package/src/core/FireworksSimulator.js +439 -0
- package/src/core/Particle.js +174 -0
- package/src/core/ParticleSystem.js +56 -0
- package/src/core/Renderer.js +44 -0
- package/src/demo.js +298 -0
- package/src/effects/BackgroundManager.js +100 -0
- package/src/pages.css +388 -0
- package/src/pages.js +1 -0
- package/src/plugin.js +9 -0
- package/src/styles.css +544 -0
- package/src/ui/ControlPanel.js +205 -0
- package/src/ui/PerformancePanel.js +23 -0
- package/src/ui/PresetManager.js +128 -0
- package/src/utils/color.js +54 -0
- package/src/utils/eventBus.js +21 -0
- package/src/utils/math.js +29 -0
- package/vite.config.js +17 -0
- package/vite.lib.config.js +19 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
# SparkFireworks API 使用指南
|
|
2
|
+
|
|
3
|
+
本文档说明如何在页面中以插件方式使用烟花模拟器 API,包括初始化、参数设置、发射控制、预设、高级模式脚本和自定义粒子格式。
|
|
4
|
+
|
|
5
|
+
## 1. 构建与引入
|
|
6
|
+
|
|
7
|
+
先构建可在生产页面直接引入的库文件:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run build:lib
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
构建产物在:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
dist-lib/spark-fireworks.umd.cjs
|
|
17
|
+
dist-lib/spark-fireworks.js
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
普通 HTML 页面可以这样引入:
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<canvas id="fireworks"></canvas>
|
|
24
|
+
|
|
25
|
+
<script src="./dist-lib/spark-fireworks.umd.cjs"></script>
|
|
26
|
+
<script>
|
|
27
|
+
const fireworks = SparkFireworks.create("fireworks", {
|
|
28
|
+
particleCount: 240,
|
|
29
|
+
explosionShape: "sphere"
|
|
30
|
+
});
|
|
31
|
+
</script>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
也可以传入 canvas DOM:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
const canvas = document.getElementById("fireworks");
|
|
38
|
+
const fireworks = SparkFireworks.create(canvas, {
|
|
39
|
+
particleCount: 240
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 2. 初始化方式
|
|
44
|
+
|
|
45
|
+
`SparkFireworks.create(canvas, configOrOptions)` 会返回一个烟花控制器对象。
|
|
46
|
+
|
|
47
|
+
简单配置:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const fireworks = SparkFireworks.create("fireworks", {
|
|
51
|
+
particleCount: 300,
|
|
52
|
+
colorStart: "#ffd166",
|
|
53
|
+
colorEnd: "#ef476f"
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
完整 options 配置:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
const fireworks = SparkFireworks.create("fireworks", {
|
|
61
|
+
config: {
|
|
62
|
+
particleCount: 300,
|
|
63
|
+
explosionShape: "heart"
|
|
64
|
+
},
|
|
65
|
+
advancedMode: false,
|
|
66
|
+
createParticles(canvasData) {
|
|
67
|
+
return [];
|
|
68
|
+
},
|
|
69
|
+
onFpsChange(fps) {
|
|
70
|
+
console.log("FPS", fps);
|
|
71
|
+
},
|
|
72
|
+
onConfigChange(config) {
|
|
73
|
+
console.log("config changed", config);
|
|
74
|
+
},
|
|
75
|
+
onLowFps(config) {
|
|
76
|
+
console.log("low fps", config);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 3. 常用控制方法
|
|
82
|
+
|
|
83
|
+
### 发射烟花
|
|
84
|
+
|
|
85
|
+
直接在指定坐标发射:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
fireworks.launch(300, 200);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
带升空轨迹:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
fireworks.launch(300, 200, { withShell: true });
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
不带升空轨迹,直接爆炸:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
fireworks.launch(300, 200, { withShell: false });
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
随机坐标发射:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
fireworks.launchRandom();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
自定义随机坐标:
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
function launchRandom() {
|
|
113
|
+
const rect = canvas.getBoundingClientRect();
|
|
114
|
+
const x = rect.width * (0.16 + Math.random() * 0.68);
|
|
115
|
+
const y = rect.height * (0.16 + Math.random() * 0.46);
|
|
116
|
+
fireworks.launch(x, y, { withShell: true });
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 自动播放
|
|
121
|
+
|
|
122
|
+
开始自动播放:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
fireworks.startAutoPlay();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
指定自动播放间隔,单位秒:
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
fireworks.startAutoPlay(0.7);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
停止自动播放:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
fireworks.stopAutoPlay();
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
按布尔值设置:
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
fireworks.setAutoPlay(true, 0.9);
|
|
144
|
+
fireworks.setAutoPlay(false);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 暂停、恢复、清除
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
fireworks.pause();
|
|
151
|
+
fireworks.resume();
|
|
152
|
+
const paused = fireworks.togglePause();
|
|
153
|
+
fireworks.clearParticles();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 重置配置
|
|
157
|
+
|
|
158
|
+
恢复初始化时的配置:
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
fireworks.resetConfig();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
用一组新配置作为新的初始化配置:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
fireworks.resetConfig({
|
|
168
|
+
particleCount: 180,
|
|
169
|
+
explosionShape: "ring",
|
|
170
|
+
colorStart: "#4cc9f0",
|
|
171
|
+
colorEnd: "#80ffdb"
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 修改参数
|
|
176
|
+
|
|
177
|
+
局部修改参数:
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
fireworks.setConfig({
|
|
181
|
+
gravity: 0.12,
|
|
182
|
+
damping: 0.986,
|
|
183
|
+
colorStart: "#48d6c2"
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
读取当前配置:
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
const config = fireworks.getConfig();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 选择内置预设
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
fireworks.selectPreset("classic-gold");
|
|
197
|
+
fireworks.selectPreset("aurora");
|
|
198
|
+
fireworks.selectPreset("fountain");
|
|
199
|
+
fireworks.selectPreset("ghost");
|
|
200
|
+
fireworks.selectPreset("meteor");
|
|
201
|
+
fireworks.selectPreset("heart");
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
恢复默认预设:
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
fireworks.selectPreset("default");
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## 4. 配置参数
|
|
211
|
+
|
|
212
|
+
下面是常用参数和含义。
|
|
213
|
+
|
|
214
|
+
### 粒子基础
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
{
|
|
218
|
+
particleCount: 180, // 每次爆炸粒子数,10~1000
|
|
219
|
+
particleMinSize: 2.5, // 最小粒子尺寸
|
|
220
|
+
particleMaxSize: 7, // 最大粒子尺寸
|
|
221
|
+
sizeEndMultiplier: 0.35 // 生命周期结束时的尺寸比例
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 运动参数
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
{
|
|
229
|
+
gravity: 0.18, // 重力,正数向下,负数向上
|
|
230
|
+
damping: 0.982, // 速度衰减,越小阻力越强
|
|
231
|
+
initialSpeedMin: 2.8, // 初始最小速度
|
|
232
|
+
initialSpeedMax: 8.2, // 初始最大速度
|
|
233
|
+
particleLife: 94, // 粒子生命周期,单位约等于帧
|
|
234
|
+
rotationSpeed: 0.025, // 旋转速度
|
|
235
|
+
colorShiftRate: 0.035 // 颜色变化速率
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### 视觉参数
|
|
240
|
+
|
|
241
|
+
```js
|
|
242
|
+
{
|
|
243
|
+
colorStart: "#ffd166", // 起始颜色
|
|
244
|
+
colorEnd: "#ef476f", // 结束颜色
|
|
245
|
+
useRandomColors: false, // 是否随机颜色
|
|
246
|
+
textureType: "circle", // circle | square | star | heart
|
|
247
|
+
glowIntensity: 0.75 // 辉光强度
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### 特效参数
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
{
|
|
255
|
+
explosionShape: "sphere", // sphere | ring | starburst | flower | willow | scatter | heart
|
|
256
|
+
enableSecondaryBurst: false, // 是否二次爆炸
|
|
257
|
+
secondaryBurstRatio: 0.2, // 二次爆炸粒子比例,0-1
|
|
258
|
+
enableTrails: true, // 粒子是否带拖尾
|
|
259
|
+
showLaunchTrail: true, // 是否显示升空轨迹
|
|
260
|
+
windEnabled: false, // 是否开启风场
|
|
261
|
+
windX: 0, // 水平风
|
|
262
|
+
windY: 0, // 垂直风
|
|
263
|
+
flicker: true, // 是否闪烁
|
|
264
|
+
fadeTrail: 0.18 // 画面残影拖尾,越小拖尾越长
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 自动播放
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
{
|
|
272
|
+
autoLaunch: false, // 是否自动发射
|
|
273
|
+
autoLaunchIntervalSeconds: 0.9, // 自动发射间隔,秒
|
|
274
|
+
autoInterval: 900 // 兼容旧版本,自动发射间隔,毫秒
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### 背景
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
{
|
|
282
|
+
backgroundType: "starfield", // solid | linear | radial | starfield | image
|
|
283
|
+
backgroundColor: "#060912",
|
|
284
|
+
backgroundColor2: "#10243a",
|
|
285
|
+
backgroundImageMode: "cover" // cover | contain | tile
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## 5. 完整初始化参数示例
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
const fireworks = SparkFireworks.create("fireworks", {
|
|
293
|
+
particleCount: 260,
|
|
294
|
+
particleMinSize: 2.5,
|
|
295
|
+
particleMaxSize: 7,
|
|
296
|
+
sizeEndMultiplier: 0.35,
|
|
297
|
+
|
|
298
|
+
gravity: 0.18,
|
|
299
|
+
damping: 0.982,
|
|
300
|
+
initialSpeedMin: 2.8,
|
|
301
|
+
initialSpeedMax: 8.2,
|
|
302
|
+
particleLife: 94,
|
|
303
|
+
rotationSpeed: 0.025,
|
|
304
|
+
colorShiftRate: 0.035,
|
|
305
|
+
|
|
306
|
+
colorStart: "#ffd166",
|
|
307
|
+
colorEnd: "#ef476f",
|
|
308
|
+
useRandomColors: false,
|
|
309
|
+
textureType: "circle",
|
|
310
|
+
glowIntensity: 0.75,
|
|
311
|
+
|
|
312
|
+
explosionShape: "sphere",
|
|
313
|
+
enableSecondaryBurst: false,
|
|
314
|
+
secondaryBurstRatio: 0.2,
|
|
315
|
+
enableTrails: true,
|
|
316
|
+
showLaunchTrail: true,
|
|
317
|
+
windEnabled: false,
|
|
318
|
+
windX: 0,
|
|
319
|
+
windY: 0,
|
|
320
|
+
flicker: true,
|
|
321
|
+
fadeTrail: 0.18,
|
|
322
|
+
|
|
323
|
+
autoLaunch: false,
|
|
324
|
+
autoLaunchIntervalSeconds: 0.9,
|
|
325
|
+
autoInterval: 900,
|
|
326
|
+
|
|
327
|
+
backgroundType: "starfield",
|
|
328
|
+
backgroundColor: "#060912",
|
|
329
|
+
backgroundColor2: "#10243a",
|
|
330
|
+
backgroundImageMode: "cover"
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## 6. 高级模式
|
|
335
|
+
|
|
336
|
+
普通模式下,发射前会根据当前配置自动生成粒子。
|
|
337
|
+
|
|
338
|
+
高级模式下,发射前不再使用默认粒子生成逻辑,而是调用用户传入的 `createParticles(canvasData)`,由它返回一组粒子。
|
|
339
|
+
|
|
340
|
+
### 创建时开启高级模式
|
|
341
|
+
|
|
342
|
+
```js
|
|
343
|
+
const fireworks = SparkFireworks.create("fireworks", {
|
|
344
|
+
config: {
|
|
345
|
+
enableTrails: true,
|
|
346
|
+
glowIntensity: 1
|
|
347
|
+
},
|
|
348
|
+
advancedMode: true,
|
|
349
|
+
createParticles(canvasData) {
|
|
350
|
+
const particles = [];
|
|
351
|
+
|
|
352
|
+
for (let i = 0; i < 200; i += 1) {
|
|
353
|
+
const angle = Math.random() * Math.PI * 2;
|
|
354
|
+
const speed = 2 + Math.random() * 8;
|
|
355
|
+
|
|
356
|
+
particles.push({
|
|
357
|
+
x: canvasData.x,
|
|
358
|
+
y: canvasData.y,
|
|
359
|
+
vx: Math.cos(angle) * speed,
|
|
360
|
+
vy: Math.sin(angle) * speed,
|
|
361
|
+
size: 2 + Math.random() * 4,
|
|
362
|
+
life: 80,
|
|
363
|
+
startColor: "#48d6c2",
|
|
364
|
+
endColor: "#ffffff",
|
|
365
|
+
textureType: "star",
|
|
366
|
+
rotationVelocity: 0.03,
|
|
367
|
+
secondaryEligible: false
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return particles;
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### 运行时开启或关闭
|
|
377
|
+
|
|
378
|
+
```js
|
|
379
|
+
fireworks.setAdvancedMode(true);
|
|
380
|
+
fireworks.setAdvancedMode(false);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
同时传入新的粒子生成函数:
|
|
384
|
+
|
|
385
|
+
```js
|
|
386
|
+
fireworks.setAdvancedMode(true, function createParticles(canvasData) {
|
|
387
|
+
return [];
|
|
388
|
+
});
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
只替换粒子生成函数,不改变高级模式开关:
|
|
392
|
+
|
|
393
|
+
```js
|
|
394
|
+
fireworks.setParticleCreator(function createParticles(canvasData) {
|
|
395
|
+
return [];
|
|
396
|
+
});
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### 页面脚本输入框写法
|
|
400
|
+
|
|
401
|
+
项目示例页面右侧的“高级脚本”输入框要求写完整函数:
|
|
402
|
+
|
|
403
|
+
```js
|
|
404
|
+
function createParticles(canvasData) {
|
|
405
|
+
const particles = [];
|
|
406
|
+
const count = 360;
|
|
407
|
+
|
|
408
|
+
for (let i = 0; i < count; i += 1) {
|
|
409
|
+
const angle = (i / count) * Math.PI * 2;
|
|
410
|
+
const speed = 3 + Math.random() * 6;
|
|
411
|
+
|
|
412
|
+
particles.push({
|
|
413
|
+
x: canvasData.x,
|
|
414
|
+
y: canvasData.y,
|
|
415
|
+
vx: Math.cos(angle) * speed,
|
|
416
|
+
vy: Math.sin(angle) * speed,
|
|
417
|
+
size: 2 + Math.random() * 5,
|
|
418
|
+
life: 90,
|
|
419
|
+
startColor: "#48d6c2",
|
|
420
|
+
endColor: "#ef476f",
|
|
421
|
+
textureType: "star",
|
|
422
|
+
rotationVelocity: 0.02,
|
|
423
|
+
secondaryEligible: false
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return particles;
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
注意:
|
|
432
|
+
|
|
433
|
+
- 必须声明名为 `createParticles` 的函数。
|
|
434
|
+
- 可以直接返回粒子数组,也可以返回 `{ config, particles }`。
|
|
435
|
+
- 返回数组时,数组元素是粒子对象。
|
|
436
|
+
- 返回 `{ config, particles }` 时,`config` 只作用于本次播放生成的粒子,不会修改全局配置面板。
|
|
437
|
+
- 高级脚本写好后,必须开启“高级模式”才会在发射时生效。
|
|
438
|
+
- 该脚本通过 `new Function` 编译执行,只适合本地或可信页面使用,不要让不可信用户提交脚本。
|
|
439
|
+
|
|
440
|
+
### 高级脚本携带本次播放配置
|
|
441
|
+
|
|
442
|
+
如果希望某一次自定义烟花使用独立的重力、拖尾、辉光、风场等全局参数,可以返回对象:
|
|
443
|
+
|
|
444
|
+
```js
|
|
445
|
+
function createParticles(canvasData) {
|
|
446
|
+
const particles = [];
|
|
447
|
+
|
|
448
|
+
for (let i = 0; i < 260; i += 1) {
|
|
449
|
+
const angle = (i / 260) * Math.PI * 2;
|
|
450
|
+
const speed = 3 + Math.random() * 6;
|
|
451
|
+
|
|
452
|
+
particles.push({
|
|
453
|
+
x: canvasData.x,
|
|
454
|
+
y: canvasData.y,
|
|
455
|
+
vx: Math.cos(angle) * speed,
|
|
456
|
+
vy: Math.sin(angle) * speed,
|
|
457
|
+
size: 2 + Math.random() * 4,
|
|
458
|
+
life: 90,
|
|
459
|
+
color: "#ffffff",
|
|
460
|
+
textureType: "star"
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
return {
|
|
465
|
+
config: {
|
|
466
|
+
gravity: 0.04,
|
|
467
|
+
damping: 0.99,
|
|
468
|
+
enableTrails: true,
|
|
469
|
+
fadeTrail: 0.08,
|
|
470
|
+
glowIntensity: 1.3,
|
|
471
|
+
flicker: true,
|
|
472
|
+
sizeEndMultiplier: 0.2,
|
|
473
|
+
colorShiftRate: 0.05,
|
|
474
|
+
windEnabled: true,
|
|
475
|
+
windX: 0.06,
|
|
476
|
+
windY: 0,
|
|
477
|
+
textureType: "star"
|
|
478
|
+
},
|
|
479
|
+
particles
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
这里的 `config` 是本次发射的局部配置:
|
|
485
|
+
|
|
486
|
+
- 会合并当前全局配置后用于本次粒子。
|
|
487
|
+
- 不会调用 `setConfig()`,也不会改右侧控制面板。
|
|
488
|
+
- 会跟随这些粒子后续更新和绘制,直到这些粒子消失。
|
|
489
|
+
- 二次爆炸产生的子粒子也会继承这份局部配置。
|
|
490
|
+
|
|
491
|
+
局部 `config` 适合覆盖这些运行时参数:
|
|
492
|
+
|
|
493
|
+
```js
|
|
494
|
+
{
|
|
495
|
+
gravity,
|
|
496
|
+
damping,
|
|
497
|
+
enableTrails,
|
|
498
|
+
fadeTrail,
|
|
499
|
+
glowIntensity,
|
|
500
|
+
flicker,
|
|
501
|
+
sizeEndMultiplier,
|
|
502
|
+
colorShiftRate,
|
|
503
|
+
windEnabled,
|
|
504
|
+
windX,
|
|
505
|
+
windY,
|
|
506
|
+
textureType,
|
|
507
|
+
enableSecondaryBurst,
|
|
508
|
+
secondaryBurstRatio
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
不建议把 `backgroundType`、`backgroundColor`、`autoLaunch`、`autoLaunchIntervalSeconds`、`autoInterval` 这类页面级设置放在局部 `config` 里;它们应继续通过 `fireworks.setConfig()` 设置。
|
|
513
|
+
|
|
514
|
+
## 7. canvasData 参数
|
|
515
|
+
|
|
516
|
+
高级脚本会接收 `canvasData`:
|
|
517
|
+
|
|
518
|
+
```js
|
|
519
|
+
{
|
|
520
|
+
canvas, // canvas DOM
|
|
521
|
+
ctx, // CanvasRenderingContext2D
|
|
522
|
+
x, // 本次发射目标 x
|
|
523
|
+
y, // 本次发射目标 y
|
|
524
|
+
width, // 当前画布 CSS 宽度
|
|
525
|
+
height, // 当前画布 CSS 高度
|
|
526
|
+
pixelRatio, // 像素比
|
|
527
|
+
config, // 当前配置快照
|
|
528
|
+
random // 工具函数 random(min, max)
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
示例:
|
|
533
|
+
|
|
534
|
+
```js
|
|
535
|
+
function createParticles(canvasData) {
|
|
536
|
+
const speed = canvasData.random(3, 9);
|
|
537
|
+
return [
|
|
538
|
+
{
|
|
539
|
+
x: canvasData.width / 2,
|
|
540
|
+
y: canvasData.height / 2,
|
|
541
|
+
vx: speed,
|
|
542
|
+
vy: -speed,
|
|
543
|
+
size: 5,
|
|
544
|
+
life: 100,
|
|
545
|
+
startColor: canvasData.config.colorStart,
|
|
546
|
+
endColor: canvasData.config.colorEnd
|
|
547
|
+
}
|
|
548
|
+
];
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
## 8. 自定义粒子字段
|
|
553
|
+
|
|
554
|
+
高级模式返回的 `particles` 数组里,每个粒子对象支持这些字段:
|
|
555
|
+
|
|
556
|
+
```js
|
|
557
|
+
{
|
|
558
|
+
x: 300, // 初始 x
|
|
559
|
+
y: 200, // 初始 y
|
|
560
|
+
vx: 4, // 水平速度
|
|
561
|
+
vy: -3, // 垂直速度
|
|
562
|
+
size: 4, // 初始大小
|
|
563
|
+
life: 90, // 生命周期
|
|
564
|
+
startColor: "#48d6c2", // 起始颜色
|
|
565
|
+
endColor: "#ef476f", // 结束颜色
|
|
566
|
+
color: "#ffffff", // 可选,同时作为 startColor/endColor 的简写
|
|
567
|
+
textureType: "star", // circle | square | star | heart
|
|
568
|
+
rotationVelocity: 0.02, // 旋转速度
|
|
569
|
+
secondaryEligible: false, // 是否允许二次爆炸
|
|
570
|
+
secondaryBurstConfig: null // 可选,二次爆炸覆盖配置;默认继承当前粒子效果
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
字段补全规则:
|
|
575
|
+
|
|
576
|
+
- 未传 `x/y` 时使用本次发射坐标。
|
|
577
|
+
- 未传 `vx/vy` 时默认为 `0`。
|
|
578
|
+
- 未传 `size/life` 时使用当前配置。
|
|
579
|
+
- 未传 `startColor/endColor` 时使用当前配置。
|
|
580
|
+
- 传了 `color` 但没传 `startColor/endColor` 时,会用 `color` 作为颜色。
|
|
581
|
+
- 未传 `textureType` 时使用当前配置。
|
|
582
|
+
- 未传 `rotationVelocity` 时根据当前 `rotationSpeed` 随机。
|
|
583
|
+
- `secondaryBurstConfig` 只影响该粒子的二次爆炸,并会强制关闭 `enableSecondaryBurst`,不会触发三次爆炸。
|
|
584
|
+
|
|
585
|
+
`secondaryBurstConfig` 只需要写要覆盖的字段,例如:
|
|
586
|
+
|
|
587
|
+
```js
|
|
588
|
+
{
|
|
589
|
+
secondaryEligible: true,
|
|
590
|
+
secondaryBurstConfig: {
|
|
591
|
+
particleCount: 36,
|
|
592
|
+
textureType: "star",
|
|
593
|
+
colorStart: "#ffffff",
|
|
594
|
+
colorEnd: "#48d6c2",
|
|
595
|
+
explosionShape: "ring"
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
## 9. 高级脚本示例:爱心爆炸
|
|
601
|
+
|
|
602
|
+
```js
|
|
603
|
+
function createParticles(canvasData) {
|
|
604
|
+
const particles = [];
|
|
605
|
+
const count = 260;
|
|
606
|
+
|
|
607
|
+
for (let i = 0; i < count; i += 1) {
|
|
608
|
+
const t = Math.random() * Math.PI * 2;
|
|
609
|
+
const hx = 16 * Math.pow(Math.sin(t), 3);
|
|
610
|
+
const hy = -(
|
|
611
|
+
13 * Math.cos(t) -
|
|
612
|
+
5 * Math.cos(2 * t) -
|
|
613
|
+
2 * Math.cos(3 * t) -
|
|
614
|
+
Math.cos(4 * t)
|
|
615
|
+
);
|
|
616
|
+
const length = Math.hypot(hx, hy) || 1;
|
|
617
|
+
const speed = 3 + Math.random() * 5;
|
|
618
|
+
|
|
619
|
+
particles.push({
|
|
620
|
+
x: canvasData.x + hx * 1.8,
|
|
621
|
+
y: canvasData.y + hy * 1.8,
|
|
622
|
+
vx: (hx / length) * speed,
|
|
623
|
+
vy: (hy / length) * speed,
|
|
624
|
+
size: 2 + Math.random() * 4,
|
|
625
|
+
life: 90 + Math.random() * 30,
|
|
626
|
+
startColor: "#ff4d6d",
|
|
627
|
+
endColor: "#ffd6e0",
|
|
628
|
+
textureType: "heart"
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
return particles;
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
## 10. 高级脚本示例:喷泉
|
|
637
|
+
|
|
638
|
+
```js
|
|
639
|
+
function createParticles(canvasData) {
|
|
640
|
+
const particles = [];
|
|
641
|
+
const count = 180;
|
|
642
|
+
|
|
643
|
+
for (let i = 0; i < count; i += 1) {
|
|
644
|
+
const angle = -Math.PI / 2 + (Math.random() - 0.5) * 0.75;
|
|
645
|
+
const speed = 5 + Math.random() * 8;
|
|
646
|
+
|
|
647
|
+
particles.push({
|
|
648
|
+
x: canvasData.x,
|
|
649
|
+
y: canvasData.y,
|
|
650
|
+
vx: Math.cos(angle) * speed,
|
|
651
|
+
vy: Math.sin(angle) * speed,
|
|
652
|
+
size: 2 + Math.random() * 3,
|
|
653
|
+
life: 70 + Math.random() * 40,
|
|
654
|
+
startColor: "#f7f3a1",
|
|
655
|
+
endColor: "#fca311",
|
|
656
|
+
textureType: "star"
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
return particles;
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
## 11. 事件与回调
|
|
665
|
+
|
|
666
|
+
初始化时可以传回调:
|
|
667
|
+
|
|
668
|
+
```js
|
|
669
|
+
const fireworks = SparkFireworks.create("fireworks", {
|
|
670
|
+
onFpsChange(fps) {
|
|
671
|
+
fpsLabel.textContent = `FPS ${fps}`;
|
|
672
|
+
},
|
|
673
|
+
onConfigChange(config) {
|
|
674
|
+
console.log(config);
|
|
675
|
+
},
|
|
676
|
+
onLowFps(config) {
|
|
677
|
+
console.warn("low fps", config);
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
也可以监听内部事件:
|
|
683
|
+
|
|
684
|
+
```js
|
|
685
|
+
const off = fireworks.on("fps:change", (fps) => {
|
|
686
|
+
console.log(fps);
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
off();
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
## 12. 背景图片
|
|
693
|
+
|
|
694
|
+
通过文件对象设置背景图片:
|
|
695
|
+
|
|
696
|
+
```js
|
|
697
|
+
input.addEventListener("change", () => {
|
|
698
|
+
const file = input.files[0];
|
|
699
|
+
fireworks.setBackgroundImage(
|
|
700
|
+
file,
|
|
701
|
+
() => console.log("background loaded"),
|
|
702
|
+
(message) => console.error(message)
|
|
703
|
+
);
|
|
704
|
+
});
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
随后可以设置:
|
|
708
|
+
|
|
709
|
+
```js
|
|
710
|
+
fireworks.setConfig({
|
|
711
|
+
backgroundType: "image",
|
|
712
|
+
backgroundImageMode: "cover"
|
|
713
|
+
});
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
## 13. 销毁实例
|
|
717
|
+
|
|
718
|
+
页面卸载或不再使用时:
|
|
719
|
+
|
|
720
|
+
```js
|
|
721
|
+
fireworks.destroy();
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
它会取消动画帧,并移除内部绑定的事件监听。
|
|
725
|
+
|
|
726
|
+
## 14. 最小完整示例
|
|
727
|
+
|
|
728
|
+
```html
|
|
729
|
+
<canvas id="fireworks" style="width:100vw;height:100vh;display:block"></canvas>
|
|
730
|
+
<button id="launch">发射</button>
|
|
731
|
+
|
|
732
|
+
<script src="./dist-lib/spark-fireworks.umd.cjs"></script>
|
|
733
|
+
<script>
|
|
734
|
+
const canvas = document.getElementById("fireworks");
|
|
735
|
+
const fireworks = SparkFireworks.create(canvas, {
|
|
736
|
+
particleCount: 220,
|
|
737
|
+
colorStart: "#ffd166",
|
|
738
|
+
colorEnd: "#ef476f"
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
document.getElementById("launch").onclick = () => {
|
|
742
|
+
const rect = canvas.getBoundingClientRect();
|
|
743
|
+
fireworks.launch(
|
|
744
|
+
rect.width * (0.2 + Math.random() * 0.6),
|
|
745
|
+
rect.height * (0.15 + Math.random() * 0.45),
|
|
746
|
+
{ withShell: true }
|
|
747
|
+
);
|
|
748
|
+
};
|
|
749
|
+
</script>
|
|
750
|
+
```
|