fireworks-engine 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/LICENSE +24 -0
- package/README.md +297 -0
- package/index.d.ts +691 -0
- package/package.json +49 -0
- package/src/burstConfigBuilder.js +262 -0
- package/src/burstSpawn.js +764 -0
- package/src/colorUtils.js +80 -0
- package/src/configBuilder.js +300 -0
- package/src/defaults.js +87 -0
- package/src/index.js +13 -0
- package/src/mathResolvers.js +77 -0
- package/src/presets.js +811 -0
- package/src/renderer.js +863 -0
- package/src/rocketLaunch.js +791 -0
- package/src/runtime.js +796 -0
- package/src/runtimeCapabilities.js +7 -0
- package/src/runtimeLifecycle.js +330 -0
- package/src/update.js +307 -0
- package/src/valueNormalizers.js +160 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, coinexplain <coinexplain@gmail.com>
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
19
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
+
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
21
|
+
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND ON ANY
|
|
22
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT INCLUDING
|
|
23
|
+
NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
24
|
+
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# Fireworks Engine
|
|
2
|
+
|
|
3
|
+
Reusable canvas fireworks runtime for browser applications.
|
|
4
|
+
|
|
5
|
+
Live examples: <https://coinexplain.github.io/fireworks-engine/example/examples.html>
|
|
6
|
+
|
|
7
|
+
Fireworks Engine creates and manages a canvas, runs an animation loop, and exposes a small imperative API for launching rockets, bursts, confetti, and curated presets. It is framework-agnostic and can be used from plain JavaScript, React, Vue, or any UI shell that can provide a DOM container.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Install from npm:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install fireworks-engine
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or open the live examples: <https://coinexplain.github.io/fireworks-engine/example/examples.html>
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import { createFireworksEngine } from 'fireworks-engine';
|
|
23
|
+
|
|
24
|
+
const fireworks = createFireworksEngine({
|
|
25
|
+
canvas: {
|
|
26
|
+
appendTarget: document.body,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
fireworks.startPreset('base');
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
For a one-shot launch from a button:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import { createFireworksEngine } from 'fireworks-engine';
|
|
37
|
+
|
|
38
|
+
const fireworks = createFireworksEngine({
|
|
39
|
+
canvas: {
|
|
40
|
+
appendTarget: document.body,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
button.addEventListener('click', () => {
|
|
45
|
+
fireworks.boom(window.innerWidth * 0.5, window.innerHeight * 0.5);
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Always call `destroy()` when the owning UI unmounts.
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
fireworks.destroy();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Public API
|
|
56
|
+
|
|
57
|
+
Primary exports:
|
|
58
|
+
|
|
59
|
+
- `FireworksEngine`
|
|
60
|
+
- `createFireworksEngine(options?)`
|
|
61
|
+
- `resolveFireworksEnginePreset(name?)`
|
|
62
|
+
- default export: `FireworksEngine`
|
|
63
|
+
|
|
64
|
+
Instance methods:
|
|
65
|
+
|
|
66
|
+
- `start(config?)` starts a scheduled effect.
|
|
67
|
+
- `startPreset(name?)` starts one of the engine presets.
|
|
68
|
+
- `boom(x, y, options?)` launches a rocket toward a target point.
|
|
69
|
+
- `burst(x, y, options?)` creates a direct burst at a target point.
|
|
70
|
+
- `confetti(x, y, options?)` creates a forms-only confetti burst.
|
|
71
|
+
- `launchRocket(options?)` launches one or more rockets using runtime targeting.
|
|
72
|
+
- `launchRocketAt(x, y, options?)` launches a rocket toward a target point.
|
|
73
|
+
- `launchRocketFromTo(startX, startY, targetX, targetY, options?)` launches a rocket along an authored path.
|
|
74
|
+
- `launchPresetAt(name, x, y, options?)` launches a named launch preset at a point.
|
|
75
|
+
- `updateOptions(options?)` updates future launches without recreating the engine.
|
|
76
|
+
- `stop(clearCanvas?)` stops the loop and clears active particles.
|
|
77
|
+
- `destroy()` stops the loop and releases DOM/runtime resources.
|
|
78
|
+
|
|
79
|
+
Coordinates are canvas-local pixels. When the engine owns a full-page canvas, those coordinates line up with viewport pixels.
|
|
80
|
+
|
|
81
|
+
## Presets
|
|
82
|
+
|
|
83
|
+
Engine presets are used with `startPreset(...)` or `resolveFireworksEnginePreset(...)`:
|
|
84
|
+
|
|
85
|
+
- `base`
|
|
86
|
+
- `rocket`
|
|
87
|
+
- `cascade`
|
|
88
|
+
- `finale`
|
|
89
|
+
|
|
90
|
+
Launch presets are used with `launchPresetAt(...)`:
|
|
91
|
+
|
|
92
|
+
- `button-click`
|
|
93
|
+
- `success-burst`
|
|
94
|
+
- `win-celebration`
|
|
95
|
+
- `achievement-unlock`
|
|
96
|
+
- `confetti-pop`
|
|
97
|
+
- `purchase-success`
|
|
98
|
+
- `victory-finale`
|
|
99
|
+
- `snowfall`
|
|
100
|
+
- `leaf-fall`
|
|
101
|
+
- `ambient-sparkle`
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
fireworks.startPreset('finale');
|
|
105
|
+
fireworks.launchPresetAt('confetti-pop', x, y);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Options
|
|
109
|
+
|
|
110
|
+
The public options are grouped by runtime area:
|
|
111
|
+
|
|
112
|
+
- `canvas`: canvas ownership and sizing.
|
|
113
|
+
- `runtime`: injected DOM, timers, animation frame, clock, and reduced-motion hooks.
|
|
114
|
+
- `performance`: queue throttling and render pressure thresholds.
|
|
115
|
+
- `rocket`: rocket trail, color, speed, duration, and cascade behavior.
|
|
116
|
+
- `rocketTailEmbers`: ember particles emitted by rockets.
|
|
117
|
+
- `burstForms`: circle, square, rectangle, glyph, and mixed form particles.
|
|
118
|
+
- `burstSparks`: spark trails and fade/spindle/uniform spark shapes.
|
|
119
|
+
- `burstCenterFlash`: radial center flash.
|
|
120
|
+
- `burstTwinkleCloud`: delayed twinkle particles around a burst.
|
|
121
|
+
|
|
122
|
+
Common launch tuning fields can be passed at engine creation, `start(...)`, `updateOptions(...)`, or individual launch calls:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
fireworks.burst(x, y, {
|
|
126
|
+
sizeScale: 1.2,
|
|
127
|
+
timeScale: 1.4,
|
|
128
|
+
burstForms: {
|
|
129
|
+
shape: 'circle|square',
|
|
130
|
+
count: 80,
|
|
131
|
+
spin: 0.3,
|
|
132
|
+
spinCoverage: 0.6,
|
|
133
|
+
spinDuration: 2,
|
|
134
|
+
spinPause: 2,
|
|
135
|
+
highlight: 0.25,
|
|
136
|
+
highlightWidth: 0.2,
|
|
137
|
+
wobble: 0.4,
|
|
138
|
+
},
|
|
139
|
+
burstSparks: {
|
|
140
|
+
shape: 'fade',
|
|
141
|
+
count: 60,
|
|
142
|
+
tailScale: 1.4,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Rocket cascade example:
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
fireworks.launchRocketAt(x, y, {
|
|
151
|
+
rocket: {
|
|
152
|
+
cascade: {
|
|
153
|
+
mode: 'rocket',
|
|
154
|
+
bursts: 4,
|
|
155
|
+
childBursts: 2,
|
|
156
|
+
delay: 160,
|
|
157
|
+
spreadX: 180,
|
|
158
|
+
spreadY: 220,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Canvas Ownership
|
|
165
|
+
|
|
166
|
+
If `canvas.appendTarget` is provided, the engine appends a managed canvas inside that element and sizes it to the element bounds.
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
const fireworks = createFireworksEngine({
|
|
170
|
+
canvas: {
|
|
171
|
+
appendTarget: document.querySelector('#fireworks-layer'),
|
|
172
|
+
maxDevicePixelRatio: 2,
|
|
173
|
+
zIndex: 20,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
If `appendTarget` is omitted, the engine resolves a root from `runtime.root`, `document.body`, or `document.documentElement` and mounts a fixed viewport canvas.
|
|
179
|
+
|
|
180
|
+
## Framework Usage
|
|
181
|
+
|
|
182
|
+
React example:
|
|
183
|
+
|
|
184
|
+
```jsx
|
|
185
|
+
import { useEffect, useRef } from 'react';
|
|
186
|
+
import { createFireworksEngine } from 'fireworks-engine';
|
|
187
|
+
|
|
188
|
+
export function FireworksLayer() {
|
|
189
|
+
const containerRef = useRef(null);
|
|
190
|
+
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (!containerRef.current) {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const fireworks = createFireworksEngine({
|
|
197
|
+
canvas: { appendTarget: containerRef.current },
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
fireworks.startPreset('base');
|
|
201
|
+
|
|
202
|
+
return () => {
|
|
203
|
+
fireworks.destroy();
|
|
204
|
+
};
|
|
205
|
+
}, []);
|
|
206
|
+
|
|
207
|
+
return <div ref={containerRef} style={{ position: 'fixed', inset: 0 }} />;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Vue example:
|
|
212
|
+
|
|
213
|
+
```vue
|
|
214
|
+
<script setup>
|
|
215
|
+
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
|
216
|
+
import { createFireworksEngine } from 'fireworks-engine';
|
|
217
|
+
|
|
218
|
+
const containerRef = ref(null);
|
|
219
|
+
let fireworks = null;
|
|
220
|
+
|
|
221
|
+
onMounted(() => {
|
|
222
|
+
fireworks = createFireworksEngine({
|
|
223
|
+
canvas: { appendTarget: containerRef.value },
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
fireworks.startPreset('base');
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
onBeforeUnmount(() => {
|
|
230
|
+
fireworks?.destroy();
|
|
231
|
+
fireworks = null;
|
|
232
|
+
});
|
|
233
|
+
</script>
|
|
234
|
+
|
|
235
|
+
<template>
|
|
236
|
+
<div ref="containerRef" style="position: fixed; inset: 0;" />
|
|
237
|
+
</template>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Examples
|
|
241
|
+
|
|
242
|
+
The npm package is intentionally core-only. Browser examples live in the repository:
|
|
243
|
+
|
|
244
|
+
- `example/minimal-usage.html` for the smallest browser integration.
|
|
245
|
+
- `example/examples.html` for an interactive examples gallery.
|
|
246
|
+
- `example/lab.html` for full effect tuning.
|
|
247
|
+
- `example/fireworks-engine-options-reference.html` for a generated options reference page.
|
|
248
|
+
- `example/scratch.html` for running standalone snippets.
|
|
249
|
+
|
|
250
|
+
Serve the repository with any static file server and open the example page you need.
|
|
251
|
+
|
|
252
|
+
## TypeScript
|
|
253
|
+
|
|
254
|
+
The package ships with `index.d.ts`.
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
import {
|
|
258
|
+
createFireworksEngine,
|
|
259
|
+
type FireworksEngineOptions,
|
|
260
|
+
} from 'fireworks-engine';
|
|
261
|
+
|
|
262
|
+
const options: FireworksEngineOptions = {
|
|
263
|
+
burstForms: {
|
|
264
|
+
shape: 'glyph',
|
|
265
|
+
glyph: '*',
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const fireworks = createFireworksEngine(options);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Reduced Motion
|
|
273
|
+
|
|
274
|
+
The runtime checks reduced-motion preferences before starting scheduled effects. You can override the check when embedding in a custom shell:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
const fireworks = createFireworksEngine({
|
|
278
|
+
runtime: {
|
|
279
|
+
prefersReducedMotion: () => false,
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Development
|
|
285
|
+
|
|
286
|
+
```sh
|
|
287
|
+
npm run smoke
|
|
288
|
+
npm run typecheck
|
|
289
|
+
npm test
|
|
290
|
+
npm pack --dry-run
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The public npm package includes the core runtime, type declarations, README, and license. Repository-local planning docs and development tests are intentionally not part of the published package.
|
|
294
|
+
|
|
295
|
+
## License
|
|
296
|
+
|
|
297
|
+
BSD-2-Clause
|