@tsparticles/plugin-emitters 3.0.3 → 3.2.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/113.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 113.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_emitters=this.webpackChunk_tsparticles_plugin_emitters||[]).push([[113],{113:(e,t,r)=>{r.d(t,{ShapeManager:()=>s});const a=new Map;class s{constructor(e){this._engine=e}addShapeGenerator(e,t){this.getShapeGenerator(e)||a.set(e,t)}getShapeGenerator(e){return a.get(e)}getSupportedShapeGenerators(){return a.keys()}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Emitters Plugin v3.2.0 by Matteo Bruni */
package/927.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 927.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_emitters=this.webpackChunk_tsparticles_plugin_emitters||[]).push([[927],{927:(t,i,s)=>{s.d(i,{EmitterInstance:()=>r});var e=s(533),n=s(177),o=s(518);function a(t,i){t.color?t.color.value=i:t.color={value:i}}class r{constructor(t,i,s,o,a){this.emitters=i,this.container=s,this._destroy=()=>{this._mutationObserver?.disconnect(),this._mutationObserver=void 0,this._resizeObserver?.disconnect(),this._resizeObserver=void 0,this.emitters.removeEmitter(this),this._engine.dispatchEvent("emitterDestroyed",{container:this.container,data:{emitter:this}})},this._prepareToDie=()=>{if(this._paused)return;const t=void 0!==this.options.life?.duration?(0,e.getRangeValue)(this.options.life.duration):void 0;this.container.retina.reduceFactor&&(this._lifeCount>0||this._immortal)&&void 0!==t&&t>0&&(this._duration=t*e.millisecondsToSeconds)},this._setColorAnimation=(t,i,s,n=1)=>{const o=this.container;if(!t.enable)return i;const a=(0,e.randomInRange)(t.offset),r=(0,e.getRangeValue)(this.options.rate.delay)*e.millisecondsToSeconds/o.retina.reduceFactor;return(i+(0,e.getRangeValue)(t.speed??0)*o.fpsLimit/r+a*n)%s},this._engine=t,this._currentDuration=0,this._currentEmitDelay=0,this._currentSpawnDelay=0,this._initialPosition=a,o instanceof n.Emitter?this.options=o:(this.options=new n.Emitter,this.options.load(o)),this._spawnDelay=(0,e.getRangeValue)(this.options.life.delay??0)*e.millisecondsToSeconds/this.container.retina.reduceFactor,this.position=this._initialPosition??this._calcPosition(),this.name=this.options.name,this.fill=this.options.fill,this._firstSpawn=!this.options.life.wait,this._startParticlesAdded=!1;let r=(0,e.deepExtend)({},this.options.particles);if(r??={},r.move??={},r.move.direction??=this.options.direction,this.options.spawnColor&&(this.spawnColor=(0,e.rangeColorToHsl)(this.options.spawnColor)),this._paused=!this.options.autoPlay,this._particlesOptions=r,this._size=this._calcSize(),this.size=(0,e.getSize)(this._size,this.container.canvas.size),this._lifeCount=this.options.life.count??-1,this._immortal=this._lifeCount<=0,this.options.domId){const t=document.getElementById(this.options.domId);t&&(this._mutationObserver=new MutationObserver((()=>{this.resize()})),this._resizeObserver=new ResizeObserver((()=>{this.resize()})),this._mutationObserver.observe(t,{attributes:!0,attributeFilter:["style","width","height"]}),this._resizeObserver.observe(t))}const h=this.options.shape,l=this._engine.emitterShapeManager?.getShapeGenerator(h.type);l&&(this._shape=l.generate(this.position,this.size,this.fill,h.options)),this._engine.dispatchEvent("emitterCreated",{container:s,data:{emitter:this}}),this.play()}externalPause(){this._paused=!0,this.pause()}externalPlay(){this._paused=!1,this.play()}async init(){await(this._shape?.init())}pause(){this._paused||delete this._emitDelay}play(){if(!this._paused&&this.container.retina.reduceFactor&&(this._lifeCount>0||this._immortal||!this.options.life.count)&&(this._firstSpawn||this._currentSpawnDelay>=(this._spawnDelay??0))){if(void 0===this._emitDelay){const t=(0,e.getRangeValue)(this.options.rate.delay);this._emitDelay=t*e.millisecondsToSeconds/this.container.retina.reduceFactor}(this._lifeCount>0||this._immortal)&&this._prepareToDie()}}resize(){const t=this._initialPosition;this.position=t&&(0,e.isPointInside)(t,this.container.canvas.size,e.Vector.origin)?t:this._calcPosition(),this._size=this._calcSize(),this.size=(0,e.getSize)(this._size,this.container.canvas.size),this._shape?.resize(this.position,this.size)}async update(t){this._paused||(this._firstSpawn&&(this._firstSpawn=!1,this._currentSpawnDelay=this._spawnDelay??0,this._currentEmitDelay=this._emitDelay??0),this._startParticlesAdded||(this._startParticlesAdded=!0,await this._emitParticles(this.options.startCount)),void 0!==this._duration&&(this._currentDuration+=t.value,this._currentDuration>=this._duration&&(this.pause(),void 0!==this._spawnDelay&&delete this._spawnDelay,this._immortal||this._lifeCount--,this._lifeCount>0||this._immortal?(this.position=this._calcPosition(),this._shape?.resize(this.position,this.size),this._spawnDelay=(0,e.getRangeValue)(this.options.life.delay??0)*e.millisecondsToSeconds/this.container.retina.reduceFactor):this._destroy(),this._currentDuration-=this._duration,delete this._duration)),void 0!==this._spawnDelay&&(this._currentSpawnDelay+=t.value,this._currentSpawnDelay>=this._spawnDelay&&(this._engine.dispatchEvent("emitterPlay",{container:this.container}),this.play(),this._currentSpawnDelay-=this._currentSpawnDelay,delete this._spawnDelay)),void 0!==this._emitDelay&&(this._currentEmitDelay+=t.value,this._currentEmitDelay>=this._emitDelay&&(await this._emit(),this._currentEmitDelay-=this._emitDelay)))}_calcPosition(){if(this.options.domId){const t=document.getElementById(this.options.domId);if(t){const i=t.getBoundingClientRect(),s=this.container.retina.pixelRatio;return{x:(i.x+.5*i.width)*s,y:(i.y+.5*i.height)*s}}}return(0,e.calcPositionOrRandomFromSizeRanged)({size:this.container.canvas.size,position:this.options.position})}_calcSize(){const t=this.container;if(this.options.domId){const i=document.getElementById(this.options.domId);if(i){const s=i.getBoundingClientRect();return{width:s.width*t.retina.pixelRatio,height:s.height*t.retina.pixelRatio,mode:"precise"}}}return this.options.size??(()=>{const t=new o.r;return t.load({height:0,mode:"percent",width:0}),t})()}async _emit(){if(this._paused)return;const t=(0,e.getRangeValue)(this.options.rate.quantity);await this._emitParticles(t)}async _emitParticles(t){const i=(0,e.itemFromSingleOrMultiple)(this._particlesOptions);for(let s=0;s<t;s++){const t=(0,e.deepExtend)({},i);if(this.spawnColor){const i=this.options.spawnColor?.animation;if(i){const t={h:360,s:100,l:100},s=3.6;this.spawnColor.h=this._setColorAnimation(i.h,this.spawnColor.h,t.h,s),this.spawnColor.s=this._setColorAnimation(i.s,this.spawnColor.s,t.s),this.spawnColor.l=this._setColorAnimation(i.l,this.spawnColor.l,t.l)}a(t,this.spawnColor)}const s=this.options.shape;let n=this.position;if(this._shape){const i=await this._shape.randomPosition();if(i){n=i.position;const e=s.replace;e.color&&i.color&&a(t,i.color),e.opacity&&(t.opacity?t.opacity.value=i.opacity:t.opacity={value:i.opacity})}else n=null}n&&await this.container.particles.addParticle(n,t)}}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Emitters Plugin v3.2.0 by Matteo Bruni */
package/964.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 964.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_emitters=this.webpackChunk_tsparticles_plugin_emitters||[]).push([[964],{964:(t,i,e)=>{e.d(i,{EmittersPlugin:()=>a});var o=e(533),s=e(177);class a{constructor(t){this._engine=t,this.id="emitters"}async getPlugin(t){const{Emitters:i}=await e.e(973).then(e.bind(e,973));return new i(this._engine,t)}loadOptions(t,i){if(!this.needsPlugin(t)&&!this.needsPlugin(i))return;i?.emitters&&(t.emitters=(0,o.executeOnSingleOrMultiple)(i.emitters,(t=>{const i=new s.Emitter;return i.load(t),i})));const e=i?.interactivity?.modes?.emitters;if(e)if((0,o.isArray)(e))t.interactivity.modes.emitters={random:{count:1,enable:!0},value:e.map((t=>{const i=new s.Emitter;return i.load(t),i}))};else{const i=e;if(void 0!==i.value){const e=1;if((0,o.isArray)(i.value))t.interactivity.modes.emitters={random:{count:i.random.count??e,enable:i.random.enable??!1},value:i.value.map((t=>{const i=new s.Emitter;return i.load(t),i}))};else{const o=new s.Emitter;o.load(i.value),t.interactivity.modes.emitters={random:{count:i.random.count??e,enable:i.random.enable??!1},value:o}}}else{(t.interactivity.modes.emitters={random:{count:1,enable:!1},value:new s.Emitter}).value.load(e)}}}needsPlugin(t){if(!t)return!1;const i=t.emitters;return(0,o.isArray)(i)&&!!i.length||void 0!==i||!!t.interactivity?.events?.onClick?.mode&&(0,o.isInArray)("emitter",t.interactivity.events.onClick.mode)}}},177:(t,i,e)=>{e.d(i,{Emitter:()=>d});var o=e(533);class s{constructor(){this.wait=!1}load(t){t&&(void 0!==t.count&&(this.count=t.count),void 0!==t.delay&&(this.delay=(0,o.setRangeValue)(t.delay)),void 0!==t.duration&&(this.duration=(0,o.setRangeValue)(t.duration)),void 0!==t.wait&&(this.wait=t.wait))}}class a{constructor(){this.quantity=1,this.delay=.1}load(t){void 0!==t&&(void 0!==t.quantity&&(this.quantity=(0,o.setRangeValue)(t.quantity)),void 0!==t.delay&&(this.delay=(0,o.setRangeValue)(t.delay)))}}class n{constructor(){this.color=!1,this.opacity=!1}load(t){t&&(void 0!==t.color&&(this.color=t.color),void 0!==t.opacity&&(this.opacity=t.opacity))}}class r{constructor(){this.options={},this.replace=new n,this.type="square"}load(t){t&&(void 0!==t.options&&(this.options=(0,o.deepExtend)({},t.options??{})),this.replace.load(t.replace),void 0!==t.type&&(this.type=t.type))}}var l=e(518);class d{constructor(){this.autoPlay=!0,this.fill=!0,this.life=new s,this.rate=new a,this.shape=new r,this.startCount=0}load(t){t&&(void 0!==t.autoPlay&&(this.autoPlay=t.autoPlay),void 0!==t.size&&(this.size||(this.size=new l.r),this.size.load(t.size)),void 0!==t.direction&&(this.direction=t.direction),this.domId=t.domId,void 0!==t.fill&&(this.fill=t.fill),this.life.load(t.life),this.name=t.name,this.particles=(0,o.executeOnSingleOrMultiple)(t.particles,(t=>(0,o.deepExtend)({},t))),this.rate.load(t.rate),this.shape.load(t.shape),void 0!==t.position&&(this.position={},void 0!==t.position.x&&(this.position.x=(0,o.setRangeValue)(t.position.x)),void 0!==t.position.y&&(this.position.y=(0,o.setRangeValue)(t.position.y))),void 0!==t.spawnColor&&(void 0===this.spawnColor&&(this.spawnColor=new o.AnimatableColor),this.spawnColor.load(t.spawnColor)),void 0!==t.startCount&&(this.startCount=t.startCount))}}},518:(t,i,e)=>{e.d(i,{r:()=>o});class o{constructor(){this.mode="percent",this.height=0,this.width=0}load(t){void 0!==t&&(void 0!==t.mode&&(this.mode=t.mode),void 0!==t.height&&(this.height=t.height),void 0!==t.width&&(this.width=t.width))}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Emitters Plugin v3.2.0 by Matteo Bruni */
package/973.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 973.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_emitters=this.webpackChunk_tsparticles_plugin_emitters||[]).push([[973],{973:(t,e,i)=>{i.d(e,{Emitters:()=>r});var s=i(533);class r{constructor(t,e){this.container=e,this._engine=t,this.array=[],this.emitters=[],this.interactivityEmitters={random:{count:1,enable:!1},value:[]};e.getEmitter=t=>void 0===t||(0,s.isNumber)(t)?this.array[t??0]:this.array.find((e=>e.name===t)),e.addEmitter=async(t,e)=>this.addEmitter(t,e),e.removeEmitter=t=>{const i=e.getEmitter(t);i&&this.removeEmitter(i)},e.playEmitter=t=>{const i=e.getEmitter(t);i&&i.externalPlay()},e.pauseEmitter=t=>{const i=e.getEmitter(t);i&&i.externalPause()}}async addEmitter(t,e){const{Emitter:s}=await Promise.resolve().then(i.bind(i,177)),{EmitterInstance:r}=await i.e(927).then(i.bind(i,927)),a=new s;a.load(t);const n=new r(this._engine,this,this.container,a,e);return await n.init(),this.array.push(n),n}handleClickMode(t){const e=this.emitters,i=this.interactivityEmitters;if("emitter"!==t)return;let r;if(i&&(0,s.isArray)(i.value)){const t=0;if(i.value.length>t&&i.random.enable){r=[];const t=[];for(let e=0;e<i.random.count;e++){const a=(0,s.arrayRandomIndex)(i.value);t.includes(a)&&t.length<i.value.length?e--:(t.push(a),r.push((0,s.itemFromArray)(i.value,a)))}}else r=i.value}else r=i?.value;const a=r??e,n=this.container.interactivity.mouse.clickPosition;(0,s.executeOnSingleOrMultiple)(a,(async t=>{await this.addEmitter(t,n)}))}async init(){if(this.emitters=this.container.actualOptions.emitters,this.interactivityEmitters=this.container.actualOptions.interactivity.modes.emitters,this.emitters)if((0,s.isArray)(this.emitters))for(const t of this.emitters)await this.addEmitter(t);else await this.addEmitter(this.emitters)}pause(){for(const t of this.array)t.pause()}play(){for(const t of this.array)t.play()}removeEmitter(t){const e=this.array.indexOf(t);e>=0&&this.array.splice(e,1)}resize(){for(const t of this.array)t.resize()}stop(){this.array=[]}async update(t){for(const e of this.array)await e.update(t)}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Emitters Plugin v3.2.0 by Matteo Bruni */
@@ -1,6 +1,7 @@
1
- import { Vector, calcPositionOrRandomFromSizeRanged, deepExtend, getRangeValue, getSize, isPointInside, itemFromSingleOrMultiple, randomInRange, rangeColorToHsl, } from "@tsparticles/engine";
1
+ import { Vector, calcPositionOrRandomFromSizeRanged, deepExtend, getRangeValue, getSize, isPointInside, itemFromSingleOrMultiple, millisecondsToSeconds, randomInRange, rangeColorToHsl, } from "@tsparticles/engine";
2
2
  import { Emitter } from "./Options/Classes/Emitter.js";
3
3
  import { EmitterSize } from "./Options/Classes/EmitterSize.js";
4
+ const half = 0.5, defaultLifeDelay = 0, minLifeCount = 0, defaultSpawnDelay = 0, defaultEmitDelay = 0, defaultLifeCount = -1, defaultColorAnimationFactor = 1;
4
5
  function setParticlesOptionsColor(particlesOptions, color) {
5
6
  if (particlesOptions.color) {
6
7
  particlesOptions.color.value = color;
@@ -32,21 +33,21 @@ export class EmitterInstance {
32
33
  if (this._paused) {
33
34
  return;
34
35
  }
35
- const duration = this.options.life?.duration !== undefined ? getRangeValue(this.options.life.duration) : undefined;
36
+ const duration = this.options.life?.duration !== undefined ? getRangeValue(this.options.life.duration) : undefined, minDuration = 0, minLifeCount = 0;
36
37
  if (this.container.retina.reduceFactor &&
37
- (this._lifeCount > 0 || this._immortal) &&
38
+ (this._lifeCount > minLifeCount || this._immortal) &&
38
39
  duration !== undefined &&
39
- duration > 0) {
40
- this._duration = duration * 1000;
40
+ duration > minDuration) {
41
+ this._duration = duration * millisecondsToSeconds;
41
42
  }
42
43
  };
43
- this._setColorAnimation = (animation, initValue, maxValue) => {
44
+ this._setColorAnimation = (animation, initValue, maxValue, factor = defaultColorAnimationFactor) => {
44
45
  const container = this.container;
45
46
  if (!animation.enable) {
46
47
  return initValue;
47
48
  }
48
- const colorOffset = randomInRange(animation.offset), delay = getRangeValue(this.options.rate.delay), emitFactor = (1000 * delay) / container.retina.reduceFactor, colorSpeed = getRangeValue(animation.speed ?? 0);
49
- return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * 3.6) % maxValue;
49
+ const colorOffset = randomInRange(animation.offset), delay = getRangeValue(this.options.rate.delay), emitFactor = (delay * millisecondsToSeconds) / container.retina.reduceFactor, defaultColorSpeed = 0, colorSpeed = getRangeValue(animation.speed ?? defaultColorSpeed);
50
+ return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
50
51
  };
51
52
  this._engine = engine;
52
53
  this._currentDuration = 0;
@@ -60,7 +61,9 @@ export class EmitterInstance {
60
61
  this.options = new Emitter();
61
62
  this.options.load(options);
62
63
  }
63
- this._spawnDelay = (getRangeValue(this.options.life.delay ?? 0) * 1000) / this.container.retina.reduceFactor;
64
+ this._spawnDelay =
65
+ (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds) /
66
+ this.container.retina.reduceFactor;
64
67
  this.position = this._initialPosition ?? this._calcPosition();
65
68
  this.name = this.options.name;
66
69
  this.fill = this.options.fill;
@@ -77,8 +80,8 @@ export class EmitterInstance {
77
80
  this._particlesOptions = particlesOptions;
78
81
  this._size = this._calcSize();
79
82
  this.size = getSize(this._size, this.container.canvas.size);
80
- this._lifeCount = this.options.life.count ?? -1;
81
- this._immortal = this._lifeCount <= 0;
83
+ this._lifeCount = this.options.life.count ?? defaultLifeCount;
84
+ this._immortal = this._lifeCount <= minLifeCount;
82
85
  if (this.options.domId) {
83
86
  const element = document.getElementById(this.options.domId);
84
87
  if (element) {
@@ -129,15 +132,15 @@ export class EmitterInstance {
129
132
  return;
130
133
  }
131
134
  if (!(this.container.retina.reduceFactor &&
132
- (this._lifeCount > 0 || this._immortal || !this.options.life.count) &&
133
- (this._firstSpawn || this._currentSpawnDelay >= (this._spawnDelay ?? 0)))) {
135
+ (this._lifeCount > minLifeCount || this._immortal || !this.options.life.count) &&
136
+ (this._firstSpawn || this._currentSpawnDelay >= (this._spawnDelay ?? defaultSpawnDelay)))) {
134
137
  return;
135
138
  }
136
139
  if (this._emitDelay === undefined) {
137
140
  const delay = getRangeValue(this.options.rate.delay);
138
- this._emitDelay = (1000 * delay) / this.container.retina.reduceFactor;
141
+ this._emitDelay = (delay * millisecondsToSeconds) / this.container.retina.reduceFactor;
139
142
  }
140
- if (this._lifeCount > 0 || this._immortal) {
143
+ if (this._lifeCount > minLifeCount || this._immortal) {
141
144
  this._prepareToDie();
142
145
  }
143
146
  }
@@ -157,8 +160,8 @@ export class EmitterInstance {
157
160
  }
158
161
  if (this._firstSpawn) {
159
162
  this._firstSpawn = false;
160
- this._currentSpawnDelay = this._spawnDelay ?? 0;
161
- this._currentEmitDelay = this._emitDelay ?? 0;
163
+ this._currentSpawnDelay = this._spawnDelay ?? defaultSpawnDelay;
164
+ this._currentEmitDelay = this._emitDelay ?? defaultEmitDelay;
162
165
  }
163
166
  if (!this._startParticlesAdded) {
164
167
  this._startParticlesAdded = true;
@@ -174,11 +177,12 @@ export class EmitterInstance {
174
177
  if (!this._immortal) {
175
178
  this._lifeCount--;
176
179
  }
177
- if (this._lifeCount > 0 || this._immortal) {
180
+ if (this._lifeCount > minLifeCount || this._immortal) {
178
181
  this.position = this._calcPosition();
179
182
  this._shape?.resize(this.position, this.size);
180
183
  this._spawnDelay =
181
- (getRangeValue(this.options.life.delay ?? 0) * 1000) / this.container.retina.reduceFactor;
184
+ (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds) /
185
+ this.container.retina.reduceFactor;
182
186
  }
183
187
  else {
184
188
  this._destroy();
@@ -201,19 +205,19 @@ export class EmitterInstance {
201
205
  if (this._emitDelay !== undefined) {
202
206
  this._currentEmitDelay += delta.value;
203
207
  if (this._currentEmitDelay >= this._emitDelay) {
204
- this._emit();
208
+ await this._emit();
205
209
  this._currentEmitDelay -= this._emitDelay;
206
210
  }
207
211
  }
208
212
  }
209
213
  _calcPosition() {
210
214
  if (this.options.domId) {
211
- const container = this.container, element = document.getElementById(this.options.domId);
215
+ const element = document.getElementById(this.options.domId);
212
216
  if (element) {
213
- const elRect = element.getBoundingClientRect();
217
+ const elRect = element.getBoundingClientRect(), pxRatio = this.container.retina.pixelRatio;
214
218
  return {
215
- x: (elRect.x + elRect.width / 2) * container.retina.pixelRatio,
216
- y: (elRect.y + elRect.height / 2) * container.retina.pixelRatio,
219
+ x: (elRect.x + elRect.width * half) * pxRatio,
220
+ y: (elRect.y + elRect.height * half) * pxRatio,
217
221
  };
218
222
  }
219
223
  }
@@ -260,9 +264,14 @@ export class EmitterInstance {
260
264
  if (this.spawnColor) {
261
265
  const hslAnimation = this.options.spawnColor?.animation;
262
266
  if (hslAnimation) {
263
- this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, 360);
264
- this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, 100);
265
- this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, 100);
267
+ const maxValues = {
268
+ h: 360,
269
+ s: 100,
270
+ l: 100,
271
+ }, colorFactor = 3.6;
272
+ this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, maxValues.h, colorFactor);
273
+ this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, maxValues.s);
274
+ this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, maxValues.l);
266
275
  }
267
276
  setParticlesOptionsColor(particlesOptions, this.spawnColor);
268
277
  }
@@ -292,7 +301,7 @@ export class EmitterInstance {
292
301
  }
293
302
  }
294
303
  if (position) {
295
- this.container.particles.addParticle(position, particlesOptions);
304
+ await this.container.particles.addParticle(position, particlesOptions);
296
305
  }
297
306
  }
298
307
  }
@@ -1,6 +1,4 @@
1
1
  import { arrayRandomIndex, executeOnSingleOrMultiple, isArray, isNumber, itemFromArray, } from "@tsparticles/engine";
2
- import { Emitter } from "./Options/Classes/Emitter.js";
3
- import { EmitterInstance } from "./EmitterInstance.js";
4
2
  export class Emitters {
5
3
  constructor(engine, container) {
6
4
  this.container = container;
@@ -14,8 +12,9 @@ export class Emitters {
14
12
  },
15
13
  value: [],
16
14
  };
15
+ const defaultIndex = 0;
17
16
  container.getEmitter = (idxOrName) => idxOrName === undefined || isNumber(idxOrName)
18
- ? this.array[idxOrName || 0]
17
+ ? this.array[idxOrName ?? defaultIndex]
19
18
  : this.array.find((t) => t.name === idxOrName);
20
19
  container.addEmitter = async (options, position) => this.addEmitter(options, position);
21
20
  container.removeEmitter = (idxOrName) => {
@@ -38,7 +37,7 @@ export class Emitters {
38
37
  };
39
38
  }
40
39
  async addEmitter(options, position) {
41
- const emitterOptions = new Emitter();
40
+ const { Emitter } = await import("./Options/Classes/Emitter.js"), { EmitterInstance } = await import("./EmitterInstance.js"), emitterOptions = new Emitter();
42
41
  emitterOptions.load(options);
43
42
  const emitter = new EmitterInstance(this._engine, this, this.container, emitterOptions, position);
44
43
  await emitter.init();
@@ -52,7 +51,8 @@ export class Emitters {
52
51
  }
53
52
  let emittersModeOptions;
54
53
  if (modeEmitters && isArray(modeEmitters.value)) {
55
- if (modeEmitters.value.length > 0 && modeEmitters.random.enable) {
54
+ const minLength = 0;
55
+ if (modeEmitters.value.length > minLength && modeEmitters.random.enable) {
56
56
  emittersModeOptions = [];
57
57
  const usedIndexes = [];
58
58
  for (let i = 0; i < modeEmitters.random.count; i++) {
@@ -73,8 +73,8 @@ export class Emitters {
73
73
  emittersModeOptions = modeEmitters?.value;
74
74
  }
75
75
  const emittersOptions = emittersModeOptions ?? emitterOptions, ePosition = this.container.interactivity.mouse.clickPosition;
76
- executeOnSingleOrMultiple(emittersOptions, (emitter) => {
77
- this.addEmitter(emitter, ePosition);
76
+ void executeOnSingleOrMultiple(emittersOptions, async (emitter) => {
77
+ await this.addEmitter(emitter, ePosition);
78
78
  });
79
79
  }
80
80
  async init() {
@@ -103,9 +103,9 @@ export class Emitters {
103
103
  }
104
104
  }
105
105
  removeEmitter(emitter) {
106
- const index = this.array.indexOf(emitter);
107
- if (index >= 0) {
108
- this.array.splice(index, 1);
106
+ const index = this.array.indexOf(emitter), minIndex = 0, deleteCount = 1;
107
+ if (index >= minIndex) {
108
+ this.array.splice(index, deleteCount);
109
109
  }
110
110
  }
111
111
  resize() {
@@ -0,0 +1,90 @@
1
+ import { executeOnSingleOrMultiple, isArray, isInArray, } from "@tsparticles/engine";
2
+ import { Emitter } from "./Options/Classes/Emitter.js";
3
+ export class EmittersPlugin {
4
+ constructor(engine) {
5
+ this._engine = engine;
6
+ this.id = "emitters";
7
+ }
8
+ async getPlugin(container) {
9
+ const { Emitters } = await import("./Emitters.js");
10
+ return new Emitters(this._engine, container);
11
+ }
12
+ loadOptions(options, source) {
13
+ if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
14
+ return;
15
+ }
16
+ if (source?.emitters) {
17
+ options.emitters = executeOnSingleOrMultiple(source.emitters, (emitter) => {
18
+ const tmp = new Emitter();
19
+ tmp.load(emitter);
20
+ return tmp;
21
+ });
22
+ }
23
+ const interactivityEmitters = source?.interactivity?.modes?.emitters;
24
+ if (interactivityEmitters) {
25
+ if (isArray(interactivityEmitters)) {
26
+ options.interactivity.modes.emitters = {
27
+ random: {
28
+ count: 1,
29
+ enable: true,
30
+ },
31
+ value: interactivityEmitters.map((s) => {
32
+ const tmp = new Emitter();
33
+ tmp.load(s);
34
+ return tmp;
35
+ }),
36
+ };
37
+ }
38
+ else {
39
+ const emitterMode = interactivityEmitters;
40
+ if (emitterMode.value !== undefined) {
41
+ const defaultCount = 1;
42
+ if (isArray(emitterMode.value)) {
43
+ options.interactivity.modes.emitters = {
44
+ random: {
45
+ count: emitterMode.random.count ?? defaultCount,
46
+ enable: emitterMode.random.enable ?? false,
47
+ },
48
+ value: emitterMode.value.map((s) => {
49
+ const tmp = new Emitter();
50
+ tmp.load(s);
51
+ return tmp;
52
+ }),
53
+ };
54
+ }
55
+ else {
56
+ const tmp = new Emitter();
57
+ tmp.load(emitterMode.value);
58
+ options.interactivity.modes.emitters = {
59
+ random: {
60
+ count: emitterMode.random.count ?? defaultCount,
61
+ enable: emitterMode.random.enable ?? false,
62
+ },
63
+ value: tmp,
64
+ };
65
+ }
66
+ }
67
+ else {
68
+ const emitterOptions = (options.interactivity.modes.emitters = {
69
+ random: {
70
+ count: 1,
71
+ enable: false,
72
+ },
73
+ value: new Emitter(),
74
+ });
75
+ emitterOptions.value.load(interactivityEmitters);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ needsPlugin(options) {
81
+ if (!options) {
82
+ return false;
83
+ }
84
+ const emitters = options.emitters;
85
+ return ((isArray(emitters) && !!emitters.length) ||
86
+ emitters !== undefined ||
87
+ (!!options.interactivity?.events?.onClick?.mode &&
88
+ isInArray("emitter", options.interactivity.events.onClick.mode)));
89
+ }
90
+ }
package/browser/index.js CHANGED
@@ -1,95 +1,6 @@
1
- import { executeOnSingleOrMultiple, isArray, isInArray, } from "@tsparticles/engine";
2
- import { Emitter } from "./Options/Classes/Emitter.js";
3
- import { Emitters } from "./Emitters.js";
4
- import { ShapeManager } from "./ShapeManager.js";
5
- class EmittersPlugin {
6
- constructor(engine) {
7
- this._engine = engine;
8
- this.id = "emitters";
9
- }
10
- getPlugin(container) {
11
- return new Emitters(this._engine, container);
12
- }
13
- loadOptions(options, source) {
14
- if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
15
- return;
16
- }
17
- if (source?.emitters) {
18
- options.emitters = executeOnSingleOrMultiple(source.emitters, (emitter) => {
19
- const tmp = new Emitter();
20
- tmp.load(emitter);
21
- return tmp;
22
- });
23
- }
24
- const interactivityEmitters = source?.interactivity?.modes?.emitters;
25
- if (interactivityEmitters) {
26
- if (isArray(interactivityEmitters)) {
27
- options.interactivity.modes.emitters = {
28
- random: {
29
- count: 1,
30
- enable: true,
31
- },
32
- value: interactivityEmitters.map((s) => {
33
- const tmp = new Emitter();
34
- tmp.load(s);
35
- return tmp;
36
- }),
37
- };
38
- }
39
- else {
40
- const emitterMode = interactivityEmitters;
41
- if (emitterMode.value !== undefined) {
42
- if (isArray(emitterMode.value)) {
43
- options.interactivity.modes.emitters = {
44
- random: {
45
- count: emitterMode.random.count ?? 1,
46
- enable: emitterMode.random.enable ?? false,
47
- },
48
- value: emitterMode.value.map((s) => {
49
- const tmp = new Emitter();
50
- tmp.load(s);
51
- return tmp;
52
- }),
53
- };
54
- }
55
- else {
56
- const tmp = new Emitter();
57
- tmp.load(emitterMode.value);
58
- options.interactivity.modes.emitters = {
59
- random: {
60
- count: emitterMode.random.count ?? 1,
61
- enable: emitterMode.random.enable ?? false,
62
- },
63
- value: tmp,
64
- };
65
- }
66
- }
67
- else {
68
- const emitterOptions = (options.interactivity.modes.emitters = {
69
- random: {
70
- count: 1,
71
- enable: false,
72
- },
73
- value: new Emitter(),
74
- });
75
- emitterOptions.value.load(interactivityEmitters);
76
- }
77
- }
78
- }
79
- }
80
- needsPlugin(options) {
81
- if (!options) {
82
- return false;
83
- }
84
- const emitters = options.emitters;
85
- return ((isArray(emitters) && !!emitters.length) ||
86
- emitters !== undefined ||
87
- (!!options.interactivity?.events?.onClick?.mode &&
88
- isInArray("emitter", options.interactivity.events.onClick.mode)));
89
- }
90
- }
91
1
  export async function loadEmittersPlugin(engine, refresh = true) {
92
2
  if (!engine.emitterShapeManager) {
3
+ const { ShapeManager } = await import("./ShapeManager.js");
93
4
  engine.emitterShapeManager = new ShapeManager(engine);
94
5
  }
95
6
  if (!engine.addEmitterShapeGenerator) {
@@ -97,7 +8,7 @@ export async function loadEmittersPlugin(engine, refresh = true) {
97
8
  engine.emitterShapeManager?.addShapeGenerator(name, generator);
98
9
  };
99
10
  }
100
- const plugin = new EmittersPlugin(engine);
11
+ const { EmittersPlugin } = await import("./EmittersPlugin.js"), plugin = new EmittersPlugin(engine);
101
12
  await engine.addPlugin(plugin, refresh);
102
13
  }
103
14
  export * from "./EmitterContainer.js";
@@ -4,6 +4,7 @@ exports.EmitterInstance = void 0;
4
4
  const engine_1 = require("@tsparticles/engine");
5
5
  const Emitter_js_1 = require("./Options/Classes/Emitter.js");
6
6
  const EmitterSize_js_1 = require("./Options/Classes/EmitterSize.js");
7
+ const half = 0.5, defaultLifeDelay = 0, minLifeCount = 0, defaultSpawnDelay = 0, defaultEmitDelay = 0, defaultLifeCount = -1, defaultColorAnimationFactor = 1;
7
8
  function setParticlesOptionsColor(particlesOptions, color) {
8
9
  if (particlesOptions.color) {
9
10
  particlesOptions.color.value = color;
@@ -35,21 +36,21 @@ class EmitterInstance {
35
36
  if (this._paused) {
36
37
  return;
37
38
  }
38
- const duration = this.options.life?.duration !== undefined ? (0, engine_1.getRangeValue)(this.options.life.duration) : undefined;
39
+ const duration = this.options.life?.duration !== undefined ? (0, engine_1.getRangeValue)(this.options.life.duration) : undefined, minDuration = 0, minLifeCount = 0;
39
40
  if (this.container.retina.reduceFactor &&
40
- (this._lifeCount > 0 || this._immortal) &&
41
+ (this._lifeCount > minLifeCount || this._immortal) &&
41
42
  duration !== undefined &&
42
- duration > 0) {
43
- this._duration = duration * 1000;
43
+ duration > minDuration) {
44
+ this._duration = duration * engine_1.millisecondsToSeconds;
44
45
  }
45
46
  };
46
- this._setColorAnimation = (animation, initValue, maxValue) => {
47
+ this._setColorAnimation = (animation, initValue, maxValue, factor = defaultColorAnimationFactor) => {
47
48
  const container = this.container;
48
49
  if (!animation.enable) {
49
50
  return initValue;
50
51
  }
51
- const colorOffset = (0, engine_1.randomInRange)(animation.offset), delay = (0, engine_1.getRangeValue)(this.options.rate.delay), emitFactor = (1000 * delay) / container.retina.reduceFactor, colorSpeed = (0, engine_1.getRangeValue)(animation.speed ?? 0);
52
- return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * 3.6) % maxValue;
52
+ const colorOffset = (0, engine_1.randomInRange)(animation.offset), delay = (0, engine_1.getRangeValue)(this.options.rate.delay), emitFactor = (delay * engine_1.millisecondsToSeconds) / container.retina.reduceFactor, defaultColorSpeed = 0, colorSpeed = (0, engine_1.getRangeValue)(animation.speed ?? defaultColorSpeed);
53
+ return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
53
54
  };
54
55
  this._engine = engine;
55
56
  this._currentDuration = 0;
@@ -63,7 +64,9 @@ class EmitterInstance {
63
64
  this.options = new Emitter_js_1.Emitter();
64
65
  this.options.load(options);
65
66
  }
66
- this._spawnDelay = ((0, engine_1.getRangeValue)(this.options.life.delay ?? 0) * 1000) / this.container.retina.reduceFactor;
67
+ this._spawnDelay =
68
+ ((0, engine_1.getRangeValue)(this.options.life.delay ?? defaultLifeDelay) * engine_1.millisecondsToSeconds) /
69
+ this.container.retina.reduceFactor;
67
70
  this.position = this._initialPosition ?? this._calcPosition();
68
71
  this.name = this.options.name;
69
72
  this.fill = this.options.fill;
@@ -80,8 +83,8 @@ class EmitterInstance {
80
83
  this._particlesOptions = particlesOptions;
81
84
  this._size = this._calcSize();
82
85
  this.size = (0, engine_1.getSize)(this._size, this.container.canvas.size);
83
- this._lifeCount = this.options.life.count ?? -1;
84
- this._immortal = this._lifeCount <= 0;
86
+ this._lifeCount = this.options.life.count ?? defaultLifeCount;
87
+ this._immortal = this._lifeCount <= minLifeCount;
85
88
  if (this.options.domId) {
86
89
  const element = document.getElementById(this.options.domId);
87
90
  if (element) {
@@ -132,15 +135,15 @@ class EmitterInstance {
132
135
  return;
133
136
  }
134
137
  if (!(this.container.retina.reduceFactor &&
135
- (this._lifeCount > 0 || this._immortal || !this.options.life.count) &&
136
- (this._firstSpawn || this._currentSpawnDelay >= (this._spawnDelay ?? 0)))) {
138
+ (this._lifeCount > minLifeCount || this._immortal || !this.options.life.count) &&
139
+ (this._firstSpawn || this._currentSpawnDelay >= (this._spawnDelay ?? defaultSpawnDelay)))) {
137
140
  return;
138
141
  }
139
142
  if (this._emitDelay === undefined) {
140
143
  const delay = (0, engine_1.getRangeValue)(this.options.rate.delay);
141
- this._emitDelay = (1000 * delay) / this.container.retina.reduceFactor;
144
+ this._emitDelay = (delay * engine_1.millisecondsToSeconds) / this.container.retina.reduceFactor;
142
145
  }
143
- if (this._lifeCount > 0 || this._immortal) {
146
+ if (this._lifeCount > minLifeCount || this._immortal) {
144
147
  this._prepareToDie();
145
148
  }
146
149
  }
@@ -160,8 +163,8 @@ class EmitterInstance {
160
163
  }
161
164
  if (this._firstSpawn) {
162
165
  this._firstSpawn = false;
163
- this._currentSpawnDelay = this._spawnDelay ?? 0;
164
- this._currentEmitDelay = this._emitDelay ?? 0;
166
+ this._currentSpawnDelay = this._spawnDelay ?? defaultSpawnDelay;
167
+ this._currentEmitDelay = this._emitDelay ?? defaultEmitDelay;
165
168
  }
166
169
  if (!this._startParticlesAdded) {
167
170
  this._startParticlesAdded = true;
@@ -177,11 +180,12 @@ class EmitterInstance {
177
180
  if (!this._immortal) {
178
181
  this._lifeCount--;
179
182
  }
180
- if (this._lifeCount > 0 || this._immortal) {
183
+ if (this._lifeCount > minLifeCount || this._immortal) {
181
184
  this.position = this._calcPosition();
182
185
  this._shape?.resize(this.position, this.size);
183
186
  this._spawnDelay =
184
- ((0, engine_1.getRangeValue)(this.options.life.delay ?? 0) * 1000) / this.container.retina.reduceFactor;
187
+ ((0, engine_1.getRangeValue)(this.options.life.delay ?? defaultLifeDelay) * engine_1.millisecondsToSeconds) /
188
+ this.container.retina.reduceFactor;
185
189
  }
186
190
  else {
187
191
  this._destroy();
@@ -204,19 +208,19 @@ class EmitterInstance {
204
208
  if (this._emitDelay !== undefined) {
205
209
  this._currentEmitDelay += delta.value;
206
210
  if (this._currentEmitDelay >= this._emitDelay) {
207
- this._emit();
211
+ await this._emit();
208
212
  this._currentEmitDelay -= this._emitDelay;
209
213
  }
210
214
  }
211
215
  }
212
216
  _calcPosition() {
213
217
  if (this.options.domId) {
214
- const container = this.container, element = document.getElementById(this.options.domId);
218
+ const element = document.getElementById(this.options.domId);
215
219
  if (element) {
216
- const elRect = element.getBoundingClientRect();
220
+ const elRect = element.getBoundingClientRect(), pxRatio = this.container.retina.pixelRatio;
217
221
  return {
218
- x: (elRect.x + elRect.width / 2) * container.retina.pixelRatio,
219
- y: (elRect.y + elRect.height / 2) * container.retina.pixelRatio,
222
+ x: (elRect.x + elRect.width * half) * pxRatio,
223
+ y: (elRect.y + elRect.height * half) * pxRatio,
220
224
  };
221
225
  }
222
226
  }
@@ -263,9 +267,14 @@ class EmitterInstance {
263
267
  if (this.spawnColor) {
264
268
  const hslAnimation = this.options.spawnColor?.animation;
265
269
  if (hslAnimation) {
266
- this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, 360);
267
- this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, 100);
268
- this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, 100);
270
+ const maxValues = {
271
+ h: 360,
272
+ s: 100,
273
+ l: 100,
274
+ }, colorFactor = 3.6;
275
+ this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, maxValues.h, colorFactor);
276
+ this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, maxValues.s);
277
+ this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, maxValues.l);
269
278
  }
270
279
  setParticlesOptionsColor(particlesOptions, this.spawnColor);
271
280
  }
@@ -295,7 +304,7 @@ class EmitterInstance {
295
304
  }
296
305
  }
297
306
  if (position) {
298
- this.container.particles.addParticle(position, particlesOptions);
307
+ await this.container.particles.addParticle(position, particlesOptions);
299
308
  }
300
309
  }
301
310
  }