UNPKG

@tsparticles/plugin-emitters

Version:

tsParticles emitters plugin

899 lines (869 loc) 41 kB
(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;