@tsparticles/fireworks
Version:
Easily create highly customizable particle animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.
284 lines (283 loc) • 9.33 kB
JavaScript
import { DestroyType, EventType, MoveDirection, OutMode, StartValueType, getRangeMax, getRangeMin, isNumber, isSsr, isString, setRangeValue, tsParticles, } from "@tsparticles/engine";
import { FireworkOptions } from "./FireworkOptions.js";
import { loadBasic } from "@tsparticles/basic";
import { loadDestroyUpdater } from "@tsparticles/updater-destroy";
import { loadEmittersPlugin } from "@tsparticles/plugin-emitters";
import { loadEmittersShapeSquare } from "@tsparticles/plugin-emitters-shape-square";
import { loadLifeUpdater } from "@tsparticles/updater-life";
import { loadRotateUpdater } from "@tsparticles/updater-rotate";
import { loadSoundsPlugin } from "@tsparticles/plugin-sounds";
import { loadTrailEffect } from "@tsparticles/effect-trail";
const minSplitCount = 2;
let initialized = false;
let initializing = false;
const explodeSoundCheck = (args) => {
const data = args.data;
return data.particle.shape === "circle" && !!data.particle.splitCount && data.particle.splitCount < minSplitCount;
};
class FireworksInstance {
constructor(container) {
this._container = container;
}
pause() {
this._container.pause();
}
play() {
this._container.play();
}
stop() {
this._container.stop();
}
}
async function initPlugins(engine) {
if (initialized) {
return;
}
if (initializing) {
return new Promise(resolve => {
const timeout = 100, interval = setInterval(() => {
if (!initialized) {
return;
}
clearInterval(interval);
resolve();
}, timeout);
});
}
initializing = true;
engine.checkVersion("3.9.1");
await loadEmittersPlugin(engine, false);
await loadEmittersShapeSquare(engine, false);
await loadSoundsPlugin(engine, false);
await loadRotateUpdater(engine, false);
await loadDestroyUpdater(engine, false);
await loadLifeUpdater(engine, false);
await loadTrailEffect(engine, false);
await loadBasic(engine, false);
initializing = false;
initialized = true;
}
function getOptions(options, canvas) {
const identity = 1;
return {
detectRetina: true,
background: {
color: options.background,
},
fullScreen: {
enable: !!canvas,
},
fpsLimit: 60,
emitters: {
direction: MoveDirection.top,
life: {
count: 0,
duration: 0.1,
delay: 0.1,
},
rate: {
delay: isNumber(options.rate)
? identity / options.rate
: { min: identity / getRangeMin(options.rate), max: identity / getRangeMax(options.rate) },
quantity: 1,
},
size: {
width: 100,
height: 0,
},
position: {
y: 100,
x: 50,
},
},
particles: {
number: {
value: 0,
},
color: {
value: "#fff",
},
destroy: {
mode: "split",
bounds: {
top: setRangeValue(options.minHeight),
},
split: {
sizeOffset: false,
count: 1,
factor: {
value: 0.333333,
},
rate: {
value: options.splitCount,
},
colorOffset: {
s: options.saturation,
l: options.brightness,
},
particles: {
color: {
value: options.colors,
},
number: {
value: 0,
},
opacity: {
value: {
min: 0.1,
max: 1,
},
animation: {
enable: true,
speed: 1,
sync: false,
startValue: StartValueType.max,
destroy: DestroyType.min,
},
},
effect: {
type: "trail",
options: {
trail: {
length: {
min: 5,
max: 10,
},
},
},
},
shape: {
type: "circle",
},
size: {
value: { min: 1, max: 2 },
animation: {
enable: true,
speed: 5,
count: 1,
sync: false,
startValue: StartValueType.min,
destroy: DestroyType.none,
},
},
life: {
count: 1,
duration: {
value: {
min: 0.25,
max: 0.5,
},
},
},
move: {
decay: { min: 0.05, max: 0.1 },
enable: true,
gravity: {
enable: true,
inverse: false,
acceleration: setRangeValue(options.gravity),
},
speed: setRangeValue(options.speed),
direction: "none",
outModes: OutMode.destroy,
},
},
},
},
life: {
count: 1,
},
effect: {
type: "trail",
options: {
trail: {
length: {
min: 10,
max: 30,
},
minWidth: 1,
maxWidth: 1,
},
},
},
shape: {
type: "circle",
},
size: {
value: 1,
},
opacity: {
value: 0.5,
},
rotate: {
path: true,
},
move: {
enable: true,
gravity: {
acceleration: 15,
enable: true,
inverse: true,
maxSpeed: 100,
},
speed: {
min: 10,
max: 20,
},
outModes: {
default: OutMode.destroy,
top: OutMode.none,
},
},
},
sounds: {
enable: options.sounds,
events: [
{
event: EventType.particleRemoved,
filter: explodeSoundCheck,
audio: [
"https://particles.js.org/audio/explosion0.mp3",
"https://particles.js.org/audio/explosion1.mp3",
"https://particles.js.org/audio/explosion2.mp3",
],
},
],
volume: 50,
},
};
}
async function getFireworksInstance(id, sourceOptions, canvas) {
await initPlugins(tsParticles);
const options = new FireworkOptions();
options.load(sourceOptions);
const particlesOptions = getOptions(options, canvas), container = await tsParticles.load({ id, element: canvas, options: particlesOptions });
if (!container) {
return;
}
return new FireworksInstance(container);
}
export async function fireworks(idOrOptions, sourceOptions) {
let id;
let options;
if (isString(idOrOptions)) {
id = idOrOptions;
options = sourceOptions ?? {};
}
else {
id = "fireworks";
options = idOrOptions ?? {};
}
return getFireworksInstance(id, options);
}
fireworks.create = async (canvas, options) => {
const id = canvas.id ?? "fireworks";
return getFireworksInstance(id, options ?? {}, canvas);
};
fireworks.init = async () => {
await initPlugins(tsParticles);
};
fireworks.version = "3.9.1";
if (!isSsr()) {
window.fireworks = fireworks;
}