@tsparticles/engine 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.
Files changed (156) hide show
  1. package/373.min.js +2 -0
  2. package/373.min.js.LICENSE.txt +1 -0
  3. package/438.min.js +2 -0
  4. package/438.min.js.LICENSE.txt +1 -0
  5. package/README.md +337 -216
  6. package/browser/Core/Canvas.js +102 -49
  7. package/browser/Core/Container.js +53 -41
  8. package/browser/Core/Engine.js +47 -32
  9. package/browser/Core/Particle.js +46 -48
  10. package/browser/Core/Particles.js +70 -57
  11. package/browser/Core/Retina.js +5 -4
  12. package/browser/Core/Utils/Circle.js +4 -3
  13. package/browser/Core/Utils/Constants.js +3 -0
  14. package/browser/Core/Utils/EventListeners.js +19 -16
  15. package/browser/Core/Utils/ExternalInteractorBase.js +1 -1
  16. package/browser/Core/Utils/InteractionManager.js +17 -8
  17. package/browser/Core/Utils/ParticlesInteractorBase.js +1 -1
  18. package/browser/Core/Utils/QuadTree.js +5 -3
  19. package/browser/Core/Utils/Vector.js +7 -2
  20. package/browser/Core/Utils/Vector3d.js +14 -9
  21. package/browser/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  22. package/browser/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  23. package/browser/Options/Classes/ManualParticle.js +3 -2
  24. package/browser/Options/Classes/Options.js +3 -0
  25. package/browser/Utils/CanvasUtils.js +50 -40
  26. package/browser/Utils/ColorUtils.js +124 -45
  27. package/browser/Utils/EventDispatcher.js +6 -5
  28. package/browser/Utils/HslColorManager.js +5 -5
  29. package/browser/Utils/NumberUtils.js +35 -23
  30. package/browser/Utils/RgbColorManager.js +5 -5
  31. package/browser/Utils/Utils.js +102 -19
  32. package/cjs/Core/Canvas.js +102 -49
  33. package/cjs/Core/Container.js +53 -41
  34. package/cjs/Core/Engine.js +70 -32
  35. package/cjs/Core/Particle.js +45 -47
  36. package/cjs/Core/Particles.js +93 -57
  37. package/cjs/Core/Retina.js +5 -4
  38. package/cjs/Core/Utils/Circle.js +4 -3
  39. package/cjs/Core/Utils/Constants.js +4 -1
  40. package/cjs/Core/Utils/EventListeners.js +18 -15
  41. package/cjs/Core/Utils/ExternalInteractorBase.js +1 -1
  42. package/cjs/Core/Utils/InteractionManager.js +17 -8
  43. package/cjs/Core/Utils/ParticlesInteractorBase.js +1 -1
  44. package/cjs/Core/Utils/QuadTree.js +5 -3
  45. package/cjs/Core/Utils/Vector.js +7 -2
  46. package/cjs/Core/Utils/Vector3d.js +14 -9
  47. package/cjs/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  48. package/cjs/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  49. package/cjs/Options/Classes/ManualParticle.js +3 -2
  50. package/cjs/Options/Classes/Options.js +3 -0
  51. package/cjs/Utils/CanvasUtils.js +50 -40
  52. package/cjs/Utils/ColorUtils.js +126 -45
  53. package/cjs/Utils/EventDispatcher.js +6 -5
  54. package/cjs/Utils/HslColorManager.js +5 -5
  55. package/cjs/Utils/NumberUtils.js +37 -24
  56. package/cjs/Utils/RgbColorManager.js +5 -5
  57. package/cjs/Utils/Utils.js +103 -19
  58. package/dist_browser_Core_Container_js.js +92 -0
  59. package/dist_browser_Core_Particle_js.js +32 -0
  60. package/esm/Core/Canvas.js +102 -49
  61. package/esm/Core/Container.js +53 -41
  62. package/esm/Core/Engine.js +47 -32
  63. package/esm/Core/Particle.js +46 -48
  64. package/esm/Core/Particles.js +70 -57
  65. package/esm/Core/Retina.js +5 -4
  66. package/esm/Core/Utils/Circle.js +4 -3
  67. package/esm/Core/Utils/Constants.js +3 -0
  68. package/esm/Core/Utils/EventListeners.js +19 -16
  69. package/esm/Core/Utils/ExternalInteractorBase.js +1 -1
  70. package/esm/Core/Utils/InteractionManager.js +17 -8
  71. package/esm/Core/Utils/ParticlesInteractorBase.js +1 -1
  72. package/esm/Core/Utils/QuadTree.js +5 -3
  73. package/esm/Core/Utils/Vector.js +7 -2
  74. package/esm/Core/Utils/Vector3d.js +14 -9
  75. package/esm/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  76. package/esm/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  77. package/esm/Options/Classes/ManualParticle.js +3 -2
  78. package/esm/Options/Classes/Options.js +3 -0
  79. package/esm/Utils/CanvasUtils.js +50 -40
  80. package/esm/Utils/ColorUtils.js +124 -45
  81. package/esm/Utils/EventDispatcher.js +6 -5
  82. package/esm/Utils/HslColorManager.js +5 -5
  83. package/esm/Utils/NumberUtils.js +35 -23
  84. package/esm/Utils/RgbColorManager.js +5 -5
  85. package/esm/Utils/Utils.js +102 -19
  86. package/package.json +1 -1
  87. package/report.html +3 -3
  88. package/tsparticles.engine.js +894 -5461
  89. package/tsparticles.engine.min.js +1 -1
  90. package/tsparticles.engine.min.js.LICENSE.txt +1 -1
  91. package/types/Core/Canvas.d.ts +5 -3
  92. package/types/Core/Container.d.ts +1 -1
  93. package/types/Core/Engine.d.ts +13 -8
  94. package/types/Core/Interfaces/IContainerPlugin.d.ts +3 -3
  95. package/types/Core/Interfaces/IEffectDrawer.d.ts +3 -3
  96. package/types/Core/Interfaces/IMovePathGenerator.d.ts +2 -2
  97. package/types/Core/Interfaces/IParticleHslAnimation.d.ts +4 -4
  98. package/types/Core/Interfaces/IParticleMover.d.ts +2 -2
  99. package/types/Core/Interfaces/IParticleUpdater.d.ts +2 -2
  100. package/types/Core/Interfaces/IParticleValueAnimation.d.ts +4 -0
  101. package/types/Core/Interfaces/IPlugin.d.ts +1 -1
  102. package/types/Core/Interfaces/IShapeDrawData.d.ts +2 -2
  103. package/types/Core/Interfaces/IShapeDrawer.d.ts +4 -4
  104. package/types/Core/Particle.d.ts +3 -3
  105. package/types/Core/Particles.d.ts +12 -8
  106. package/types/Core/Utils/Constants.d.ts +3 -0
  107. package/types/Core/Utils/ExternalInteractorBase.d.ts +1 -1
  108. package/types/Core/Utils/InteractionManager.d.ts +3 -3
  109. package/types/Core/Utils/ParticlesInteractorBase.d.ts +1 -1
  110. package/types/Core/Utils/Point.d.ts +1 -1
  111. package/types/Enums/Modes/OutMode.d.ts +0 -3
  112. package/types/Options/Classes/BackgroundMask/BackgroundMaskCover.d.ts +2 -1
  113. package/types/Options/Classes/Options.d.ts +1 -0
  114. package/types/Options/Classes/Particles/Move/Move.d.ts +1 -2
  115. package/types/Options/Classes/Particles/Move/OutModes.d.ts +5 -6
  116. package/types/Options/Interfaces/BackgroundMask/IBackgroundMask.d.ts +2 -1
  117. package/types/Options/Interfaces/BackgroundMask/IBackgroundMaskCover.d.ts +2 -1
  118. package/types/Options/Interfaces/IOptions.d.ts +1 -0
  119. package/types/Options/Interfaces/Interactivity/Modes/IModes.d.ts +1 -3
  120. package/types/Options/Interfaces/Particles/Move/IMove.d.ts +2 -2
  121. package/types/Options/Interfaces/Particles/Move/IOutModes.d.ts +6 -6
  122. package/types/Types/CustomEventArgs.d.ts +2 -2
  123. package/types/Types/ExportResult.d.ts +2 -2
  124. package/types/Types/ParticlesGroups.d.ts +1 -3
  125. package/types/Types/PathOptions.d.ts +1 -3
  126. package/types/Types/ShapeData.d.ts +1 -3
  127. package/types/Utils/CanvasUtils.d.ts +9 -8
  128. package/types/Utils/ColorUtils.d.ts +5 -0
  129. package/types/Utils/NumberUtils.d.ts +2 -2
  130. package/types/Utils/Utils.d.ts +9 -6
  131. package/umd/Core/Canvas.js +102 -49
  132. package/umd/Core/Container.js +54 -42
  133. package/umd/Core/Engine.js +72 -33
  134. package/umd/Core/Particle.js +46 -48
  135. package/umd/Core/Particles.js +95 -58
  136. package/umd/Core/Retina.js +5 -4
  137. package/umd/Core/Utils/Circle.js +4 -3
  138. package/umd/Core/Utils/Constants.js +4 -1
  139. package/umd/Core/Utils/EventListeners.js +18 -15
  140. package/umd/Core/Utils/ExternalInteractorBase.js +1 -1
  141. package/umd/Core/Utils/InteractionManager.js +17 -8
  142. package/umd/Core/Utils/ParticlesInteractorBase.js +1 -1
  143. package/umd/Core/Utils/QuadTree.js +5 -3
  144. package/umd/Core/Utils/Vector.js +7 -2
  145. package/umd/Core/Utils/Vector3d.js +14 -9
  146. package/umd/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  147. package/umd/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  148. package/umd/Options/Classes/ManualParticle.js +3 -2
  149. package/umd/Options/Classes/Options.js +3 -0
  150. package/umd/Utils/CanvasUtils.js +50 -40
  151. package/umd/Utils/ColorUtils.js +127 -46
  152. package/umd/Utils/EventDispatcher.js +6 -5
  153. package/umd/Utils/HslColorManager.js +5 -5
  154. package/umd/Utils/NumberUtils.js +38 -25
  155. package/umd/Utils/RgbColorManager.js +5 -5
  156. package/umd/Utils/Utils.js +104 -20
@@ -3,9 +3,29 @@ import { deepExtend, getLogger, safeMutationObserver } from "../Utils/Utils.js";
3
3
  import { getStyleFromHsl, getStyleFromRgb, rangeColorToHsl, rangeColorToRgb } from "../Utils/ColorUtils.js";
4
4
  import { generatedAttribute } from "./Utils/Constants.js";
5
5
  function setTransformValue(factor, newFactor, key) {
6
- const newValue = newFactor[key];
6
+ const newValue = newFactor[key], defaultValue = 1;
7
7
  if (newValue !== undefined) {
8
- factor[key] = (factor[key] ?? 1) * newValue;
8
+ factor[key] = (factor[key] ?? defaultValue) * newValue;
9
+ }
10
+ }
11
+ function setStyle(canvas, style, important = false) {
12
+ if (!style) {
13
+ return;
14
+ }
15
+ const element = canvas;
16
+ if (!element) {
17
+ return;
18
+ }
19
+ const elementStyle = element.style;
20
+ if (!elementStyle) {
21
+ return;
22
+ }
23
+ for (const key in style) {
24
+ const value = style[key];
25
+ if (!value) {
26
+ continue;
27
+ }
28
+ elementStyle.setProperty(key, value, important ? "important" : "");
9
29
  }
10
30
  }
11
31
  export class Canvas {
@@ -13,7 +33,7 @@ export class Canvas {
13
33
  this.container = container;
14
34
  this._applyPostDrawUpdaters = (particle) => {
15
35
  for (const updater of this._postDrawUpdaters) {
16
- updater.afterDraw && updater.afterDraw(particle);
36
+ updater.afterDraw?.(particle);
17
37
  }
18
38
  };
19
39
  this._applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
@@ -33,12 +53,12 @@ export class Canvas {
33
53
  setTransformValue(transform, updaterTransform, key);
34
54
  }
35
55
  }
36
- updater.beforeDraw && updater.beforeDraw(particle);
56
+ updater.beforeDraw?.(particle);
37
57
  }
38
58
  };
39
59
  this._applyResizePlugins = () => {
40
60
  for (const plugin of this._resizePlugins) {
41
- plugin.resize && plugin.resize();
61
+ plugin.resize?.();
42
62
  }
43
63
  };
44
64
  this._getPluginParticleColors = (particle) => {
@@ -56,14 +76,36 @@ export class Canvas {
56
76
  }
57
77
  return [fColor, sColor];
58
78
  };
59
- this._initCover = () => {
60
- const options = this.container.actualOptions, cover = options.backgroundMask.cover, color = cover.color, coverRgb = rangeColorToRgb(color);
61
- if (coverRgb) {
62
- const coverColor = {
63
- ...coverRgb,
64
- a: cover.opacity,
65
- };
66
- this._coverColorStyle = getStyleFromRgb(coverColor, coverColor.a);
79
+ this._initCover = async () => {
80
+ const options = this.container.actualOptions, cover = options.backgroundMask.cover, color = cover.color;
81
+ if (color) {
82
+ const coverRgb = rangeColorToRgb(color);
83
+ if (coverRgb) {
84
+ const coverColor = {
85
+ ...coverRgb,
86
+ a: cover.opacity,
87
+ };
88
+ this._coverColorStyle = getStyleFromRgb(coverColor, coverColor.a);
89
+ }
90
+ }
91
+ else {
92
+ await new Promise((resolve, reject) => {
93
+ if (!cover.image) {
94
+ return;
95
+ }
96
+ const img = document.createElement("img");
97
+ img.addEventListener("load", () => {
98
+ this._coverImage = {
99
+ image: img,
100
+ opacity: cover.opacity,
101
+ };
102
+ resolve();
103
+ });
104
+ img.addEventListener("error", (evt) => {
105
+ reject(evt.error);
106
+ });
107
+ img.src = cover.image;
108
+ });
67
109
  }
68
110
  };
69
111
  this._initStyle = () => {
@@ -94,17 +136,17 @@ export class Canvas {
94
136
  if (!trail.enable) {
95
137
  return;
96
138
  }
139
+ const factorNumerator = 1, opacity = factorNumerator / trail.length;
97
140
  if (trailFill.color) {
98
141
  const fillColor = rangeColorToRgb(trailFill.color);
99
142
  if (!fillColor) {
100
143
  return;
101
144
  }
102
- const trail = options.particles.move.trail;
103
145
  this._trailFill = {
104
146
  color: {
105
147
  ...fillColor,
106
148
  },
107
- opacity: 1 / trail.length,
149
+ opacity,
108
150
  };
109
151
  }
110
152
  else {
@@ -116,7 +158,7 @@ export class Canvas {
116
158
  img.addEventListener("load", () => {
117
159
  this._trailFill = {
118
160
  image: img,
119
- opacity: 1 / trail.length,
161
+ opacity,
120
162
  };
121
163
  resolve();
122
164
  });
@@ -148,13 +190,7 @@ export class Canvas {
148
190
  if (!(element && originalStyle)) {
149
191
  return;
150
192
  }
151
- const style = element.style;
152
- style.position = originalStyle.position;
153
- style.zIndex = originalStyle.zIndex;
154
- style.top = originalStyle.top;
155
- style.left = originalStyle.left;
156
- style.width = originalStyle.width;
157
- style.height = originalStyle.height;
193
+ setStyle(element, originalStyle);
158
194
  };
159
195
  this._safeMutationObserver = (callback) => {
160
196
  if (!this._mutationObserver) {
@@ -167,13 +203,15 @@ export class Canvas {
167
203
  if (!element) {
168
204
  return;
169
205
  }
170
- const priority = "important", style = element.style;
171
- style.setProperty("position", "fixed", priority);
172
- style.setProperty("z-index", this.container.actualOptions.fullScreen.zIndex.toString(10), priority);
173
- style.setProperty("top", "0", priority);
174
- style.setProperty("left", "0", priority);
175
- style.setProperty("width", "100%", priority);
176
- style.setProperty("height", "100%", priority);
206
+ const radix = 10;
207
+ setStyle(element, {
208
+ position: "fixed",
209
+ zIndex: this.container.actualOptions.fullScreen.zIndex.toString(radix),
210
+ top: "0",
211
+ left: "0",
212
+ width: "100%",
213
+ height: "100%",
214
+ }, true);
177
215
  };
178
216
  this.size = {
179
217
  height: 0,
@@ -190,11 +228,11 @@ export class Canvas {
190
228
  return this.container.actualOptions.fullScreen.enable;
191
229
  }
192
230
  clear() {
193
- const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = this._trailFill;
231
+ const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = this._trailFill, minimumLength = 0;
194
232
  if (options.backgroundMask.enable) {
195
233
  this.paint();
196
234
  }
197
- else if (trail.enable && trail.length > 0 && trailFill) {
235
+ else if (trail.enable && trail.length > minimumLength && trailFill) {
198
236
  if (trailFill.color) {
199
237
  this._paintBase(getStyleFromRgb(trailFill.color, trailFill.opacity));
200
238
  }
@@ -212,7 +250,7 @@ export class Canvas {
212
250
  this.stop();
213
251
  if (this._generated) {
214
252
  const element = this.element;
215
- element && element.remove();
253
+ element?.remove();
216
254
  }
217
255
  else {
218
256
  this._resetOriginalStyle();
@@ -229,12 +267,19 @@ export class Canvas {
229
267
  }
230
268
  return cb(ctx);
231
269
  }
232
- drawParticle(particle, delta) {
270
+ drawAsync(cb) {
271
+ const ctx = this._context;
272
+ if (!ctx) {
273
+ return Promise.resolve(undefined);
274
+ }
275
+ return cb(ctx);
276
+ }
277
+ async drawParticle(particle, delta) {
233
278
  if (particle.spawning || particle.destroyed) {
234
279
  return;
235
280
  }
236
- const radius = particle.getRadius();
237
- if (radius <= 0) {
281
+ const radius = particle.getRadius(), minimumSize = 0;
282
+ if (radius <= minimumSize) {
238
283
  return;
239
284
  }
240
285
  const pfColor = particle.getFillColor(), psColor = particle.getStrokeColor() ?? pfColor;
@@ -248,13 +293,13 @@ export class Canvas {
248
293
  if (!fColor && !sColor) {
249
294
  return;
250
295
  }
251
- this.draw((ctx) => {
252
- const container = this.container, options = container.actualOptions, zIndexOptions = particle.options.zIndex, zOpacityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.opacityRate, opacity = particle.bubble.opacity ?? particle.opacity?.value ?? 1, strokeOpacity = particle.strokeOpacity ?? opacity, zOpacity = opacity * zOpacityFactor, zStrokeOpacity = strokeOpacity * zOpacityFactor, transform = {}, colorStyles = {
296
+ await this.drawAsync(async (ctx) => {
297
+ const container = this.container, options = container.actualOptions, zIndexOptions = particle.options.zIndex, zIndexFactorOffset = 1, zIndexFactor = zIndexFactorOffset - particle.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, defaultOpacity = 1, opacity = particle.bubble.opacity ?? particle.opacity?.value ?? defaultOpacity, strokeOpacity = particle.strokeOpacity ?? opacity, zOpacity = opacity * zOpacityFactor, zStrokeOpacity = strokeOpacity * zOpacityFactor, transform = {}, colorStyles = {
253
298
  fill: fColor ? getStyleFromHsl(fColor, zOpacity) : undefined,
254
299
  };
255
300
  colorStyles.stroke = sColor ? getStyleFromHsl(sColor, zStrokeOpacity) : colorStyles.fill;
256
301
  this._applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform);
257
- drawParticle({
302
+ await drawParticle({
258
303
  container,
259
304
  context: ctx,
260
305
  particle,
@@ -262,7 +307,7 @@ export class Canvas {
262
307
  colorStyles,
263
308
  backgroundMask: options.backgroundMask.enable,
264
309
  composite: options.backgroundMask.composite,
265
- radius: radius * (1 - particle.zIndexFactor) ** zIndexOptions.sizeRate,
310
+ radius: radius * zIndexFactor ** zIndexOptions.sizeRate,
266
311
  opacity: zOpacity,
267
312
  shadow: particle.options.shadow,
268
313
  transform,
@@ -270,11 +315,11 @@ export class Canvas {
270
315
  this._applyPostDrawUpdaters(particle);
271
316
  });
272
317
  }
273
- drawParticlePlugin(plugin, particle, delta) {
274
- this.draw((ctx) => drawParticlePlugin(ctx, plugin, particle, delta));
318
+ async drawParticlePlugin(plugin, particle, delta) {
319
+ await this.drawAsync((ctx) => drawParticlePlugin(ctx, plugin, particle, delta));
275
320
  }
276
- drawPlugin(plugin, delta) {
277
- this.draw((ctx) => drawPlugin(ctx, plugin, delta));
321
+ async drawPlugin(plugin, delta) {
322
+ await this.drawAsync((ctx) => drawPlugin(ctx, plugin, delta));
278
323
  }
279
324
  async init() {
280
325
  this._safeMutationObserver((obs) => obs.disconnect());
@@ -287,7 +332,7 @@ export class Canvas {
287
332
  });
288
333
  this.resize();
289
334
  this._initStyle();
290
- this._initCover();
335
+ await this._initCover();
291
336
  try {
292
337
  await this._initTrail();
293
338
  }
@@ -332,7 +377,7 @@ export class Canvas {
332
377
  if (plugin.resize) {
333
378
  this._resizePlugins.push(plugin);
334
379
  }
335
- if (plugin.particleFillColor || plugin.particleStrokeColor) {
380
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
336
381
  this._colorPlugins.push(plugin);
337
382
  }
338
383
  }
@@ -344,7 +389,7 @@ export class Canvas {
344
389
  if (updater.afterDraw) {
345
390
  this._postDrawUpdaters.push(updater);
346
391
  }
347
- if (updater.getColorStyles || updater.getTransformValues || updater.beforeDraw) {
392
+ if (updater.getColorStyles ?? updater.getTransformValues ?? updater.beforeDraw) {
348
393
  this._preDrawUpdaters.push(updater);
349
394
  }
350
395
  }
@@ -377,7 +422,15 @@ export class Canvas {
377
422
  this.draw((ctx) => {
378
423
  if (options.backgroundMask.enable && options.backgroundMask.cover) {
379
424
  clear(ctx, this.size);
380
- this._paintBase(this._coverColorStyle);
425
+ if (this._coverImage) {
426
+ this._paintImage(this._coverImage.image, this._coverImage.opacity);
427
+ }
428
+ else if (this._coverColorStyle) {
429
+ this._paintBase(this._coverColorStyle);
430
+ }
431
+ else {
432
+ this._paintBase();
433
+ }
381
434
  }
382
435
  else {
383
436
  this._paintBase();
@@ -419,7 +472,7 @@ export class Canvas {
419
472
  return;
420
473
  }
421
474
  const container = this.container, needsRefresh = container.updateActualOptions();
422
- container.particles.setDensity();
475
+ await container.particles.setDensity();
423
476
  this._applyResizePlugins();
424
477
  if (needsRefresh) {
425
478
  await container.refresh();
@@ -1,19 +1,20 @@
1
+ import { errorPrefix, millisecondsToSeconds } from "./Utils/Constants.js";
1
2
  import { getLogger, safeIntersectionObserver } from "../Utils/Utils.js";
2
3
  import { Canvas } from "./Canvas.js";
3
4
  import { EventListeners } from "./Utils/EventListeners.js";
4
5
  import { Options } from "../Options/Classes/Options.js";
5
6
  import { Particles } from "./Particles.js";
6
7
  import { Retina } from "./Retina.js";
7
- import { errorPrefix } from "./Utils/Constants.js";
8
8
  import { getRangeValue } from "../Utils/NumberUtils.js";
9
9
  import { loadOptions } from "../Utils/OptionsUtils.js";
10
10
  function guardCheck(container) {
11
11
  return container && !container.destroyed;
12
12
  }
13
- function initDelta(value, fpsLimit = 60, smooth = false) {
13
+ const defaultFps = 60;
14
+ function initDelta(value, fpsLimit = defaultFps, smooth = false) {
14
15
  return {
15
16
  value,
16
- factor: smooth ? 60 / fpsLimit : (60 * value) / 1000,
17
+ factor: smooth ? defaultFps / fpsLimit : (defaultFps * value) / millisecondsToSeconds,
17
18
  };
18
19
  }
19
20
  function loadContainerOptions(engine, container, ...sourceOptionsArr) {
@@ -31,14 +32,19 @@ export class Container {
31
32
  if (entry.target !== this.interactivity.element) {
32
33
  continue;
33
34
  }
34
- (entry.isIntersecting ? this.play : this.pause)();
35
+ if (entry.isIntersecting) {
36
+ this.play();
37
+ }
38
+ else {
39
+ this.pause();
40
+ }
35
41
  }
36
42
  };
37
43
  this._nextFrame = async (timestamp) => {
38
44
  try {
39
45
  if (!this._smooth &&
40
46
  this._lastFrameTime !== undefined &&
41
- timestamp < this._lastFrameTime + 1000 / this.fpsLimit) {
47
+ timestamp < this._lastFrameTime + millisecondsToSeconds / this.fpsLimit) {
42
48
  this.draw(false);
43
49
  return;
44
50
  }
@@ -46,7 +52,7 @@ export class Container {
46
52
  const delta = initDelta(timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
47
53
  this.addLifeTime(delta.value);
48
54
  this._lastFrameTime = timestamp;
49
- if (delta.value > 1000) {
55
+ if (delta.value > millisecondsToSeconds) {
50
56
  this.draw(false);
51
57
  return;
52
58
  }
@@ -55,7 +61,7 @@ export class Container {
55
61
  this.destroy();
56
62
  return;
57
63
  }
58
- if (this.getAnimationStatus()) {
64
+ if (this.animationStatus) {
59
65
  this.draw(false);
60
66
  }
61
67
  }
@@ -98,6 +104,9 @@ export class Container {
98
104
  this._intersectionObserver = safeIntersectionObserver((entries) => this._intersectionManager(entries));
99
105
  this._engine.dispatchEvent("containerBuilt", { container: this });
100
106
  }
107
+ get animationStatus() {
108
+ return !this._paused && !this.pageHidden && guardCheck(this);
109
+ }
101
110
  get options() {
102
111
  return this._options;
103
112
  }
@@ -129,8 +138,8 @@ export class Container {
129
138
  const mouseEvent = e, pos = {
130
139
  x: mouseEvent.offsetX || mouseEvent.clientX,
131
140
  y: mouseEvent.offsetY || mouseEvent.clientY,
132
- };
133
- clickOrTouchHandler(e, pos, 1);
141
+ }, radius = 1;
142
+ clickOrTouchHandler(e, pos, radius);
134
143
  };
135
144
  const touchStartHandler = () => {
136
145
  if (!guardCheck(this)) {
@@ -151,16 +160,17 @@ export class Container {
151
160
  }
152
161
  if (touched && !touchMoved) {
153
162
  const touchEvent = e;
154
- let lastTouch = touchEvent.touches[touchEvent.touches.length - 1];
163
+ const lengthOffset = 1;
164
+ let lastTouch = touchEvent.touches[touchEvent.touches.length - lengthOffset];
155
165
  if (!lastTouch) {
156
- lastTouch = touchEvent.changedTouches[touchEvent.changedTouches.length - 1];
166
+ lastTouch = touchEvent.changedTouches[touchEvent.changedTouches.length - lengthOffset];
157
167
  if (!lastTouch) {
158
168
  return;
159
169
  }
160
170
  }
161
- const element = this.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
162
- x: lastTouch.clientX - (canvasRect ? canvasRect.left : 0),
163
- y: lastTouch.clientY - (canvasRect ? canvasRect.top : 0),
171
+ const element = this.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, minCoordinate = 0, pos = {
172
+ x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
173
+ y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
164
174
  };
165
175
  clickOrTouchHandler(e, pos, Math.max(lastTouch.radiusX, lastTouch.radiusY));
166
176
  }
@@ -202,10 +212,10 @@ export class Container {
202
212
  this.particles.destroy();
203
213
  this.canvas.destroy();
204
214
  for (const [, effectDrawer] of this.effectDrawers) {
205
- effectDrawer.destroy && effectDrawer.destroy(this);
215
+ effectDrawer.destroy?.(this);
206
216
  }
207
217
  for (const [, shapeDrawer] of this.shapeDrawers) {
208
- shapeDrawer.destroy && shapeDrawer.destroy(this);
218
+ shapeDrawer.destroy?.(this);
209
219
  }
210
220
  for (const key of this.effectDrawers.keys()) {
211
221
  this.effectDrawers.delete(key);
@@ -215,9 +225,10 @@ export class Container {
215
225
  }
216
226
  this._engine.clearPlugins(this);
217
227
  this.destroyed = true;
218
- const mainArr = this._engine.dom(), idx = mainArr.findIndex((t) => t === this);
219
- if (idx >= 0) {
220
- mainArr.splice(idx, 1);
228
+ const mainArr = this._engine.dom(), idx = mainArr.findIndex((t) => t === this), minIndex = 0;
229
+ if (idx >= minIndex) {
230
+ const deleteCount = 1;
231
+ mainArr.splice(idx, deleteCount);
221
232
  }
222
233
  this._engine.dispatchEvent("containerDestroyed", { container: this });
223
234
  }
@@ -226,13 +237,14 @@ export class Container {
226
237
  return;
227
238
  }
228
239
  let refreshTime = force;
229
- this._drawAnimationFrame = requestAnimationFrame(async (timestamp) => {
240
+ const frame = async (timestamp) => {
230
241
  if (refreshTime) {
231
242
  this._lastFrameTime = undefined;
232
243
  refreshTime = false;
233
244
  }
234
245
  await this._nextFrame(timestamp);
235
- });
246
+ };
247
+ this._drawAnimationFrame = requestAnimationFrame((timestamp) => void frame(timestamp));
236
248
  }
237
249
  async export(type, options = {}) {
238
250
  for (const [, plugin] of this.plugins) {
@@ -247,16 +259,13 @@ export class Container {
247
259
  }
248
260
  getLogger().error(`${errorPrefix} - Export plugin with type ${type} not found`);
249
261
  }
250
- getAnimationStatus() {
251
- return !this._paused && !this.pageHidden && guardCheck(this);
252
- }
253
262
  handleClickMode(mode) {
254
263
  if (!guardCheck(this)) {
255
264
  return;
256
265
  }
257
266
  this.particles.handleClickMode(mode);
258
267
  for (const [, plugin] of this.plugins) {
259
- plugin.handleClickMode && plugin.handleClickMode(mode);
268
+ plugin.handleClickMode?.(mode);
260
269
  }
261
270
  }
262
271
  async init() {
@@ -277,9 +286,10 @@ export class Container {
277
286
  this.shapeDrawers.set(type, drawer);
278
287
  }
279
288
  }
289
+ await this.particles.initPlugins();
280
290
  this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
281
291
  this.actualOptions = loadContainerOptions(this._engine, this, this._options);
282
- const availablePlugins = this._engine.getAvailablePlugins(this);
292
+ const availablePlugins = await this._engine.getAvailablePlugins(this);
283
293
  for (const [id, plugin] of availablePlugins) {
284
294
  this.plugins.set(id, plugin);
285
295
  }
@@ -289,25 +299,26 @@ export class Container {
289
299
  this.canvas.initBackground();
290
300
  this.canvas.resize();
291
301
  this.zLayers = this.actualOptions.zLayers;
292
- this._duration = getRangeValue(this.actualOptions.duration) * 1000;
293
- this._delay = getRangeValue(this.actualOptions.delay) * 1000;
302
+ this._duration = getRangeValue(this.actualOptions.duration) * millisecondsToSeconds;
303
+ this._delay = getRangeValue(this.actualOptions.delay) * millisecondsToSeconds;
294
304
  this._lifeTime = 0;
295
- this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
305
+ const defaultFpsLimit = 120, minFpsLimit = 0;
306
+ this.fpsLimit = this.actualOptions.fpsLimit > minFpsLimit ? this.actualOptions.fpsLimit : defaultFpsLimit;
296
307
  this._smooth = this.actualOptions.smooth;
297
308
  for (const [, drawer] of this.effectDrawers) {
298
- drawer.init && (await drawer.init(this));
309
+ await drawer.init?.(this);
299
310
  }
300
311
  for (const [, drawer] of this.shapeDrawers) {
301
- drawer.init && (await drawer.init(this));
312
+ await drawer.init?.(this);
302
313
  }
303
314
  for (const [, plugin] of this.plugins) {
304
- plugin.init && (await plugin.init());
315
+ await plugin.init?.();
305
316
  }
306
317
  this._engine.dispatchEvent("containerInit", { container: this });
307
- this.particles.init();
308
- this.particles.setDensity();
318
+ await this.particles.init();
319
+ await this.particles.setDensity();
309
320
  for (const [, plugin] of this.plugins) {
310
- plugin.particlesSetup && plugin.particlesSetup();
321
+ plugin.particlesSetup?.();
311
322
  }
312
323
  this._engine.dispatchEvent("particlesSetup", { container: this });
313
324
  }
@@ -330,7 +341,7 @@ export class Container {
330
341
  return;
331
342
  }
332
343
  for (const [, plugin] of this.plugins) {
333
- plugin.pause && plugin.pause();
344
+ plugin.pause?.();
334
345
  }
335
346
  if (!this.pageHidden) {
336
347
  this._paused = true;
@@ -357,7 +368,7 @@ export class Container {
357
368
  }
358
369
  }
359
370
  this._engine.dispatchEvent("containerPlay", { container: this });
360
- this.draw(needsUpdate || false);
371
+ this.draw(needsUpdate ?? false);
361
372
  }
362
373
  async refresh() {
363
374
  if (!guardCheck(this)) {
@@ -382,18 +393,19 @@ export class Container {
382
393
  await this.init();
383
394
  this.started = true;
384
395
  await new Promise((resolve) => {
385
- this._delayTimeout = setTimeout(async () => {
396
+ const start = async () => {
386
397
  this._eventListeners.addListeners();
387
398
  if (this.interactivity.element instanceof HTMLElement && this._intersectionObserver) {
388
399
  this._intersectionObserver.observe(this.interactivity.element);
389
400
  }
390
401
  for (const [, plugin] of this.plugins) {
391
- plugin.start && (await plugin.start());
402
+ await plugin.start?.();
392
403
  }
393
404
  this._engine.dispatchEvent("containerStarted", { container: this });
394
405
  this.play();
395
406
  resolve();
396
- }, this._delay);
407
+ };
408
+ this._delayTimeout = setTimeout(() => void start(), this._delay);
397
409
  });
398
410
  }
399
411
  stop() {
@@ -414,7 +426,7 @@ export class Container {
414
426
  this._intersectionObserver.unobserve(this.interactivity.element);
415
427
  }
416
428
  for (const [, plugin] of this.plugins) {
417
- plugin.stop && plugin.stop();
429
+ plugin.stop?.();
418
430
  }
419
431
  for (const key of this.plugins.keys()) {
420
432
  this.plugins.delete(key);