@tsparticles/plugin-emitters
Version:
tsParticles emitters plugin
899 lines (869 loc) • 41 kB
JavaScript
(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
/* Plugin v4.3.2 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tsparticles/plugin-interactivity'), require('@tsparticles/engine')) :
typeof define === 'function' && define.amd ? define(['exports', '@tsparticles/plugin-interactivity', '@tsparticles/engine'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.plugins = global.__tsParticlesInternals.plugins || {}, global.__tsParticlesInternals.plugins.emitters = global.__tsParticlesInternals.plugins.emitters || {}), global.__tsParticlesInternals.plugins.interactivity, global.__tsParticlesInternals.engine));
})(this, (function (exports, pluginInteractivity, engine) { 'use strict';
class EmitterLife {
count;
delay;
duration;
wait = false;
load(data) {
if (engine.isNull(data)) {
return;
}
engine.loadProperty(this, "count", data.count);
engine.loadRangeProperty(this, "delay", data.delay);
engine.loadRangeProperty(this, "duration", data.duration);
engine.loadProperty(this, "wait", data.wait);
}
}
class EmitterRate {
delay = 0.1;
quantity = 1;
load(data) {
if (engine.isNull(data)) {
return;
}
engine.loadRangeProperty(this, "quantity", data.quantity);
engine.loadRangeProperty(this, "delay", data.delay);
}
}
class EmitterShapeReplace {
color = false;
opacity = false;
load(data) {
if (engine.isNull(data)) {
return;
}
engine.loadProperty(this, "color", data.color);
engine.loadProperty(this, "opacity", data.opacity);
}
}
class EmitterShape {
options = {};
replace = new EmitterShapeReplace();
type = "square";
load(data) {
if (engine.isNull(data)) {
return;
}
if (data.options !== undefined) {
this.options = engine.deepExtend({}, data.options ?? {});
}
this.replace.load(data.replace);
engine.loadProperty(this, "type", data.type);
}
}
class EmitterSize {
height = 0;
mode = engine.PixelMode.percent;
width = 0;
load(data) {
if (engine.isNull(data)) {
return;
}
engine.loadProperty(this, "mode", data.mode);
engine.loadProperty(this, "height", data.height);
engine.loadProperty(this, "width", data.width);
}
}
class EmitterSpawn {
fill;
stroke;
load(data) {
if (engine.isNull(data)) {
return;
}
if (data.fill) {
this.fill ??= new engine.Fill();
this.fill.load(data.fill);
}
if (data.stroke) {
this.stroke ??= new engine.Stroke();
this.stroke.load(data.stroke);
}
}
}
class Emitter {
autoPlay = true;
direction;
domId;
fill = true;
life = new EmitterLife();
name;
particles;
position;
rate = new EmitterRate();
shape = new EmitterShape();
size;
spawn = new EmitterSpawn();
spawnFillColor;
spawnStrokeColor;
startCount = 0;
load(data) {
if (engine.isNull(data)) {
return;
}
engine.loadProperty(this, "autoPlay", data.autoPlay);
if (data.size !== undefined) {
this.size ??= new EmitterSize();
this.size.load(data.size);
}
engine.loadProperty(this, "direction", data.direction);
engine.loadProperty(this, "domId", data.domId);
engine.loadProperty(this, "fill", data.fill);
this.life.load(data.life);
engine.loadProperty(this, "name", data.name);
this.particles = engine.executeOnSingleOrMultiple(data.particles, particles => {
return engine.deepExtend({}, particles);
});
this.rate.load(data.rate);
this.shape.load(data.shape);
this.spawn.load(data.spawn);
if (data.position !== undefined) {
this.position = {};
if (data.position.x !== undefined) {
this.position.x = engine.setRangeValue(data.position.x);
}
if (data.position.y !== undefined) {
this.position.y = engine.setRangeValue(data.position.y);
}
}
if (data.spawnFillColor !== undefined) {
this.spawnFillColor ??= new engine.AnimatableColor();
this.spawnFillColor.load(data.spawnFillColor);
}
if (data.spawnStrokeColor !== undefined) {
this.spawnStrokeColor ??= new engine.AnimatableColor();
this.spawnStrokeColor.load(data.spawnStrokeColor);
}
engine.loadProperty(this, "startCount", data.startCount);
}
}
const defaultRandomOptions = {
count: 1,
enable: true,
};
const emittersMode = "emitters";
class EmittersInteractor extends pluginInteractivity.ExternalInteractorBase {
handleClickMode;
maxDistance;
#instancesManager;
constructor(instancesManager, container) {
super(container);
this.#instancesManager = instancesManager;
this.maxDistance = 0;
this.handleClickMode = (mode, interactivityData) => {
const container = this.container, options = container.actualOptions, modeEmitters = options.interactivity.modes.emitters;
if (!modeEmitters || mode !== emittersMode) {
return;
}
let emittersModeOptions;
if (engine.isArray(modeEmitters.value)) {
const minLength = 0, modeEmittersCount = modeEmitters.value.length;
if (modeEmittersCount > minLength && modeEmitters.random.enable) {
emittersModeOptions = [];
const usedIndexes = new Set();
for (let i = 0; i < modeEmitters.random.count; i++) {
const idx = Math.floor(engine.getRandom() * modeEmitters.value.length);
if (usedIndexes.has(idx) && usedIndexes.size < modeEmittersCount) {
i--;
continue;
}
usedIndexes.add(idx);
const selectedOptions = engine.itemFromArray(modeEmitters.value, idx);
if (!selectedOptions) {
continue;
}
emittersModeOptions.push(selectedOptions);
}
}
else {
emittersModeOptions = modeEmitters.value;
}
}
else {
emittersModeOptions = modeEmitters.value;
}
const emittersOptions = emittersModeOptions, ePosition = interactivityData.mouse.clickPosition;
void engine.executeOnSingleOrMultiple(emittersOptions, async (emitter) => {
await this.#instancesManager.addEmitter(this.container, emitter, ePosition);
});
};
}
clear() {
}
init() {
}
interact(_interactivityData, delta) {
for (const emitter of this.#instancesManager.getArray(this.container)) {
emitter.update(delta);
}
}
isEnabled(interactivityData, particle) {
const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity).events;
if (!mouse.clickPosition || !events.onClick.enable) {
return false;
}
return engine.isInArray(emittersMode, events.onClick.mode);
}
loadModeOptions(options, ...sources) {
options.emitters = {
random: defaultRandomOptions,
value: [],
};
for (const source of sources) {
if (!source?.emitters) {
continue;
}
if (engine.isArray(source.emitters)) {
for (const emitter of source.emitters) {
const tmp = new Emitter();
tmp.load(emitter);
options.emitters.value.push(tmp);
}
}
else if ("value" in source.emitters) {
const emitterModeOptions = source.emitters;
options.emitters.random.enable = emitterModeOptions.random?.enable ?? options.emitters.random.enable;
options.emitters.random.count = emitterModeOptions.random?.count ?? options.emitters.random.count;
if (engine.isArray(emitterModeOptions.value)) {
for (const emitter of emitterModeOptions.value) {
const tmp = new Emitter();
tmp.load(emitter);
options.emitters.value.push(tmp);
}
}
else {
const tmp = new Emitter();
tmp.load(emitterModeOptions.value);
options.emitters.value.push(tmp);
}
}
else {
const tmp = new Emitter();
tmp.load(source.emitters);
options.emitters.value.push(tmp);
}
}
}
removeEmitter(emitter) {
const index = this.#instancesManager.getArray(this.container).indexOf(emitter), minIndex = 0, deleteCount = 1;
if (index >= minIndex) {
this.#instancesManager.getArray(this.container).splice(index, deleteCount);
}
}
reset() {
}
}
async function addEmittersShapesManager(e) {
const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
pluginManager.emitterShapeManager ??= new ShapeManager();
pluginManager.addEmitterShapeGenerator ??= (name, generator) => {
pluginManager.emitterShapeManager?.addShapeGenerator(name, generator);
};
}
const instancesManagers = new WeakMap();
function getEmittersInstancesManager(e) {
const pluginManager = e.pluginManager;
let manager = instancesManagers.get(pluginManager);
if (!manager) {
manager = Promise.resolve().then(function () { return EmittersInstancesManager$1; })
.then(({ EmittersInstancesManager }) => new EmittersInstancesManager(pluginManager))
.catch((error) => {
instancesManagers.delete(pluginManager);
throw error;
});
instancesManagers.set(pluginManager, manager);
}
return manager;
}
class EmitterShapeBase {
fill;
options;
position;
size;
constructor(position, size, fill, options) {
this.position = position;
this.size = size;
this.fill = fill;
this.options = options;
}
resize(position, size) {
this.position = position;
this.size = size;
}
}
exports.EmitterClickMode = void 0;
(function (EmitterClickMode) {
EmitterClickMode["emitter"] = "emitter";
})(exports.EmitterClickMode || (exports.EmitterClickMode = {}));
async function loadEmittersInteraction(engine) {
engine.checkVersion("4.3.2");
await engine.pluginManager.register(async (e) => {
const instancesManager = await getEmittersInstancesManager(e);
pluginInteractivity.ensureInteractivityPluginLoaded(e);
await addEmittersShapesManager(e);
e.pluginManager.addInteractor?.("externalEmitters", container => {
return Promise.resolve(new EmittersInteractor(instancesManager, container));
});
});
}
class EmittersPlugin {
id = "emitters";
#instancesManager;
constructor(instancesManager) {
this.#instancesManager = instancesManager;
}
async getPlugin(container) {
const { EmittersPluginInstance } = await Promise.resolve().then(function () { return EmittersPluginInstance$1; });
return new EmittersPluginInstance(this.#instancesManager, container);
}
loadOptions(_container, options, source) {
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
return;
}
if (source?.emitters) {
options.emitters = engine.executeOnSingleOrMultiple(source.emitters, emitter => {
const tmp = new Emitter();
tmp.load(emitter);
return tmp;
});
}
}
needsPlugin(options) {
if (!options) {
return false;
}
const emitters = options.emitters;
return (engine.isArray(emitters) && !!emitters.length) || emitters !== undefined;
}
}
async function loadEmittersPluginSimple(engine) {
engine.checkVersion("4.3.2");
await engine.pluginManager.register(async (e) => {
const instancesManager = await getEmittersInstancesManager(e);
await addEmittersShapesManager(e);
e.pluginManager.addPlugin(new EmittersPlugin(instancesManager));
});
}
function ensureEmittersPluginLoaded(e) {
if (!e.pluginManager.addEmitterShapeGenerator) {
throw new Error("tsParticles Emitters Plugin is not loaded");
}
}
async function loadEmittersPlugin(engine) {
await loadEmittersPluginSimple(engine);
await loadEmittersInteraction(engine);
}
const globalObject = globalThis;
globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
globalObject.loadEmittersPlugin = loadEmittersPlugin;
const shapeGenerators = new Map();
class ShapeManager {
addShapeGenerator(name, generator) {
if (!this.getShapeGenerator(name)) {
shapeGenerators.set(name, generator);
}
}
getShapeGenerator(name) {
return shapeGenerators.get(name);
}
getSupportedShapeGenerators() {
return shapeGenerators.keys();
}
}
var ShapeManager$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
ShapeManager: ShapeManager
});
const defaultIndex = 0;
class EmittersInstancesManager {
#containerArrays;
#pluginManager;
constructor(pluginManager) {
this.#containerArrays = new Map();
this.#pluginManager = pluginManager;
}
async addEmitter(container, options, position) {
const emitterOptions = new Emitter();
emitterOptions.load(options);
const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
this.removeEmitter(container, emitter);
}, emitterOptions, position);
await emitter.init();
this.getArray(container).push(emitter);
return emitter;
}
clear(container) {
this.initContainer(container);
this.#containerArrays.set(container, []);
}
getArray(container) {
this.initContainer(container);
let array = this.#containerArrays.get(container);
if (!array) {
array = [];
this.#containerArrays.set(container, array);
}
return array;
}
initContainer(container) {
if (this.#containerArrays.has(container)) {
return;
}
this.#containerArrays.set(container, []);
container.getEmitter = (idxOrName) => {
const array = this.getArray(container);
return idxOrName === undefined || engine.isNumber(idxOrName)
? array[idxOrName ?? defaultIndex]
: array.find(t => t.name === idxOrName);
};
container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
container.removeEmitter = (idxOrName) => {
const emitter = container.getEmitter?.(idxOrName);
if (emitter) {
this.removeEmitter(container, emitter);
}
};
container.playEmitter = (idxOrName) => {
const emitter = container.getEmitter?.(idxOrName);
if (emitter) {
emitter.externalPlay();
}
};
container.pauseEmitter = (idxOrName) => {
const emitter = container.getEmitter?.(idxOrName);
if (emitter) {
emitter.externalPause();
}
};
}
removeEmitter(container, emitter) {
const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
if (index >= minIndex) {
this.getArray(container).splice(index, deleteCount);
}
}
}
var EmittersInstancesManager$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
EmittersInstancesManager: EmittersInstancesManager
});
class EmittersPluginInstance {
#container;
#instancesManager;
constructor(instancesManager, container) {
this.#instancesManager = instancesManager;
this.#container = container;
this.#instancesManager.initContainer(container);
}
async init() {
const emittersOptions = this.#container.actualOptions.emitters;
if (engine.isArray(emittersOptions)) {
for (const emitterOptions of emittersOptions) {
await this.#instancesManager.addEmitter(this.#container, emitterOptions);
}
}
else {
await this.#instancesManager.addEmitter(this.#container, emittersOptions);
}
}
pause() {
for (const emitter of this.#instancesManager.getArray(this.#container)) {
emitter.pause();
}
}
play() {
for (const emitter of this.#instancesManager.getArray(this.#container)) {
emitter.play();
}
}
resize() {
for (const emitter of this.#instancesManager.getArray(this.#container)) {
emitter.resize();
}
}
stop() {
this.#instancesManager.clear(this.#container);
}
update(delta) {
this.#instancesManager.getArray(this.#container).forEach(emitter => {
emitter.update(delta);
});
}
}
var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
EmittersPluginInstance: EmittersPluginInstance
});
const defaultLifeDelay = 0, minLifeCount = 0, defaultSpawnDelay = 0, defaultEmitDelay = 0, defaultLifeCount = -1, defaultColorAnimationFactor = 1, colorFactor = 3.6, defaultStrokeWidth = 1;
function setParticlesOptionsFillColor(particlesOptions, color, opacity, enable) {
const paint = (particlesOptions.paint ??= new engine.Paint());
paint.fill = {
color: engine.AnimatableColor.create(undefined, { value: color }),
enable,
opacity,
};
}
function setParticlesOptionsStrokeColor(particlesOptions, color, opacity, width) {
const paint = (particlesOptions.paint ??= new engine.Paint());
paint.stroke = {
color: engine.AnimatableColor.create(undefined, { value: color }),
opacity,
width,
};
}
class EmitterInstance {
fill;
name;
options;
position;
size;
spawnFillColor;
spawnFillEnabled;
spawnFillOpacity;
spawnStrokeColor;
spawnStrokeOpacity;
spawnStrokeWidth;
#container;
#currentDuration;
#currentEmitDelay;
#currentSpawnDelay;
#duration;
#emitDelay;
#firstSpawn;
#immortal;
#initialPosition;
#lifeCount;
#mutationObserver;
#particlesOptions;
#paused;
#pluginManager;
#removeCallback;
#resizeObserver;
#shape;
#size;
#spawnDelay;
#startParticlesAdded;
constructor(pluginManager, container, removeCallback, options, position) {
this.#pluginManager = pluginManager;
this.#container = container;
this.#removeCallback = removeCallback;
this.#currentDuration = 0;
this.#currentEmitDelay = 0;
this.#currentSpawnDelay = 0;
this.#initialPosition = position;
if (options instanceof Emitter) {
this.options = options;
}
else {
this.options = new Emitter();
this.options.load(options);
}
this.#spawnDelay = container.retina.reduceFactor
? (engine.getRangeValue(this.options.life.delay ?? defaultLifeDelay) * engine.millisecondsToSeconds) /
container.retina.reduceFactor
: Infinity;
this.position = this.#initialPosition ?? this.#calcPosition();
this.name = this.options.name;
this.fill = this.options.fill;
this.#firstSpawn = !this.options.life.wait;
this.#startParticlesAdded = false;
const particlesOptions = engine.deepExtend({}, this.options.particles);
particlesOptions.move ??= {};
particlesOptions.move.direction ??= this.options.direction;
if (this.options.spawn.fill?.color) {
this.spawnFillColor = engine.rangeColorToHsl(this.#pluginManager, this.options.spawn.fill.color);
}
if (this.options.spawn.stroke?.color) {
this.spawnStrokeColor = engine.rangeColorToHsl(this.#pluginManager, this.options.spawn.stroke.color);
}
this.#paused = !this.options.autoPlay;
this.#particlesOptions = particlesOptions;
this.#size = this.#calcSize();
this.size =
this.#size.mode === engine.PixelMode.percent
? {
width: (this.#size.width / engine.percentDenominator) * this.#container.canvas.size.width,
height: (this.#size.height / engine.percentDenominator) * this.#container.canvas.size.height,
}
: { width: this.#size.width, height: this.#size.height };
this.#lifeCount = this.options.life.count ?? defaultLifeCount;
this.#immortal = this.#lifeCount <= minLifeCount;
if (this.options.domId) {
const element = engine.safeDocument().getElementById(this.options.domId);
if (element) {
this.#mutationObserver = new MutationObserver(() => {
this.resize();
});
this.#resizeObserver = new ResizeObserver(() => {
this.resize();
});
this.#mutationObserver.observe(element, {
attributes: true,
attributeFilter: ["style", "width", "height"],
});
this.#resizeObserver.observe(element);
}
}
const shapeOptions = this.options.shape, shapeGenerator = this.#pluginManager.emitterShapeManager?.getShapeGenerator(shapeOptions.type);
if (shapeGenerator) {
this.#shape = shapeGenerator.generate(this.#container, this.position, this.size, this.fill, shapeOptions.options);
}
this.#container.dispatchEvent("emitterCreated", {
emitter: this,
});
this.play();
}
externalPause() {
this.#paused = true;
this.pause();
}
externalPlay() {
this.#paused = false;
this.play();
}
async init() {
await this.#shape?.init();
}
pause() {
if (this.#paused) {
return;
}
this.#emitDelay = undefined;
}
play() {
if (this.#paused) {
return;
}
if (!((this.#lifeCount > minLifeCount || this.#immortal || !this.options.life.count) &&
(this.#firstSpawn || this.#currentSpawnDelay >= (this.#spawnDelay ?? defaultSpawnDelay)))) {
return;
}
const container = this.#container;
if (this.#emitDelay === undefined) {
const delay = engine.getRangeValue(this.options.rate.delay);
this.#emitDelay = container.retina.reduceFactor
? (delay * engine.millisecondsToSeconds) / container.retina.reduceFactor
: Infinity;
}
if (this.#lifeCount > minLifeCount || this.#immortal) {
this.#prepareToDie();
}
}
resize() {
const initialPosition = this.#initialPosition, container = this.#container;
this.position =
initialPosition && engine.isPointInside(initialPosition, container.canvas.size, engine.Vector.origin)
? initialPosition
: this.#calcPosition();
this.#size = this.#calcSize();
this.size =
this.#size.mode === engine.PixelMode.percent
? {
width: (this.#size.width / engine.percentDenominator) * container.canvas.size.width,
height: (this.#size.height / engine.percentDenominator) * container.canvas.size.height,
}
: { width: this.#size.width, height: this.#size.height };
this.#shape?.resize(this.position, this.size);
}
update(delta) {
if (this.#paused) {
return;
}
const container = this.#container;
if (this.#firstSpawn) {
this.#firstSpawn = false;
this.#currentSpawnDelay = this.#spawnDelay ?? defaultSpawnDelay;
this.#currentEmitDelay = this.#emitDelay ?? defaultEmitDelay;
}
if (!this.#startParticlesAdded) {
this.#startParticlesAdded = true;
this.#emitParticles(this.options.startCount);
}
if (this.#duration !== undefined) {
this.#currentDuration += delta.value;
if (this.#currentDuration >= this.#duration) {
this.pause();
if (this.#spawnDelay !== undefined) {
this.#spawnDelay = undefined;
}
if (!this.#immortal) {
this.#lifeCount--;
}
if (this.#lifeCount > minLifeCount || this.#immortal) {
this.position = this.#calcPosition();
this.#shape?.resize(this.position, this.size);
this.#spawnDelay = container.retina.reduceFactor
? (engine.getRangeValue(this.options.life.delay ?? defaultLifeDelay) * engine.millisecondsToSeconds) /
container.retina.reduceFactor
: Infinity;
}
else {
this.#destroy();
}
this.#currentDuration -= this.#duration;
this.#duration = undefined;
}
}
if (this.#spawnDelay !== undefined) {
this.#currentSpawnDelay += delta.value;
if (this.#currentSpawnDelay >= this.#spawnDelay) {
this.#container.dispatchEvent("emitterPlay");
this.play();
this.#currentSpawnDelay -= this.#spawnDelay;
this.#spawnDelay = undefined;
}
}
if (this.#emitDelay !== undefined) {
this.#currentEmitDelay += delta.value;
if (this.#currentEmitDelay >= this.#emitDelay) {
this.#emit();
this.#currentEmitDelay -= this.#emitDelay;
}
}
}
#calcPosition() {
const container = this.#container;
if (this.options.domId) {
const element = engine.safeDocument().getElementById(this.options.domId);
if (element) {
const elRect = element.getBoundingClientRect(), pxRatio = container.retina.pixelRatio;
return {
x: (elRect.x + elRect.width * engine.half) * pxRatio,
y: (elRect.y + elRect.height * engine.half) * pxRatio,
};
}
}
return engine.calcPositionOrRandomFromSizeRanged({
size: container.canvas.size,
position: this.options.position,
});
}
#calcSize() {
const container = this.#container;
if (this.options.domId) {
const element = engine.safeDocument().getElementById(this.options.domId);
if (element) {
const elRect = element.getBoundingClientRect();
return {
width: elRect.width * container.retina.pixelRatio,
height: elRect.height * container.retina.pixelRatio,
mode: engine.PixelMode.precise,
};
}
}
return (this.options.size ??
(() => {
const size = new EmitterSize();
size.load({
height: 0,
mode: engine.PixelMode.percent,
width: 0,
});
return size;
})());
}
#destroy() {
this.#mutationObserver?.disconnect();
this.#mutationObserver = undefined;
this.#resizeObserver?.disconnect();
this.#resizeObserver = undefined;
this.#removeCallback(this);
this.#container.dispatchEvent("emitterDestroyed", {
emitter: this,
});
}
#emit() {
if (this.#paused) {
return;
}
const quantity = engine.getRangeValue(this.options.rate.quantity);
this.#emitParticles(quantity);
}
#emitParticles(quantity) {
const singleParticlesOptions = (engine.itemFromSingleOrMultiple(this.#particlesOptions) ??
{}), fillHslAnimation = this.options.spawn.fill?.color?.animation, fillEnabled = this.options.spawn.fill?.enable ?? !!this.options.spawn.fill?.color, fillOpacity = this.options.spawn.fill?.opacity === undefined
? engine.defaultOpacity
: engine.getRangeValue(this.options.spawn.fill.opacity), strokeHslAnimation = this.options.spawn.stroke?.color?.animation, strokeOpacity = this.options.spawn.stroke?.opacity === undefined
? engine.defaultOpacity
: engine.getRangeValue(this.options.spawn.stroke.opacity), strokeWidth = this.options.spawn.stroke?.width === undefined
? defaultStrokeWidth
: engine.getRangeValue(this.options.spawn.stroke.width), reduceFactor = this.#container.retina.reduceFactor, needsFillColorAnimation = !!fillHslAnimation, needsStrokeColorAnimation = !!strokeHslAnimation, needsShapeData = !!this.#shape, needsColorAnimation = needsFillColorAnimation || needsStrokeColorAnimation, needsCopy = needsColorAnimation || needsShapeData, maxValues = needsColorAnimation ? { h: engine.hMax, s: engine.sMax, l: engine.lMax } : null, shapeOptions = this.options.shape;
for (let i = 0; i < quantity * reduceFactor; i++) {
const particlesOptions = needsCopy
? engine.deepExtend({}, singleParticlesOptions)
: singleParticlesOptions;
this.spawnFillOpacity = fillOpacity;
this.spawnFillEnabled = fillEnabled;
this.spawnStrokeOpacity = strokeOpacity;
this.spawnStrokeWidth = strokeWidth;
if (this.spawnFillColor) {
if (fillHslAnimation && maxValues) {
this.spawnFillColor.h = this.#setColorAnimation(fillHslAnimation.h, this.spawnFillColor.h, maxValues.h, colorFactor);
this.spawnFillColor.s = this.#setColorAnimation(fillHslAnimation.s, this.spawnFillColor.s, maxValues.s);
this.spawnFillColor.l = this.#setColorAnimation(fillHslAnimation.l, this.spawnFillColor.l, maxValues.l);
}
setParticlesOptionsFillColor(particlesOptions, this.spawnFillColor, this.spawnFillOpacity, this.spawnFillEnabled);
}
if (this.spawnStrokeColor) {
if (strokeHslAnimation && maxValues) {
this.spawnStrokeColor.h = this.#setColorAnimation(strokeHslAnimation.h, this.spawnStrokeColor.h, maxValues.h, colorFactor);
this.spawnStrokeColor.s = this.#setColorAnimation(strokeHslAnimation.s, this.spawnStrokeColor.s, maxValues.s);
this.spawnStrokeColor.l = this.#setColorAnimation(strokeHslAnimation.l, this.spawnStrokeColor.l, maxValues.l);
}
setParticlesOptionsStrokeColor(particlesOptions, this.spawnStrokeColor, this.spawnStrokeOpacity, this.spawnStrokeWidth);
}
let position = this.position;
if (this.#shape) {
const shapePosData = this.#shape.randomPosition();
if (shapePosData) {
position = shapePosData.position;
const replaceData = shapeOptions.replace;
if (replaceData.color && shapePosData.color) {
setParticlesOptionsFillColor(particlesOptions, shapePosData.color, replaceData.opacity ? (shapePosData.opacity ?? engine.defaultOpacity) : engine.defaultOpacity, true);
}
}
else {
position = null;
}
}
if (position) {
this.#container.particles.addParticle(position, particlesOptions);
}
}
}
#prepareToDie() {
if (this.#paused) {
return;
}
const duration = this.options.life.duration !== undefined ? engine.getRangeValue(this.options.life.duration) : undefined, minDuration = 0, minLifeCount = 0;
if ((this.#lifeCount > minLifeCount || this.#immortal) && duration !== undefined && duration > minDuration) {
this.#duration = duration * engine.millisecondsToSeconds;
}
}
#setColorAnimation(animation, initValue, maxValue, factor = defaultColorAnimationFactor) {
const container = this.#container;
if (!animation.enable) {
return initValue;
}
const colorOffset = engine.randomInRangeValue(animation.offset), delay = engine.getRangeValue(this.options.rate.delay), emitFactor = container.retina.reduceFactor
? (delay * engine.millisecondsToSeconds) / container.retina.reduceFactor
: Infinity, colorSpeed = engine.getRangeValue(animation.speed);
return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
}
}
var EmitterInstance$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
EmitterInstance: EmitterInstance
});
exports.EmitterShapeBase = EmitterShapeBase;
exports.ensureEmittersPluginLoaded = ensureEmittersPluginLoaded;
exports.loadEmittersPlugin = loadEmittersPlugin;
}));
Object.assign(globalThis.window || globalThis, { loadEmittersPlugin: (globalThis.__tsParticlesInternals.plugins.emitters || {}).loadEmittersPlugin });
delete (globalThis.window || globalThis).tsparticlesInternalExports;