@tsparticles/engine 3.0.2 → 3.1.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 (124) hide show
  1. package/README.md +283 -163
  2. package/browser/Core/Canvas.js +19 -19
  3. package/browser/Core/Container.js +45 -34
  4. package/browser/Core/Engine.js +36 -20
  5. package/browser/Core/Particle.js +35 -36
  6. package/browser/Core/Particles.js +30 -24
  7. package/browser/Core/Retina.js +5 -4
  8. package/browser/Core/Utils/Circle.js +4 -3
  9. package/browser/Core/Utils/Constants.js +3 -0
  10. package/browser/Core/Utils/EventListeners.js +18 -15
  11. package/browser/Core/Utils/ExternalInteractorBase.js +1 -1
  12. package/browser/Core/Utils/InteractionManager.js +14 -6
  13. package/browser/Core/Utils/ParticlesInteractorBase.js +1 -1
  14. package/browser/Core/Utils/QuadTree.js +5 -3
  15. package/browser/Core/Utils/Vector.js +7 -2
  16. package/browser/Core/Utils/Vector3d.js +14 -9
  17. package/browser/Options/Classes/ManualParticle.js +3 -2
  18. package/browser/Options/Classes/Options.js +3 -0
  19. package/browser/Utils/CanvasUtils.js +36 -26
  20. package/browser/Utils/ColorUtils.js +124 -45
  21. package/browser/Utils/EventDispatcher.js +6 -5
  22. package/browser/Utils/HslColorManager.js +5 -5
  23. package/browser/Utils/NumberUtils.js +35 -23
  24. package/browser/Utils/RgbColorManager.js +5 -5
  25. package/browser/Utils/Utils.js +102 -19
  26. package/cjs/Core/Canvas.js +19 -19
  27. package/cjs/Core/Container.js +45 -34
  28. package/cjs/Core/Engine.js +36 -20
  29. package/cjs/Core/Particle.js +34 -35
  30. package/cjs/Core/Particles.js +30 -24
  31. package/cjs/Core/Retina.js +5 -4
  32. package/cjs/Core/Utils/Circle.js +4 -3
  33. package/cjs/Core/Utils/Constants.js +4 -1
  34. package/cjs/Core/Utils/EventListeners.js +17 -14
  35. package/cjs/Core/Utils/ExternalInteractorBase.js +1 -1
  36. package/cjs/Core/Utils/InteractionManager.js +14 -6
  37. package/cjs/Core/Utils/ParticlesInteractorBase.js +1 -1
  38. package/cjs/Core/Utils/QuadTree.js +5 -3
  39. package/cjs/Core/Utils/Vector.js +7 -2
  40. package/cjs/Core/Utils/Vector3d.js +14 -9
  41. package/cjs/Options/Classes/ManualParticle.js +3 -2
  42. package/cjs/Options/Classes/Options.js +3 -0
  43. package/cjs/Utils/CanvasUtils.js +36 -26
  44. package/cjs/Utils/ColorUtils.js +126 -45
  45. package/cjs/Utils/EventDispatcher.js +6 -5
  46. package/cjs/Utils/HslColorManager.js +5 -5
  47. package/cjs/Utils/NumberUtils.js +37 -24
  48. package/cjs/Utils/RgbColorManager.js +5 -5
  49. package/cjs/Utils/Utils.js +103 -19
  50. package/esm/Core/Canvas.js +19 -19
  51. package/esm/Core/Container.js +45 -34
  52. package/esm/Core/Engine.js +36 -20
  53. package/esm/Core/Particle.js +35 -36
  54. package/esm/Core/Particles.js +30 -24
  55. package/esm/Core/Retina.js +5 -4
  56. package/esm/Core/Utils/Circle.js +4 -3
  57. package/esm/Core/Utils/Constants.js +3 -0
  58. package/esm/Core/Utils/EventListeners.js +18 -15
  59. package/esm/Core/Utils/ExternalInteractorBase.js +1 -1
  60. package/esm/Core/Utils/InteractionManager.js +14 -6
  61. package/esm/Core/Utils/ParticlesInteractorBase.js +1 -1
  62. package/esm/Core/Utils/QuadTree.js +5 -3
  63. package/esm/Core/Utils/Vector.js +7 -2
  64. package/esm/Core/Utils/Vector3d.js +14 -9
  65. package/esm/Options/Classes/ManualParticle.js +3 -2
  66. package/esm/Options/Classes/Options.js +3 -0
  67. package/esm/Utils/CanvasUtils.js +36 -26
  68. package/esm/Utils/ColorUtils.js +124 -45
  69. package/esm/Utils/EventDispatcher.js +6 -5
  70. package/esm/Utils/HslColorManager.js +5 -5
  71. package/esm/Utils/NumberUtils.js +35 -23
  72. package/esm/Utils/RgbColorManager.js +5 -5
  73. package/esm/Utils/Utils.js +102 -19
  74. package/package.json +1 -1
  75. package/report.html +2 -2
  76. package/tsparticles.engine.js +693 -334
  77. package/tsparticles.engine.min.js +1 -1
  78. package/tsparticles.engine.min.js.LICENSE.txt +1 -1
  79. package/types/Core/Interfaces/IParticleHslAnimation.d.ts +4 -4
  80. package/types/Core/Interfaces/IParticleValueAnimation.d.ts +4 -0
  81. package/types/Core/Interfaces/IShapeDrawData.d.ts +2 -2
  82. package/types/Core/Utils/Constants.d.ts +3 -0
  83. package/types/Core/Utils/ExternalInteractorBase.d.ts +1 -1
  84. package/types/Core/Utils/InteractionManager.d.ts +1 -1
  85. package/types/Core/Utils/ParticlesInteractorBase.d.ts +1 -1
  86. package/types/Core/Utils/Point.d.ts +1 -1
  87. package/types/Options/Classes/Options.d.ts +1 -0
  88. package/types/Options/Classes/Particles/Move/Move.d.ts +1 -2
  89. package/types/Options/Classes/Particles/Move/OutModes.d.ts +1 -2
  90. package/types/Options/Interfaces/IOptions.d.ts +1 -0
  91. package/types/Options/Interfaces/Interactivity/Modes/IModes.d.ts +1 -3
  92. package/types/Types/CustomEventArgs.d.ts +2 -2
  93. package/types/Types/ExportResult.d.ts +2 -2
  94. package/types/Types/ParticlesGroups.d.ts +1 -3
  95. package/types/Types/PathOptions.d.ts +1 -3
  96. package/types/Types/ShapeData.d.ts +1 -3
  97. package/types/Utils/CanvasUtils.d.ts +3 -2
  98. package/types/Utils/ColorUtils.d.ts +5 -0
  99. package/types/Utils/NumberUtils.d.ts +2 -2
  100. package/types/Utils/Utils.d.ts +9 -6
  101. package/umd/Core/Canvas.js +19 -19
  102. package/umd/Core/Container.js +46 -35
  103. package/umd/Core/Engine.js +36 -20
  104. package/umd/Core/Particle.js +35 -36
  105. package/umd/Core/Particles.js +30 -24
  106. package/umd/Core/Retina.js +5 -4
  107. package/umd/Core/Utils/Circle.js +4 -3
  108. package/umd/Core/Utils/Constants.js +4 -1
  109. package/umd/Core/Utils/EventListeners.js +17 -14
  110. package/umd/Core/Utils/ExternalInteractorBase.js +1 -1
  111. package/umd/Core/Utils/InteractionManager.js +14 -6
  112. package/umd/Core/Utils/ParticlesInteractorBase.js +1 -1
  113. package/umd/Core/Utils/QuadTree.js +5 -3
  114. package/umd/Core/Utils/Vector.js +7 -2
  115. package/umd/Core/Utils/Vector3d.js +14 -9
  116. package/umd/Options/Classes/ManualParticle.js +3 -2
  117. package/umd/Options/Classes/Options.js +3 -0
  118. package/umd/Utils/CanvasUtils.js +36 -26
  119. package/umd/Utils/ColorUtils.js +127 -46
  120. package/umd/Utils/EventDispatcher.js +6 -5
  121. package/umd/Utils/HslColorManager.js +5 -5
  122. package/umd/Utils/NumberUtils.js +38 -25
  123. package/umd/Utils/RgbColorManager.js +5 -5
  124. package/umd/Utils/Utils.js +104 -20
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * tsParticles Engine v3.0.2
2
+ * tsParticles Engine v3.1.0
3
3
  * Author: Matteo Bruni
4
4
  * MIT license: https://opensource.org/licenses/MIT
5
5
  * Website: https://particles.js.org/
@@ -141,6 +141,7 @@ __webpack_require__.d(__webpack_exports__, {
141
141
  colorToHsl: () => (/* reexport */ colorToHsl),
142
142
  colorToRgb: () => (/* reexport */ colorToRgb),
143
143
  deepExtend: () => (/* reexport */ deepExtend),
144
+ degToRad: () => (/* reexport */ degToRad),
144
145
  divMode: () => (/* reexport */ divMode),
145
146
  divModeExecute: () => (/* reexport */ divModeExecute),
146
147
  drawEffect: () => (/* reexport */ drawEffect),
@@ -173,6 +174,7 @@ __webpack_require__.d(__webpack_exports__, {
173
174
  getSize: () => (/* reexport */ getSize),
174
175
  getStyleFromHsl: () => (/* reexport */ getStyleFromHsl),
175
176
  getStyleFromRgb: () => (/* reexport */ getStyleFromRgb),
177
+ halfRandom: () => (/* reexport */ halfRandom),
176
178
  hasMatchMedia: () => (/* reexport */ hasMatchMedia),
177
179
  hslToRgb: () => (/* reexport */ hslToRgb),
178
180
  hslaToRgba: () => (/* reexport */ hslaToRgba),
@@ -192,6 +194,7 @@ __webpack_require__.d(__webpack_exports__, {
192
194
  loadFont: () => (/* reexport */ loadFont),
193
195
  loadOptions: () => (/* reexport */ loadOptions),
194
196
  loadParticlesOptions: () => (/* reexport */ loadParticlesOptions),
197
+ millisecondsToSeconds: () => (/* reexport */ millisecondsToSeconds),
195
198
  mix: () => (/* reexport */ mix),
196
199
  mouseDownEvent: () => (/* reexport */ mouseDownEvent),
197
200
  mouseLeaveEvent: () => (/* reexport */ mouseLeaveEvent),
@@ -201,6 +204,7 @@ __webpack_require__.d(__webpack_exports__, {
201
204
  paintBase: () => (/* reexport */ paintBase),
202
205
  paintImage: () => (/* reexport */ paintImage),
203
206
  parseAlpha: () => (/* reexport */ parseAlpha),
207
+ percentDenominator: () => (/* reexport */ percentDenominator),
204
208
  randomInRange: () => (/* reexport */ randomInRange),
205
209
  rangeColorToHsl: () => (/* reexport */ rangeColorToHsl),
206
210
  rangeColorToRgb: () => (/* reexport */ rangeColorToRgb),
@@ -221,6 +225,9 @@ __webpack_require__.d(__webpack_exports__, {
221
225
  touchMoveEvent: () => (/* reexport */ touchMoveEvent),
222
226
  touchStartEvent: () => (/* reexport */ touchStartEvent),
223
227
  tsParticles: () => (/* binding */ tsParticles),
228
+ updateAnimation: () => (/* reexport */ updateAnimation),
229
+ updateColor: () => (/* reexport */ updateColor),
230
+ updateColorValue: () => (/* reexport */ updateColorValue),
224
231
  visibilityChangeEvent: () => (/* reexport */ visibilityChangeEvent)
225
232
  });
226
233
 
@@ -238,9 +245,19 @@ const touchCancelEvent = "touchcancel";
238
245
  const resizeEvent = "resize";
239
246
  const visibilityChangeEvent = "visibilitychange";
240
247
  const errorPrefix = "tsParticles - Error";
248
+ const percentDenominator = 100;
249
+ const halfRandom = 0.5;
250
+ const millisecondsToSeconds = 1000;
241
251
  ;// CONCATENATED MODULE: ./dist/browser/Core/Utils/Vector3d.js
242
252
 
243
253
 
254
+ const origin = {
255
+ x: 0,
256
+ y: 0,
257
+ z: 0
258
+ },
259
+ squareExp = 2,
260
+ inverseFactorNumerator = 1.0;
244
261
  class Vector3d {
245
262
  constructor(xOrCoords, y, z) {
246
263
  this._updateFromAngle = (angle, length) => {
@@ -251,17 +268,17 @@ class Vector3d {
251
268
  this.x = xOrCoords.x;
252
269
  this.y = xOrCoords.y;
253
270
  const coords3d = xOrCoords;
254
- this.z = coords3d.z ? coords3d.z : 0;
271
+ this.z = coords3d.z ? coords3d.z : origin.z;
255
272
  } else if (xOrCoords !== undefined && y !== undefined) {
256
273
  this.x = xOrCoords;
257
274
  this.y = y;
258
- this.z = z ?? 0;
275
+ this.z = z ?? origin.z;
259
276
  } else {
260
277
  throw new Error(`${errorPrefix} Vector3d not initialized correctly`);
261
278
  }
262
279
  }
263
280
  static get origin() {
264
- return Vector3d.create(0, 0, 0);
281
+ return Vector3d.create(origin.x, origin.y, origin.z);
265
282
  }
266
283
  get angle() {
267
284
  return Math.atan2(this.y, this.x);
@@ -307,7 +324,7 @@ class Vector3d {
307
324
  this.z /= n;
308
325
  }
309
326
  getLengthSq() {
310
- return this.x ** 2 + this.y ** 2;
327
+ return this.x ** squareExp + this.y ** squareExp;
311
328
  }
312
329
  mult(n) {
313
330
  return Vector3d.create(this.x * n, this.y * n, this.z * n);
@@ -318,19 +335,20 @@ class Vector3d {
318
335
  this.z *= n;
319
336
  }
320
337
  normalize() {
321
- const length = this.length;
322
- if (length != 0) {
323
- this.multTo(1.0 / length);
338
+ const length = this.length,
339
+ noLength = 0;
340
+ if (length != noLength) {
341
+ this.multTo(inverseFactorNumerator / length);
324
342
  }
325
343
  }
326
344
  rotate(angle) {
327
- return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle), 0);
345
+ return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle), origin.z);
328
346
  }
329
347
  setTo(c) {
330
348
  this.x = c.x;
331
349
  this.y = c.y;
332
350
  const v3d = c;
333
- this.z = v3d.z ? v3d.z : 0;
351
+ this.z = v3d.z ? v3d.z : origin.z;
334
352
  }
335
353
  sub(v) {
336
354
  return Vector3d.create(this.x - v.x, this.y - v.y, this.z - v.z);
@@ -343,12 +361,17 @@ class Vector3d {
343
361
  }
344
362
  ;// CONCATENATED MODULE: ./dist/browser/Core/Utils/Vector.js
345
363
 
364
+ const Vector_origin = {
365
+ x: 0,
366
+ y: 0,
367
+ z: 0
368
+ };
346
369
  class Vector extends Vector3d {
347
370
  constructor(xOrCoords, y) {
348
- super(xOrCoords, y, 0);
371
+ super(xOrCoords, y, Vector_origin.z);
349
372
  }
350
373
  static get origin() {
351
- return Vector.create(0, 0);
374
+ return Vector.create(Vector_origin.x, Vector_origin.y);
352
375
  }
353
376
  static clone(source) {
354
377
  return Vector.create(source.x, source.y);
@@ -360,8 +383,11 @@ class Vector extends Vector3d {
360
383
  ;// CONCATENATED MODULE: ./dist/browser/Utils/NumberUtils.js
361
384
 
362
385
 
386
+
363
387
  let _random = Math.random;
364
- const easings = new Map();
388
+ const easings = new Map(),
389
+ NumberUtils_double = 2,
390
+ doublePI = Math.PI * NumberUtils_double;
365
391
  function addEasing(name, easing) {
366
392
  if (easings.get(name)) {
367
393
  return;
@@ -369,13 +395,15 @@ function addEasing(name, easing) {
369
395
  easings.set(name, easing);
370
396
  }
371
397
  function getEasing(name) {
372
- return easings.get(name) || (value => value);
398
+ return easings.get(name) ?? (value => value);
373
399
  }
374
400
  function setRandom(rnd = Math.random) {
375
401
  _random = rnd;
376
402
  }
377
403
  function getRandom() {
378
- return clamp(_random(), 0, 1 - 1e-16);
404
+ const min = 0,
405
+ max = 1;
406
+ return clamp(_random(), min, max - Number.EPSILON);
379
407
  }
380
408
  function clamp(num, min, max) {
381
409
  return Math.min(Math.max(num, min), max);
@@ -384,10 +412,11 @@ function mix(comp1, comp2, weight1, weight2) {
384
412
  return Math.floor((comp1 * weight1 + comp2 * weight2) / (weight1 + weight2));
385
413
  }
386
414
  function randomInRange(r) {
387
- const max = getRangeMax(r);
415
+ const max = getRangeMax(r),
416
+ minOffset = 0;
388
417
  let min = getRangeMin(r);
389
418
  if (max === min) {
390
- min = 0;
419
+ min = minOffset;
391
420
  }
392
421
  return getRandom() * (max - min) + min;
393
422
  }
@@ -413,43 +442,52 @@ function setRangeValue(source, value) {
413
442
  }
414
443
  function getDistances(pointA, pointB) {
415
444
  const dx = pointA.x - pointB.x,
416
- dy = pointA.y - pointB.y;
445
+ dy = pointA.y - pointB.y,
446
+ squareExp = 2;
417
447
  return {
418
448
  dx: dx,
419
449
  dy: dy,
420
- distance: Math.sqrt(dx ** 2 + dy ** 2)
450
+ distance: Math.sqrt(dx ** squareExp + dy ** squareExp)
421
451
  };
422
452
  }
423
453
  function getDistance(pointA, pointB) {
424
454
  return getDistances(pointA, pointB).distance;
425
455
  }
456
+ function degToRad(degrees) {
457
+ const PIDeg = 180;
458
+ return degrees * Math.PI / PIDeg;
459
+ }
426
460
  function getParticleDirectionAngle(direction, position, center) {
427
461
  if (isNumber(direction)) {
428
- return direction * Math.PI / 180;
462
+ return degToRad(direction);
429
463
  }
464
+ const empty = 0,
465
+ half = 0.5,
466
+ quarter = 0.25,
467
+ threeQuarter = half + quarter;
430
468
  switch (direction) {
431
469
  case "top":
432
- return -Math.PI * 0.5;
470
+ return -Math.PI * half;
433
471
  case "top-right":
434
- return -Math.PI * 0.25;
472
+ return -Math.PI * quarter;
435
473
  case "right":
436
- return 0;
474
+ return empty;
437
475
  case "bottom-right":
438
- return Math.PI * 0.25;
476
+ return Math.PI * quarter;
439
477
  case "bottom":
440
- return Math.PI * 0.5;
478
+ return Math.PI * half;
441
479
  case "bottom-left":
442
- return Math.PI * 0.75;
480
+ return Math.PI * threeQuarter;
443
481
  case "left":
444
482
  return Math.PI;
445
483
  case "top-left":
446
- return -Math.PI * 0.75;
484
+ return -Math.PI * threeQuarter;
447
485
  case "inside":
448
486
  return Math.atan2(center.y - position.y, center.x - position.x);
449
487
  case "outside":
450
488
  return Math.atan2(position.y - center.y, position.x - center.x);
451
489
  default:
452
- return getRandom() * Math.PI * 2;
490
+ return getRandom() * doublePI;
453
491
  }
454
492
  }
455
493
  function getParticleBaseVelocity(direction) {
@@ -459,18 +497,19 @@ function getParticleBaseVelocity(direction) {
459
497
  return baseVelocity;
460
498
  }
461
499
  function collisionVelocity(v1, v2, m1, m2) {
462
- return Vector.create(v1.x * (m1 - m2) / (m1 + m2) + v2.x * 2 * m2 / (m1 + m2), v1.y);
500
+ const double = 2;
501
+ return Vector.create(v1.x * (m1 - m2) / (m1 + m2) + v2.x * double * m2 / (m1 + m2), v1.y);
463
502
  }
464
503
  function calcPositionFromSize(data) {
465
- return data.position && data.position.x !== undefined && data.position.y !== undefined ? {
466
- x: data.position.x * data.size.width / 100,
467
- y: data.position.y * data.size.height / 100
504
+ return data.position?.x !== undefined && data.position.y !== undefined ? {
505
+ x: data.position.x * data.size.width / percentDenominator,
506
+ y: data.position.y * data.size.height / percentDenominator
468
507
  } : undefined;
469
508
  }
470
509
  function calcPositionOrRandomFromSize(data) {
471
510
  return {
472
- x: (data.position?.x ?? getRandom() * 100) * data.size.width / 100,
473
- y: (data.position?.y ?? getRandom() * 100) * data.size.height / 100
511
+ x: (data.position?.x ?? getRandom() * percentDenominator) * data.size.width / percentDenominator,
512
+ y: (data.position?.y ?? getRandom() * percentDenominator) * data.size.height / percentDenominator
474
513
  };
475
514
  }
476
515
  function calcPositionOrRandomFromSizeRanged(data) {
@@ -500,11 +539,16 @@ function calcExactPositionOrRandomFromSizeRanged(data) {
500
539
  });
501
540
  }
502
541
  function parseAlpha(input) {
503
- return input ? input.endsWith("%") ? parseFloat(input) / 100 : parseFloat(input) : 1;
542
+ const defaultAlpha = 1;
543
+ if (!input) {
544
+ return defaultAlpha;
545
+ }
546
+ return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
504
547
  }
505
548
  ;// CONCATENATED MODULE: ./dist/browser/Utils/Utils.js
506
549
 
507
550
 
551
+
508
552
  const _logger = {
509
553
  debug: console.debug,
510
554
  error: console.error,
@@ -535,11 +579,13 @@ function rectSideBounce(data) {
535
579
  rectOtherSide,
536
580
  velocity,
537
581
  factor
538
- } = data;
582
+ } = data,
583
+ half = 0.5,
584
+ minVelocity = 0;
539
585
  if (pOtherSide.min < rectOtherSide.min || pOtherSide.min > rectOtherSide.max || pOtherSide.max < rectOtherSide.min || pOtherSide.max > rectOtherSide.max) {
540
586
  return res;
541
587
  }
542
- if (pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) * 0.5 && velocity > 0 || pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) * 0.5 && velocity < 0) {
588
+ if (pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) * half && velocity > minVelocity || pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) * half && velocity < minVelocity) {
543
589
  res.velocity = velocity * -factor;
544
590
  res.bounced = true;
545
591
  }
@@ -576,7 +622,8 @@ function safeMutationObserver(callback) {
576
622
  return new MutationObserver(callback);
577
623
  }
578
624
  function isInArray(value, array) {
579
- return value === array || isArray(array) && array.indexOf(value) > -1;
625
+ const invalidIndex = -1;
626
+ return value === array || isArray(array) && array.indexOf(value) > invalidIndex;
580
627
  }
581
628
  async function loadFont(font, weight) {
582
629
  try {
@@ -590,7 +637,8 @@ function itemFromArray(array, index, useIndex = true) {
590
637
  return array[index !== undefined && useIndex ? index % array.length : arrayRandomIndex(array)];
591
638
  }
592
639
  function isPointInside(point, size, offset, radius, direction) {
593
- return areBoundsInside(calculateBounds(point, radius ?? 0), size, offset, direction);
640
+ const minRadius = 0;
641
+ return areBoundsInside(calculateBounds(point, radius ?? minRadius), size, offset, direction);
594
642
  }
595
643
  function areBoundsInside(bounds, size, offset, direction) {
596
644
  let inside = true;
@@ -687,8 +735,9 @@ function circleBounce(p1, p2) {
687
735
  {
688
736
  dx: xDist,
689
737
  dy: yDist
690
- } = getDistances(pos2, pos1);
691
- if (xVelocityDiff * xDist + yVelocityDiff * yDist < 0) {
738
+ } = getDistances(pos2, pos1),
739
+ minimumDistance = 0;
740
+ if (xVelocityDiff * xDist + yVelocityDiff * yDist < minimumDistance) {
692
741
  return;
693
742
  }
694
743
  const angle = -Math.atan2(yDist, xDist),
@@ -768,19 +817,24 @@ function rectBounce(particle, divBounds) {
768
817
  }
769
818
  }
770
819
  function executeOnSingleOrMultiple(obj, callback) {
771
- return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, 0);
820
+ const defaultIndex = 0;
821
+ return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, defaultIndex);
772
822
  }
773
823
  function itemFromSingleOrMultiple(obj, index, useIndex) {
774
824
  return isArray(obj) ? itemFromArray(obj, index, useIndex) : obj;
775
825
  }
776
826
  function findItemFromSingleOrMultiple(obj, callback) {
777
- return isArray(obj) ? obj.find((t, index) => callback(t, index)) : callback(obj, 0) ? obj : undefined;
827
+ if (isArray(obj)) {
828
+ return obj.find((t, index) => callback(t, index));
829
+ }
830
+ const defaultIndex = 0;
831
+ return callback(obj, defaultIndex) ? obj : undefined;
778
832
  }
779
833
  function initParticleNumericAnimationValue(options, pxRatio) {
780
834
  const valueRange = options.value,
781
835
  animationOptions = options.animation,
782
836
  res = {
783
- delayTime: getRangeValue(animationOptions.delay) * 1000,
837
+ delayTime: getRangeValue(animationOptions.delay) * millisecondsToSeconds,
784
838
  enable: animationOptions.enable,
785
839
  value: getRangeValue(options.value) * pxRatio,
786
840
  max: getRangeMax(valueRange) * pxRatio,
@@ -788,9 +842,10 @@ function initParticleNumericAnimationValue(options, pxRatio) {
788
842
  loops: 0,
789
843
  maxLoops: getRangeValue(animationOptions.count),
790
844
  time: 0
791
- };
845
+ },
846
+ decayOffset = 1;
792
847
  if (animationOptions.enable) {
793
- res.decay = 1 - getRangeValue(animationOptions.decay);
848
+ res.decay = decayOffset - getRangeValue(animationOptions.decay);
794
849
  switch (animationOptions.mode) {
795
850
  case "increase":
796
851
  res.status = "increasing";
@@ -799,7 +854,7 @@ function initParticleNumericAnimationValue(options, pxRatio) {
799
854
  res.status = "decreasing";
800
855
  break;
801
856
  case "random":
802
- res.status = getRandom() >= 0.5 ? "increasing" : "decreasing";
857
+ res.status = getRandom() >= halfRandom ? "increasing" : "decreasing";
803
858
  break;
804
859
  }
805
860
  const autoStatus = animationOptions.mode === "auto";
@@ -820,7 +875,7 @@ function initParticleNumericAnimationValue(options, pxRatio) {
820
875
  default:
821
876
  res.value = randomInRange(res);
822
877
  if (autoStatus) {
823
- res.status = getRandom() >= 0.5 ? "increasing" : "decreasing";
878
+ res.status = getRandom() >= halfRandom ? "increasing" : "decreasing";
824
879
  }
825
880
  break;
826
881
  }
@@ -840,13 +895,13 @@ function getPositionOrSize(positionOrSize, canvasSize) {
840
895
  const isPosition = ("x" in positionOrSize);
841
896
  if (isPosition) {
842
897
  return {
843
- x: positionOrSize.x / 100 * canvasSize.width,
844
- y: positionOrSize.y / 100 * canvasSize.height
898
+ x: positionOrSize.x / percentDenominator * canvasSize.width,
899
+ y: positionOrSize.y / percentDenominator * canvasSize.height
845
900
  };
846
901
  } else {
847
902
  return {
848
- width: positionOrSize.width / 100 * canvasSize.width,
849
- height: positionOrSize.height / 100 * canvasSize.height
903
+ width: positionOrSize.width / percentDenominator * canvasSize.width,
904
+ height: positionOrSize.height / percentDenominator * canvasSize.height
850
905
  };
851
906
  }
852
907
  }
@@ -874,9 +929,85 @@ function isObject(arg) {
874
929
  function isArray(arg) {
875
930
  return Array.isArray(arg);
876
931
  }
932
+ function checkDestroy(particle, destroyType, value, minValue, maxValue) {
933
+ switch (destroyType) {
934
+ case "max":
935
+ if (value >= maxValue) {
936
+ particle.destroy();
937
+ }
938
+ break;
939
+ case "min":
940
+ if (value <= minValue) {
941
+ particle.destroy();
942
+ }
943
+ break;
944
+ }
945
+ }
946
+ function updateAnimation(particle, data, changeDirection, destroyType, delta) {
947
+ const minLoops = 0,
948
+ minDelay = 0,
949
+ identity = 1,
950
+ minVelocity = 0,
951
+ minDecay = 1;
952
+ if (particle.destroyed || !data || !data.enable || (data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops)) {
953
+ return;
954
+ }
955
+ const velocity = (data.velocity ?? minVelocity) * delta.factor,
956
+ minValue = data.min,
957
+ maxValue = data.max,
958
+ decay = data.decay ?? minDecay;
959
+ if (!data.time) {
960
+ data.time = 0;
961
+ }
962
+ if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
963
+ data.time += delta.value;
964
+ }
965
+ if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
966
+ return;
967
+ }
968
+ switch (data.status) {
969
+ case "increasing":
970
+ if (data.value >= maxValue) {
971
+ if (changeDirection) {
972
+ data.status = "decreasing";
973
+ } else {
974
+ data.value -= maxValue;
975
+ }
976
+ if (!data.loops) {
977
+ data.loops = minLoops;
978
+ }
979
+ data.loops++;
980
+ } else {
981
+ data.value += velocity;
982
+ }
983
+ break;
984
+ case "decreasing":
985
+ if (data.value <= minValue) {
986
+ if (changeDirection) {
987
+ data.status = "increasing";
988
+ } else {
989
+ data.value += maxValue;
990
+ }
991
+ if (!data.loops) {
992
+ data.loops = minLoops;
993
+ }
994
+ data.loops++;
995
+ } else {
996
+ data.value -= velocity;
997
+ }
998
+ }
999
+ if (data.velocity && decay !== identity) {
1000
+ data.velocity *= decay;
1001
+ }
1002
+ checkDestroy(particle, destroyType, data.value, minValue, maxValue);
1003
+ if (!particle.destroyed) {
1004
+ data.value = clamp(data.value, minValue, maxValue);
1005
+ }
1006
+ }
877
1007
  ;// CONCATENATED MODULE: ./dist/browser/Utils/ColorUtils.js
878
1008
 
879
1009
 
1010
+
880
1011
  const randomColorValue = "random",
881
1012
  midColorValue = "mid",
882
1013
  colorManagers = new Map();
@@ -894,12 +1025,15 @@ function stringToRgba(input) {
894
1025
  return r + r + g + g + b + b + (a !== undefined ? a + a : "");
895
1026
  }),
896
1027
  regex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i,
897
- result = regex.exec(hexFixed);
1028
+ result = regex.exec(hexFixed),
1029
+ radix = 16,
1030
+ defaultAlpha = 1,
1031
+ alphaFactor = 0xff;
898
1032
  return result ? {
899
- a: result[4] !== undefined ? parseInt(result[4], 16) / 0xff : 1,
900
- b: parseInt(result[3], 16),
901
- g: parseInt(result[2], 16),
902
- r: parseInt(result[1], 16)
1033
+ a: result[4] !== undefined ? parseInt(result[4], radix) / alphaFactor : defaultAlpha,
1034
+ b: parseInt(result[3], radix),
1035
+ g: parseInt(result[2], radix),
1036
+ r: parseInt(result[1], radix)
903
1037
  } : undefined;
904
1038
  }
905
1039
  function rangeColorToRgb(input, index, useIndex = true) {
@@ -955,28 +1089,37 @@ function rangeColorToHsl(color, index, useIndex = true) {
955
1089
  return rgb ? rgbToHsl(rgb) : undefined;
956
1090
  }
957
1091
  function rgbToHsl(color) {
958
- const r1 = color.r / 255,
959
- g1 = color.g / 255,
960
- b1 = color.b / 255,
1092
+ const rgbMax = 255,
1093
+ hMax = 360,
1094
+ sMax = 100,
1095
+ lMax = 100,
1096
+ hMin = 0,
1097
+ sMin = 0,
1098
+ hPhase = 60,
1099
+ half = 0.5,
1100
+ double = 2,
1101
+ r1 = color.r / rgbMax,
1102
+ g1 = color.g / rgbMax,
1103
+ b1 = color.b / rgbMax,
961
1104
  max = Math.max(r1, g1, b1),
962
1105
  min = Math.min(r1, g1, b1),
963
1106
  res = {
964
- h: 0,
965
- l: (max + min) * 0.5,
966
- s: 0
1107
+ h: hMin,
1108
+ l: (max + min) * half,
1109
+ s: sMin
967
1110
  };
968
1111
  if (max !== min) {
969
- res.s = res.l < 0.5 ? (max - min) / (max + min) : (max - min) / (2.0 - max - min);
970
- res.h = r1 === max ? (g1 - b1) / (max - min) : res.h = g1 === max ? 2.0 + (b1 - r1) / (max - min) : 4.0 + (r1 - g1) / (max - min);
1112
+ res.s = res.l < half ? (max - min) / (max + min) : (max - min) / (double - max - min);
1113
+ res.h = r1 === max ? (g1 - b1) / (max - min) : res.h = g1 === max ? double + (b1 - r1) / (max - min) : double * double + (r1 - g1) / (max - min);
971
1114
  }
972
- res.l *= 100;
973
- res.s *= 100;
974
- res.h *= 60;
975
- if (res.h < 0) {
976
- res.h += 360;
1115
+ res.l *= lMax;
1116
+ res.s *= sMax;
1117
+ res.h *= hPhase;
1118
+ if (res.h < hMin) {
1119
+ res.h += hMax;
977
1120
  }
978
- if (res.h >= 360) {
979
- res.h -= 360;
1121
+ if (res.h >= hMax) {
1122
+ res.h -= hMax;
980
1123
  }
981
1124
  return res;
982
1125
  }
@@ -987,43 +1130,59 @@ function stringToRgb(input) {
987
1130
  return stringToRgba(input);
988
1131
  }
989
1132
  function hslToRgb(hsl) {
990
- const h = (hsl.h % 360 + 360) % 360,
991
- s = Math.max(0, Math.min(100, hsl.s)),
992
- l = Math.max(0, Math.min(100, hsl.l)),
993
- hNormalized = h / 360,
994
- sNormalized = s / 100,
995
- lNormalized = l / 100;
996
- if (s === 0) {
997
- const grayscaleValue = Math.round(lNormalized * 255);
1133
+ const hMax = 360,
1134
+ sMax = 100,
1135
+ lMax = 100,
1136
+ sMin = 0,
1137
+ lMin = 0,
1138
+ h = (hsl.h % hMax + hMax) % hMax,
1139
+ s = Math.max(sMin, Math.min(sMax, hsl.s)),
1140
+ l = Math.max(lMin, Math.min(lMax, hsl.l)),
1141
+ hNormalized = h / hMax,
1142
+ sNormalized = s / sMax,
1143
+ lNormalized = l / lMax,
1144
+ rgbFactor = 255,
1145
+ triple = 3;
1146
+ if (s === sMin) {
1147
+ const grayscaleValue = Math.round(lNormalized * rgbFactor);
998
1148
  return {
999
1149
  r: grayscaleValue,
1000
1150
  g: grayscaleValue,
1001
1151
  b: grayscaleValue
1002
1152
  };
1003
1153
  }
1004
- const channel = (temp1, temp2, temp3) => {
1005
- if (temp3 < 0) {
1006
- temp3 += 1;
1154
+ const half = 0.5,
1155
+ double = 2,
1156
+ channel = (temp1, temp2, temp3) => {
1157
+ const temp3Min = 0,
1158
+ temp3Max = 1,
1159
+ sextuple = 6;
1160
+ if (temp3 < temp3Min) {
1161
+ temp3++;
1007
1162
  }
1008
- if (temp3 > 1) {
1009
- temp3 -= 1;
1163
+ if (temp3 > temp3Max) {
1164
+ temp3--;
1010
1165
  }
1011
- if (temp3 * 6 < 1) {
1012
- return temp1 + (temp2 - temp1) * 6 * temp3;
1166
+ if (temp3 * sextuple < temp3Max) {
1167
+ return temp1 + (temp2 - temp1) * sextuple * temp3;
1013
1168
  }
1014
- if (temp3 * 2 < 1) {
1169
+ if (temp3 * double < temp3Max) {
1015
1170
  return temp2;
1016
1171
  }
1017
- if (temp3 * 3 < 2) {
1018
- return temp1 + (temp2 - temp1) * (2 / 3 - temp3) * 6;
1172
+ if (temp3 * triple < temp3Max * double) {
1173
+ const temp3Offset = double / triple;
1174
+ return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
1019
1175
  }
1020
1176
  return temp1;
1021
1177
  },
1022
- temp1 = lNormalized < 0.5 ? lNormalized * (1 + sNormalized) : lNormalized + sNormalized - lNormalized * sNormalized,
1023
- temp2 = 2 * lNormalized - temp1,
1024
- red = Math.min(255, 255 * channel(temp2, temp1, hNormalized + 1 / 3)),
1025
- green = Math.min(255, 255 * channel(temp2, temp1, hNormalized)),
1026
- blue = Math.min(255, 255 * channel(temp2, temp1, hNormalized - 1 / 3));
1178
+ sNormalizedOffset = 1,
1179
+ temp1 = lNormalized < half ? lNormalized * (sNormalizedOffset + sNormalized) : lNormalized + sNormalized - lNormalized * sNormalized,
1180
+ temp2 = double * lNormalized - temp1,
1181
+ phaseNumerator = 1,
1182
+ phaseThird = phaseNumerator / triple,
1183
+ red = Math.min(rgbFactor, rgbFactor * channel(temp2, temp1, hNormalized + phaseThird)),
1184
+ green = Math.min(rgbFactor, rgbFactor * channel(temp2, temp1, hNormalized)),
1185
+ blue = Math.min(rgbFactor, rgbFactor * channel(temp2, temp1, hNormalized - phaseThird));
1027
1186
  return {
1028
1187
  r: Math.round(red),
1029
1188
  g: Math.round(green),
@@ -1040,18 +1199,22 @@ function hslaToRgba(hsla) {
1040
1199
  };
1041
1200
  }
1042
1201
  function getRandomRgbColor(min) {
1043
- const fixedMin = min ?? 0;
1202
+ const defaultMin = 0,
1203
+ fixedMin = min ?? defaultMin,
1204
+ rgbMax = 256;
1044
1205
  return {
1045
- b: Math.floor(randomInRange(setRangeValue(fixedMin, 256))),
1046
- g: Math.floor(randomInRange(setRangeValue(fixedMin, 256))),
1047
- r: Math.floor(randomInRange(setRangeValue(fixedMin, 256)))
1206
+ b: Math.floor(randomInRange(setRangeValue(fixedMin, rgbMax))),
1207
+ g: Math.floor(randomInRange(setRangeValue(fixedMin, rgbMax))),
1208
+ r: Math.floor(randomInRange(setRangeValue(fixedMin, rgbMax)))
1048
1209
  };
1049
1210
  }
1050
1211
  function getStyleFromRgb(color, opacity) {
1051
- return `rgba(${color.r}, ${color.g}, ${color.b}, ${opacity ?? 1})`;
1212
+ const defaultOpacity = 1;
1213
+ return `rgba(${color.r}, ${color.g}, ${color.b}, ${opacity ?? defaultOpacity})`;
1052
1214
  }
1053
1215
  function getStyleFromHsl(color, opacity) {
1054
- return `hsla(${color.h}, ${color.s}%, ${color.l}%, ${opacity ?? 1})`;
1216
+ const defaultOpacity = 1;
1217
+ return `hsla(${color.h}, ${color.s}%, ${color.l}%, ${opacity ?? defaultOpacity})`;
1055
1218
  }
1056
1219
  function colorMix(color1, color2, size1, size2) {
1057
1220
  let rgb1 = color1,
@@ -1137,25 +1300,120 @@ function getHslAnimationFromHsl(hsl, animationOptions, reduceFactor) {
1137
1300
  }
1138
1301
  function setColorAnimation(colorValue, colorAnimation, reduceFactor) {
1139
1302
  colorValue.enable = colorAnimation.enable;
1303
+ const defaultVelocity = 0,
1304
+ decayOffset = 1,
1305
+ defaultLoops = 0,
1306
+ defaultTime = 0;
1140
1307
  if (colorValue.enable) {
1141
- colorValue.velocity = getRangeValue(colorAnimation.speed) / 100 * reduceFactor;
1142
- colorValue.decay = 1 - getRangeValue(colorAnimation.decay);
1308
+ colorValue.velocity = getRangeValue(colorAnimation.speed) / percentDenominator * reduceFactor;
1309
+ colorValue.decay = decayOffset - getRangeValue(colorAnimation.decay);
1143
1310
  colorValue.status = "increasing";
1144
- colorValue.loops = 0;
1311
+ colorValue.loops = defaultLoops;
1145
1312
  colorValue.maxLoops = getRangeValue(colorAnimation.count);
1146
- colorValue.time = 0;
1147
- colorValue.delayTime = getRangeValue(colorAnimation.delay) * 1000;
1313
+ colorValue.time = defaultTime;
1314
+ colorValue.delayTime = getRangeValue(colorAnimation.delay) * millisecondsToSeconds;
1148
1315
  if (!colorAnimation.sync) {
1149
1316
  colorValue.velocity *= getRandom();
1150
1317
  colorValue.value *= getRandom();
1151
1318
  }
1152
1319
  colorValue.initialValue = colorValue.value;
1320
+ colorValue.offset = setRangeValue(colorAnimation.offset);
1321
+ } else {
1322
+ colorValue.velocity = defaultVelocity;
1323
+ }
1324
+ }
1325
+ function updateColorValue(data, range, decrease, delta) {
1326
+ const minLoops = 0,
1327
+ minDelay = 0,
1328
+ identity = 1,
1329
+ minVelocity = 0,
1330
+ minOffset = 0,
1331
+ velocityFactor = 3.6;
1332
+ if (!data || !data.enable || (data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops)) {
1333
+ return;
1334
+ }
1335
+ if (!data.time) {
1336
+ data.time = 0;
1337
+ }
1338
+ if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
1339
+ data.time += delta.value;
1340
+ }
1341
+ if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
1342
+ return;
1343
+ }
1344
+ const offset = data.offset ? randomInRange(data.offset) : minOffset,
1345
+ velocity = (data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor,
1346
+ decay = data.decay ?? identity,
1347
+ max = getRangeMax(range),
1348
+ min = getRangeMin(range);
1349
+ if (!decrease || data.status === "increasing") {
1350
+ data.value += velocity;
1351
+ if (data.value > max) {
1352
+ if (!data.loops) {
1353
+ data.loops = 0;
1354
+ }
1355
+ data.loops++;
1356
+ if (decrease) {
1357
+ data.status = "decreasing";
1358
+ } else {
1359
+ data.value -= max;
1360
+ }
1361
+ }
1153
1362
  } else {
1154
- colorValue.velocity = 0;
1363
+ data.value -= velocity;
1364
+ const minValue = 0;
1365
+ if (data.value < minValue) {
1366
+ if (!data.loops) {
1367
+ data.loops = 0;
1368
+ }
1369
+ data.loops++;
1370
+ data.status = "increasing";
1371
+ }
1372
+ }
1373
+ if (data.velocity && decay !== identity) {
1374
+ data.velocity *= decay;
1375
+ }
1376
+ data.value = clamp(data.value, min, max);
1377
+ }
1378
+ function updateColor(color, delta) {
1379
+ if (!color) {
1380
+ return;
1381
+ }
1382
+ const {
1383
+ h,
1384
+ s,
1385
+ l
1386
+ } = color;
1387
+ const ranges = {
1388
+ h: {
1389
+ min: 0,
1390
+ max: 360
1391
+ },
1392
+ s: {
1393
+ min: 0,
1394
+ max: 100
1395
+ },
1396
+ l: {
1397
+ min: 0,
1398
+ max: 100
1399
+ }
1400
+ };
1401
+ if (h) {
1402
+ updateColorValue(h, ranges.h, false, delta);
1403
+ }
1404
+ if (s) {
1405
+ updateColorValue(s, ranges.s, true, delta);
1406
+ }
1407
+ if (l) {
1408
+ updateColorValue(l, ranges.l, true, delta);
1155
1409
  }
1156
1410
  }
1157
1411
  ;// CONCATENATED MODULE: ./dist/browser/Utils/CanvasUtils.js
1158
1412
 
1413
+ const CanvasUtils_origin = {
1414
+ x: 0,
1415
+ y: 0
1416
+ };
1159
1417
  function drawLine(context, begin, end) {
1160
1418
  context.beginPath();
1161
1419
  context.moveTo(begin.x, begin.y);
@@ -1164,44 +1422,46 @@ function drawLine(context, begin, end) {
1164
1422
  }
1165
1423
  function paintBase(context, dimension, baseColor) {
1166
1424
  context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1167
- context.fillRect(0, 0, dimension.width, dimension.height);
1425
+ context.fillRect(CanvasUtils_origin.x, CanvasUtils_origin.y, dimension.width, dimension.height);
1168
1426
  }
1169
1427
  function paintImage(context, dimension, image, opacity) {
1170
1428
  if (!image) {
1171
1429
  return;
1172
1430
  }
1173
1431
  context.globalAlpha = opacity;
1174
- context.drawImage(image, 0, 0, dimension.width, dimension.height);
1432
+ context.drawImage(image, CanvasUtils_origin.x, CanvasUtils_origin.y, dimension.width, dimension.height);
1175
1433
  context.globalAlpha = 1;
1176
1434
  }
1177
1435
  function clear(context, dimension) {
1178
- context.clearRect(0, 0, dimension.width, dimension.height);
1436
+ context.clearRect(CanvasUtils_origin.x, CanvasUtils_origin.y, dimension.width, dimension.height);
1179
1437
  }
1180
1438
  function drawParticle(data) {
1181
1439
  const {
1182
- container,
1183
- context,
1184
- particle,
1185
- delta,
1186
- colorStyles,
1187
- backgroundMask,
1188
- composite,
1189
- radius,
1190
- opacity,
1191
- shadow,
1192
- transform
1193
- } = data;
1194
- const pos = particle.getPosition(),
1195
- angle = particle.rotation + (particle.pathRotation ? particle.velocity.angle : 0),
1440
+ container,
1441
+ context,
1442
+ particle,
1443
+ delta,
1444
+ colorStyles,
1445
+ backgroundMask,
1446
+ composite,
1447
+ radius,
1448
+ opacity,
1449
+ shadow,
1450
+ transform
1451
+ } = data,
1452
+ pos = particle.getPosition(),
1453
+ defaultAngle = 0,
1454
+ angle = particle.rotation + (particle.pathRotation ? particle.velocity.angle : defaultAngle),
1196
1455
  rotateData = {
1197
1456
  sin: Math.sin(angle),
1198
1457
  cos: Math.cos(angle)
1199
1458
  },
1459
+ defaultTransformFactor = 1,
1200
1460
  transformData = {
1201
- a: rotateData.cos * (transform.a ?? 1),
1202
- b: rotateData.sin * (transform.b ?? 1),
1203
- c: -rotateData.sin * (transform.c ?? 1),
1204
- d: rotateData.cos * (transform.d ?? 1)
1461
+ a: rotateData.cos * (transform.a ?? defaultTransformFactor),
1462
+ b: rotateData.sin * (transform.b ?? defaultTransformFactor),
1463
+ c: -rotateData.sin * (transform.c ?? defaultTransformFactor),
1464
+ d: rotateData.cos * (transform.d ?? defaultTransformFactor)
1205
1465
  };
1206
1466
  context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1207
1467
  if (backgroundMask) {
@@ -1217,7 +1477,8 @@ function drawParticle(data) {
1217
1477
  if (colorStyles.fill) {
1218
1478
  context.fillStyle = colorStyles.fill;
1219
1479
  }
1220
- const strokeWidth = particle.strokeWidth ?? 0;
1480
+ const minStrokeWidth = 0,
1481
+ strokeWidth = particle.strokeWidth ?? minStrokeWidth;
1221
1482
  context.lineWidth = strokeWidth;
1222
1483
  if (colorStyles.stroke) {
1223
1484
  context.strokeStyle = colorStyles.stroke;
@@ -1229,23 +1490,14 @@ function drawParticle(data) {
1229
1490
  radius,
1230
1491
  opacity,
1231
1492
  delta,
1232
- transformData
1493
+ transformData,
1494
+ strokeWidth
1233
1495
  };
1234
- context.beginPath();
1235
1496
  drawShape(drawData);
1236
- if (particle.shapeClose) {
1237
- context.closePath();
1238
- }
1239
- if (strokeWidth > 0) {
1240
- context.stroke();
1241
- }
1242
- if (particle.shapeFill) {
1243
- context.fill();
1244
- }
1245
1497
  drawShapeAfterDraw(drawData);
1246
1498
  drawEffect(drawData);
1247
1499
  context.globalCompositeOperation = "source-over";
1248
- context.setTransform(1, 0, 0, 1, 0, 0);
1500
+ context.resetTransform();
1249
1501
  }
1250
1502
  function drawEffect(data) {
1251
1503
  const {
@@ -1278,14 +1530,16 @@ function drawEffect(data) {
1278
1530
  }
1279
1531
  function drawShape(data) {
1280
1532
  const {
1281
- container,
1282
- context,
1283
- particle,
1284
- radius,
1285
- opacity,
1286
- delta,
1287
- transformData
1288
- } = data;
1533
+ container,
1534
+ context,
1535
+ particle,
1536
+ radius,
1537
+ opacity,
1538
+ delta,
1539
+ strokeWidth,
1540
+ transformData
1541
+ } = data,
1542
+ minStrokeWidth = 0;
1289
1543
  if (!particle.shape) {
1290
1544
  return;
1291
1545
  }
@@ -1293,6 +1547,7 @@ function drawShape(data) {
1293
1547
  if (!drawer) {
1294
1548
  return;
1295
1549
  }
1550
+ context.beginPath();
1296
1551
  drawer.draw({
1297
1552
  context,
1298
1553
  particle,
@@ -1304,6 +1559,15 @@ function drawShape(data) {
1304
1559
  ...transformData
1305
1560
  }
1306
1561
  });
1562
+ if (particle.shapeClose) {
1563
+ context.closePath();
1564
+ }
1565
+ if (strokeWidth > minStrokeWidth) {
1566
+ context.stroke();
1567
+ }
1568
+ if (particle.shapeFill) {
1569
+ context.fill();
1570
+ }
1307
1571
  }
1308
1572
  function drawShapeAfterDraw(data) {
1309
1573
  const {
@@ -1319,7 +1583,7 @@ function drawShapeAfterDraw(data) {
1319
1583
  return;
1320
1584
  }
1321
1585
  const drawer = container.shapeDrawers.get(particle.shape);
1322
- if (!drawer || !drawer.afterDraw) {
1586
+ if (!drawer?.afterDraw) {
1323
1587
  return;
1324
1588
  }
1325
1589
  drawer.afterDraw({
@@ -1347,10 +1611,11 @@ function drawParticlePlugin(context, plugin, particle, delta) {
1347
1611
  plugin.drawParticle(context, particle, delta);
1348
1612
  }
1349
1613
  function alterHsl(color, type, value) {
1614
+ const lFactor = 1;
1350
1615
  return {
1351
1616
  h: color.h,
1352
1617
  s: color.s,
1353
- l: color.l + (type === "darken" ? -1 : 1) * value
1618
+ l: color.l + (type === "darken" ? -lFactor : lFactor) * value
1354
1619
  };
1355
1620
  }
1356
1621
  ;// CONCATENATED MODULE: ./dist/browser/Core/Canvas.js
@@ -1359,9 +1624,10 @@ function alterHsl(color, type, value) {
1359
1624
 
1360
1625
 
1361
1626
  function setTransformValue(factor, newFactor, key) {
1362
- const newValue = newFactor[key];
1627
+ const newValue = newFactor[key],
1628
+ defaultValue = 1;
1363
1629
  if (newValue !== undefined) {
1364
- factor[key] = (factor[key] ?? 1) * newValue;
1630
+ factor[key] = (factor[key] ?? defaultValue) * newValue;
1365
1631
  }
1366
1632
  }
1367
1633
  class Canvas {
@@ -1369,7 +1635,7 @@ class Canvas {
1369
1635
  this.container = container;
1370
1636
  this._applyPostDrawUpdaters = particle => {
1371
1637
  for (const updater of this._postDrawUpdaters) {
1372
- updater.afterDraw && updater.afterDraw(particle);
1638
+ updater.afterDraw?.(particle);
1373
1639
  }
1374
1640
  };
1375
1641
  this._applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
@@ -1392,12 +1658,12 @@ class Canvas {
1392
1658
  setTransformValue(transform, updaterTransform, key);
1393
1659
  }
1394
1660
  }
1395
- updater.beforeDraw && updater.beforeDraw(particle);
1661
+ updater.beforeDraw?.(particle);
1396
1662
  }
1397
1663
  };
1398
1664
  this._applyResizePlugins = () => {
1399
1665
  for (const plugin of this._resizePlugins) {
1400
- plugin.resize && plugin.resize();
1666
+ plugin.resize?.();
1401
1667
  }
1402
1668
  };
1403
1669
  this._getPluginParticleColors = particle => {
@@ -1458,17 +1724,18 @@ class Canvas {
1458
1724
  if (!trail.enable) {
1459
1725
  return;
1460
1726
  }
1727
+ const factorNumerator = 1,
1728
+ opacity = factorNumerator / trail.length;
1461
1729
  if (trailFill.color) {
1462
1730
  const fillColor = rangeColorToRgb(trailFill.color);
1463
1731
  if (!fillColor) {
1464
1732
  return;
1465
1733
  }
1466
- const trail = options.particles.move.trail;
1467
1734
  this._trailFill = {
1468
1735
  color: {
1469
1736
  ...fillColor
1470
1737
  },
1471
- opacity: 1 / trail.length
1738
+ opacity
1472
1739
  };
1473
1740
  } else {
1474
1741
  await new Promise((resolve, reject) => {
@@ -1479,7 +1746,7 @@ class Canvas {
1479
1746
  img.addEventListener("load", () => {
1480
1747
  this._trailFill = {
1481
1748
  image: img,
1482
- opacity: 1 / trail.length
1749
+ opacity
1483
1750
  };
1484
1751
  resolve();
1485
1752
  });
@@ -1534,9 +1801,10 @@ class Canvas {
1534
1801
  return;
1535
1802
  }
1536
1803
  const priority = "important",
1537
- style = element.style;
1804
+ style = element.style,
1805
+ radix = 10;
1538
1806
  style.setProperty("position", "fixed", priority);
1539
- style.setProperty("z-index", this.container.actualOptions.fullScreen.zIndex.toString(10), priority);
1807
+ style.setProperty("z-index", this.container.actualOptions.fullScreen.zIndex.toString(radix), priority);
1540
1808
  style.setProperty("top", "0", priority);
1541
1809
  style.setProperty("left", "0", priority);
1542
1810
  style.setProperty("width", "100%", priority);
@@ -1559,10 +1827,11 @@ class Canvas {
1559
1827
  clear() {
1560
1828
  const options = this.container.actualOptions,
1561
1829
  trail = options.particles.move.trail,
1562
- trailFill = this._trailFill;
1830
+ trailFill = this._trailFill,
1831
+ minimumLength = 0;
1563
1832
  if (options.backgroundMask.enable) {
1564
1833
  this.paint();
1565
- } else if (trail.enable && trail.length > 0 && trailFill) {
1834
+ } else if (trail.enable && trail.length > minimumLength && trailFill) {
1566
1835
  if (trailFill.color) {
1567
1836
  this._paintBase(getStyleFromRgb(trailFill.color, trailFill.opacity));
1568
1837
  } else if (trailFill.image) {
@@ -1578,7 +1847,7 @@ class Canvas {
1578
1847
  this.stop();
1579
1848
  if (this._generated) {
1580
1849
  const element = this.element;
1581
- element && element.remove();
1850
+ element?.remove();
1582
1851
  } else {
1583
1852
  this._resetOriginalStyle();
1584
1853
  }
@@ -1598,8 +1867,9 @@ class Canvas {
1598
1867
  if (particle.spawning || particle.destroyed) {
1599
1868
  return;
1600
1869
  }
1601
- const radius = particle.getRadius();
1602
- if (radius <= 0) {
1870
+ const radius = particle.getRadius(),
1871
+ minimumSize = 0;
1872
+ if (radius <= minimumSize) {
1603
1873
  return;
1604
1874
  }
1605
1875
  const pfColor = particle.getFillColor(),
@@ -1618,8 +1888,11 @@ class Canvas {
1618
1888
  const container = this.container,
1619
1889
  options = container.actualOptions,
1620
1890
  zIndexOptions = particle.options.zIndex,
1621
- zOpacityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.opacityRate,
1622
- opacity = particle.bubble.opacity ?? particle.opacity?.value ?? 1,
1891
+ zIndexFactorOffset = 1,
1892
+ zIndexFactor = zIndexFactorOffset - particle.zIndexFactor,
1893
+ zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate,
1894
+ defaultOpacity = 1,
1895
+ opacity = particle.bubble.opacity ?? particle.opacity?.value ?? defaultOpacity,
1623
1896
  strokeOpacity = particle.strokeOpacity ?? opacity,
1624
1897
  zOpacity = opacity * zOpacityFactor,
1625
1898
  zStrokeOpacity = strokeOpacity * zOpacityFactor,
@@ -1637,7 +1910,7 @@ class Canvas {
1637
1910
  colorStyles,
1638
1911
  backgroundMask: options.backgroundMask.enable,
1639
1912
  composite: options.backgroundMask.composite,
1640
- radius: radius * (1 - particle.zIndexFactor) ** zIndexOptions.sizeRate,
1913
+ radius: radius * zIndexFactor ** zIndexOptions.sizeRate,
1641
1914
  opacity: zOpacity,
1642
1915
  shadow: particle.options.shadow,
1643
1916
  transform
@@ -1709,7 +1982,7 @@ class Canvas {
1709
1982
  if (plugin.resize) {
1710
1983
  this._resizePlugins.push(plugin);
1711
1984
  }
1712
- if (plugin.particleFillColor || plugin.particleStrokeColor) {
1985
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
1713
1986
  this._colorPlugins.push(plugin);
1714
1987
  }
1715
1988
  }
@@ -1721,7 +1994,7 @@ class Canvas {
1721
1994
  if (updater.afterDraw) {
1722
1995
  this._postDrawUpdaters.push(updater);
1723
1996
  }
1724
- if (updater.getColorStyles || updater.getTransformValues || updater.beforeDraw) {
1997
+ if (updater.getColorStyles ?? updater.getTransformValues ?? updater.beforeDraw) {
1725
1998
  this._preDrawUpdaters.push(updater);
1726
1999
  }
1727
2000
  }
@@ -1807,6 +2080,7 @@ class Canvas {
1807
2080
  ;// CONCATENATED MODULE: ./dist/browser/Core/Utils/EventListeners.js
1808
2081
 
1809
2082
 
2083
+ const EventListeners_double = 2;
1810
2084
  function manageListener(element, event, handler, add, options) {
1811
2085
  if (add) {
1812
2086
  let addOptions = {
@@ -1843,7 +2117,8 @@ class EventListeners {
1843
2117
  executeOnSingleOrMultiple(onClick.mode, mode => this.container.handleClickMode(mode));
1844
2118
  }
1845
2119
  if (e.type === "touchend") {
1846
- setTimeout(() => this._mouseTouchFinish(), 500);
2120
+ const touchDelay = 500;
2121
+ setTimeout(() => this._mouseTouchFinish(), touchDelay);
1847
2122
  }
1848
2123
  };
1849
2124
  this._handleThemeChange = e => {
@@ -1854,7 +2129,7 @@ class EventListeners {
1854
2129
  themeName = mediaEvent.matches ? defaultThemes.dark : defaultThemes.light,
1855
2130
  theme = options.themes.find(theme => theme.name === themeName);
1856
2131
  if (theme && theme.default.auto) {
1857
- container.loadTheme(themeName);
2132
+ void container.loadTheme(themeName);
1858
2133
  }
1859
2134
  };
1860
2135
  this._handleVisibilityChange = () => {
@@ -1876,15 +2151,16 @@ class EventListeners {
1876
2151
  }
1877
2152
  }
1878
2153
  };
1879
- this._handleWindowResize = async () => {
2154
+ this._handleWindowResize = () => {
1880
2155
  if (this._resizeTimeout) {
1881
2156
  clearTimeout(this._resizeTimeout);
1882
2157
  delete this._resizeTimeout;
1883
2158
  }
1884
- this._resizeTimeout = setTimeout(async () => {
2159
+ const handleResize = async () => {
1885
2160
  const canvas = this.container.canvas;
1886
- canvas && (await canvas.windowResize());
1887
- }, this.container.actualOptions.interactivity.events.resize.delay * 1000);
2161
+ await canvas?.windowResize();
2162
+ };
2163
+ this._resizeTimeout = setTimeout(() => void handleResize(), this.container.actualOptions.interactivity.events.resize.delay * millisecondsToSeconds);
1888
2164
  };
1889
2165
  this._manageInteractivityListeners = (mouseLeaveTmpEvent, add) => {
1890
2166
  const handlers = this._handlers,
@@ -1975,12 +2251,12 @@ class EventListeners {
1975
2251
  this._resizeObserver.disconnect();
1976
2252
  delete this._resizeObserver;
1977
2253
  } else if (!this._resizeObserver && add && canvasEl) {
1978
- this._resizeObserver = new ResizeObserver(async entries => {
2254
+ this._resizeObserver = new ResizeObserver(entries => {
1979
2255
  const entry = entries.find(e => e.target === canvasEl);
1980
2256
  if (!entry) {
1981
2257
  return;
1982
2258
  }
1983
- await this._handleWindowResize();
2259
+ this._handleWindowResize();
1984
2260
  });
1985
2261
  this._resizeObserver.observe(canvasEl);
1986
2262
  }
@@ -2042,7 +2318,7 @@ class EventListeners {
2042
2318
  options = container.actualOptions,
2043
2319
  interactivity = container.interactivity,
2044
2320
  canvasEl = container.canvas.element;
2045
- if (!interactivity || !interactivity.element) {
2321
+ if (!interactivity?.element) {
2046
2322
  return;
2047
2323
  }
2048
2324
  interactivity.mouse.inside = true;
@@ -2066,8 +2342,8 @@ class EventListeners {
2066
2342
  targetRect = target.getBoundingClientRect(),
2067
2343
  canvasRect = canvasEl.getBoundingClientRect();
2068
2344
  pos = {
2069
- x: mouseEvent.offsetX + 2 * sourceRect.left - (targetRect.left + canvasRect.left),
2070
- y: mouseEvent.offsetY + 2 * sourceRect.top - (targetRect.top + canvasRect.top)
2345
+ x: mouseEvent.offsetX + EventListeners_double * sourceRect.left - (targetRect.left + canvasRect.left),
2346
+ y: mouseEvent.offsetY + EventListeners_double * sourceRect.top - (targetRect.top + canvasRect.top)
2071
2347
  };
2072
2348
  } else {
2073
2349
  pos = {
@@ -2085,11 +2361,13 @@ class EventListeners {
2085
2361
  this._canPush = e.type !== "touchmove";
2086
2362
  if (canvasEl) {
2087
2363
  const touchEvent = e,
2088
- lastTouch = touchEvent.touches[touchEvent.touches.length - 1],
2089
- canvasRect = canvasEl.getBoundingClientRect();
2364
+ lengthOffset = 1,
2365
+ lastTouch = touchEvent.touches[touchEvent.touches.length - lengthOffset],
2366
+ canvasRect = canvasEl.getBoundingClientRect(),
2367
+ defaultCoordinate = 0;
2090
2368
  pos = {
2091
- x: lastTouch.clientX - (canvasRect.left ?? 0),
2092
- y: lastTouch.clientY - (canvasRect.top ?? 0)
2369
+ x: lastTouch.clientX - (canvasRect.left ?? defaultCoordinate),
2370
+ y: lastTouch.clientY - (canvasRect.top ?? defaultCoordinate)
2093
2371
  };
2094
2372
  }
2095
2373
  }
@@ -2466,6 +2744,7 @@ class Interactivity {
2466
2744
  }
2467
2745
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ManualParticle.js
2468
2746
 
2747
+ const defaultPosition = 50;
2469
2748
  class ManualParticle {
2470
2749
  load(data) {
2471
2750
  if (!data) {
@@ -2473,8 +2752,8 @@ class ManualParticle {
2473
2752
  }
2474
2753
  if (data.position) {
2475
2754
  this.position = {
2476
- x: data.position.x ?? 50,
2477
- y: data.position.y ?? 50,
2755
+ x: data.position.x ?? defaultPosition,
2756
+ y: data.position.y ?? defaultPosition,
2478
2757
  mode: data.position.mode ?? "percent"
2479
2758
  };
2480
2759
  }
@@ -3563,6 +3842,9 @@ class Options {
3563
3842
  if (data.clear !== undefined) {
3564
3843
  this.clear = data.clear;
3565
3844
  }
3845
+ if (data.key !== undefined) {
3846
+ this.key = data.key;
3847
+ }
3566
3848
  if (data.name !== undefined) {
3567
3849
  this.name = data.name;
3568
3850
  }
@@ -3675,12 +3957,14 @@ class InteractionManager {
3675
3957
  }
3676
3958
  async externalInteract(delta) {
3677
3959
  for (const interactor of this._externalInteractors) {
3678
- interactor.isEnabled() && (await interactor.interact(delta));
3960
+ if (interactor.isEnabled()) {
3961
+ await interactor.interact(delta);
3962
+ }
3679
3963
  }
3680
3964
  }
3681
3965
  handleClickMode(mode) {
3682
3966
  for (const interactor of this._externalInteractors) {
3683
- interactor.handleClickMode && interactor.handleClickMode(mode);
3967
+ interactor.handleClickMode?.(mode);
3684
3968
  }
3685
3969
  }
3686
3970
  init() {
@@ -3703,15 +3987,21 @@ class InteractionManager {
3703
3987
  interactor.clear(particle, delta);
3704
3988
  }
3705
3989
  for (const interactor of this._particleInteractors) {
3706
- interactor.isEnabled(particle) && (await interactor.interact(particle, delta));
3990
+ if (interactor.isEnabled(particle)) {
3991
+ await interactor.interact(particle, delta);
3992
+ }
3707
3993
  }
3708
3994
  }
3709
- async reset(particle) {
3995
+ reset(particle) {
3710
3996
  for (const interactor of this._externalInteractors) {
3711
- interactor.isEnabled() && interactor.reset(particle);
3997
+ if (interactor.isEnabled()) {
3998
+ interactor.reset(particle);
3999
+ }
3712
4000
  }
3713
4001
  for (const interactor of this._particleInteractors) {
3714
- interactor.isEnabled(particle) && interactor.reset(particle);
4002
+ if (interactor.isEnabled(particle)) {
4003
+ interactor.reset(particle);
4004
+ }
3715
4005
  }
3716
4006
  }
3717
4007
  }
@@ -3725,6 +4015,10 @@ class InteractionManager {
3725
4015
 
3726
4016
 
3727
4017
 
4018
+ const defaultRetryCount = 0,
4019
+ Particle_double = 2,
4020
+ half = 0.5,
4021
+ Particle_squareExp = 2;
3728
4022
  function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
3729
4023
  const effectData = effectOptions.options[effect];
3730
4024
  if (!effectData) {
@@ -3749,7 +4043,7 @@ function fixOutMode(data) {
3749
4043
  if (!isInArray(data.outMode, data.checkModes)) {
3750
4044
  return;
3751
4045
  }
3752
- const diameter = data.radius * 2;
4046
+ const diameter = data.radius * Particle_double;
3753
4047
  if (data.coord > data.maxCoord - diameter) {
3754
4048
  data.setCb(-data.radius);
3755
4049
  } else if (data.coord < diameter) {
@@ -3759,7 +4053,7 @@ function fixOutMode(data) {
3759
4053
  class Particle {
3760
4054
  constructor(engine, id, container, position, overrideOptions, group) {
3761
4055
  this.container = container;
3762
- this._calcPosition = (container, position, zIndex, tryCount = 0) => {
4056
+ this._calcPosition = (container, position, zIndex, tryCount = defaultRetryCount) => {
3763
4057
  for (const [, plugin] of container.plugins) {
3764
4058
  const pluginPos = plugin.particlePosition !== undefined ? plugin.particlePosition(position, this) : undefined;
3765
4059
  if (pluginPos) {
@@ -3799,7 +4093,8 @@ class Particle {
3799
4093
  fixVertical(outModes.top ?? outModes.default);
3800
4094
  fixVertical(outModes.bottom ?? outModes.default);
3801
4095
  if (this._checkOverlap(pos, tryCount)) {
3802
- return this._calcPosition(container, undefined, zIndex, tryCount + 1);
4096
+ const increment = 1;
4097
+ return this._calcPosition(container, undefined, zIndex, tryCount + increment);
3803
4098
  }
3804
4099
  return pos;
3805
4100
  };
@@ -3810,11 +4105,11 @@ class Particle {
3810
4105
  if (moveOptions.direction === "inside" || moveOptions.direction === "outside") {
3811
4106
  return res;
3812
4107
  }
3813
- const rad = Math.PI / 180 * getRangeValue(moveOptions.angle.value),
3814
- radOffset = Math.PI / 180 * getRangeValue(moveOptions.angle.offset),
4108
+ const rad = degToRad(getRangeValue(moveOptions.angle.value)),
4109
+ radOffset = degToRad(getRangeValue(moveOptions.angle.offset)),
3815
4110
  range = {
3816
- left: radOffset - rad * 0.5,
3817
- right: radOffset + rad * 0.5
4111
+ left: radOffset - rad * half,
4112
+ right: radOffset + rad * half
3818
4113
  };
3819
4114
  if (!moveOptions.straight) {
3820
4115
  res.angle += randomInRange(setRangeValue(range.left, range.right));
@@ -3824,7 +4119,7 @@ class Particle {
3824
4119
  }
3825
4120
  return res;
3826
4121
  };
3827
- this._checkOverlap = (pos, tryCount = 0) => {
4122
+ this._checkOverlap = (pos, tryCount = defaultRetryCount) => {
3828
4123
  const collisionsOptions = this.options.collisions,
3829
4124
  radius = this.getRadius();
3830
4125
  if (!collisionsOptions.enable) {
@@ -3834,8 +4129,9 @@ class Particle {
3834
4129
  if (overlapOptions.enable) {
3835
4130
  return false;
3836
4131
  }
3837
- const retries = overlapOptions.retries;
3838
- if (retries >= 0 && tryCount > retries) {
4132
+ const retries = overlapOptions.retries,
4133
+ minRetries = 0;
4134
+ if (retries >= minRetries && tryCount > retries) {
3839
4135
  throw new Error(`${errorPrefix} particle is overlapping and can't be placed`);
3840
4136
  }
3841
4137
  return !!this.container.particles.find(particle => getDistance(pos, particle.position) < radius + particle.getRadius());
@@ -3844,9 +4140,11 @@ class Particle {
3844
4140
  if (!color || !this.roll || !this.backColor && !this.roll.alter) {
3845
4141
  return color;
3846
4142
  }
3847
- const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1,
3848
- backSum = this.roll.horizontal ? Math.PI * 0.5 : 0,
3849
- rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
4143
+ const rollFactor = 1,
4144
+ none = 0,
4145
+ backFactor = this.roll.horizontal && this.roll.vertical ? Particle_double * rollFactor : rollFactor,
4146
+ backSum = this.roll.horizontal ? Math.PI * half : none,
4147
+ rolled = Math.floor(((this.roll.angle ?? none) + backSum) / (Math.PI / backFactor)) % Particle_double;
3850
4148
  if (!rolled) {
3851
4149
  return color;
3852
4150
  }
@@ -3860,13 +4158,15 @@ class Particle {
3860
4158
  };
3861
4159
  this._initPosition = position => {
3862
4160
  const container = this.container,
3863
- zIndexValue = getRangeValue(this.options.zIndex.value);
3864
- this.position = this._calcPosition(container, position, clamp(zIndexValue, 0, container.zLayers));
4161
+ zIndexValue = getRangeValue(this.options.zIndex.value),
4162
+ minZ = 0;
4163
+ this.position = this._calcPosition(container, position, clamp(zIndexValue, minZ, container.zLayers));
3865
4164
  this.initialPosition = this.position.copy();
3866
- const canvasSize = container.canvas.size;
4165
+ const canvasSize = container.canvas.size,
4166
+ defaultRadius = 0;
3867
4167
  this.moveCenter = {
3868
4168
  ...getPosition(this.options.move.center, canvasSize),
3869
- radius: this.options.move.center.radius ?? 0,
4169
+ radius: this.options.move.center.radius ?? defaultRadius,
3870
4170
  mode: this.options.move.center.mode ?? "percent"
3871
4171
  };
3872
4172
  this.direction = getParticleDirectionAngle(this.options.move.direction, this.position, this.moveCenter);
@@ -3893,14 +4193,14 @@ class Particle {
3893
4193
  const container = this.container,
3894
4194
  pathGenerator = this.pathGenerator,
3895
4195
  shapeDrawer = container.shapeDrawers.get(this.shape);
3896
- shapeDrawer && shapeDrawer.particleDestroy && shapeDrawer.particleDestroy(this);
4196
+ shapeDrawer?.particleDestroy?.(this);
3897
4197
  for (const [, plugin] of container.plugins) {
3898
- plugin.particleDestroyed && plugin.particleDestroyed(this, override);
4198
+ plugin.particleDestroyed?.(this, override);
3899
4199
  }
3900
4200
  for (const updater of container.particles.updaters) {
3901
- updater.particleDestroyed && updater.particleDestroyed(this, override);
4201
+ updater.particleDestroyed?.(this, override);
3902
4202
  }
3903
- pathGenerator && pathGenerator.reset(this);
4203
+ pathGenerator?.reset(this);
3904
4204
  this._engine.dispatchEvent("particleDestroyed", {
3905
4205
  container: this.container,
3906
4206
  data: {
@@ -3920,7 +4220,7 @@ class Particle {
3920
4220
  return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.color));
3921
4221
  }
3922
4222
  getMass() {
3923
- return this.getRadius() ** 2 * Math.PI * 0.5;
4223
+ return this.getRadius() ** Particle_squareExp * Math.PI * half;
3924
4224
  }
3925
4225
  getPosition() {
3926
4226
  return {
@@ -3968,7 +4268,7 @@ class Particle {
3968
4268
  const effectOptions = particlesOptions.effect,
3969
4269
  shapeOptions = particlesOptions.shape;
3970
4270
  if (overrideOptions) {
3971
- if (overrideOptions.effect && overrideOptions.effect.type) {
4271
+ if (overrideOptions.effect?.type) {
3972
4272
  const overrideEffectType = overrideOptions.effect.type,
3973
4273
  effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
3974
4274
  if (effect) {
@@ -3976,7 +4276,7 @@ class Particle {
3976
4276
  effectOptions.load(overrideOptions.effect);
3977
4277
  }
3978
4278
  }
3979
- if (overrideOptions.shape && overrideOptions.shape.type) {
4279
+ if (overrideOptions.shape?.type) {
3980
4280
  const overrideShapeType = overrideOptions.shape.type,
3981
4281
  shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3982
4282
  if (shape) {
@@ -4006,7 +4306,7 @@ class Particle {
4006
4306
  this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
4007
4307
  this.options = particlesOptions;
4008
4308
  const pathOptions = this.options.move.path;
4009
- this.pathDelay = getRangeValue(pathOptions.delay.value) * 1000;
4309
+ this.pathDelay = getRangeValue(pathOptions.delay.value) * millisecondsToSeconds;
4010
4310
  if (pathOptions.generator) {
4011
4311
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
4012
4312
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
@@ -4025,7 +4325,8 @@ class Particle {
4025
4325
  this._initPosition(position);
4026
4326
  this.initialVelocity = this._calculateVelocity();
4027
4327
  this.velocity = this.initialVelocity.copy();
4028
- this.moveDecay = 1 - getRangeValue(this.options.move.decay);
4328
+ const decayOffset = 1;
4329
+ this.moveDecay = decayOffset - getRangeValue(this.options.move.decay);
4029
4330
  const particles = container.particles;
4030
4331
  particles.setLastZIndex(this.position.z);
4031
4332
  this.zIndexFactor = this.position.z / container.zLayers;
@@ -4037,7 +4338,7 @@ class Particle {
4037
4338
  container.effectDrawers.set(this.effect, effectDrawer);
4038
4339
  }
4039
4340
  }
4040
- if (effectDrawer && effectDrawer.loadEffect) {
4341
+ if (effectDrawer?.loadEffect) {
4041
4342
  effectDrawer.loadEffect(this);
4042
4343
  }
4043
4344
  let shapeDrawer = container.shapeDrawers.get(this.shape);
@@ -4047,7 +4348,7 @@ class Particle {
4047
4348
  container.shapeDrawers.set(this.shape, shapeDrawer);
4048
4349
  }
4049
4350
  }
4050
- if (shapeDrawer && shapeDrawer.loadShape) {
4351
+ if (shapeDrawer?.loadShape) {
4051
4352
  shapeDrawer.loadShape(this);
4052
4353
  }
4053
4354
  const sideCountFunc = shapeDrawer?.getSidesCount;
@@ -4060,16 +4361,12 @@ class Particle {
4060
4361
  updater.init(this);
4061
4362
  }
4062
4363
  for (const mover of particles.movers) {
4063
- mover.init && mover.init(this);
4064
- }
4065
- if (effectDrawer && effectDrawer.particleInit) {
4066
- effectDrawer.particleInit(container, this);
4067
- }
4068
- if (shapeDrawer && shapeDrawer.particleInit) {
4069
- shapeDrawer.particleInit(container, this);
4364
+ mover.init?.(this);
4070
4365
  }
4366
+ effectDrawer?.particleInit?.(container, this);
4367
+ shapeDrawer?.particleInit?.(container, this);
4071
4368
  for (const [, plugin] of container.plugins) {
4072
- plugin.particleCreated && plugin.particleCreated(this);
4369
+ plugin.particleCreated?.(this);
4073
4370
  }
4074
4371
  }
4075
4372
  isInsideCanvas() {
@@ -4083,7 +4380,7 @@ class Particle {
4083
4380
  }
4084
4381
  reset() {
4085
4382
  for (const updater of this.container.particles.updaters) {
4086
- updater.reset && updater.reset(this);
4383
+ updater.reset?.(this);
4087
4384
  }
4088
4385
  }
4089
4386
  }
@@ -4141,6 +4438,7 @@ class Rectangle extends Range {
4141
4438
 
4142
4439
 
4143
4440
 
4441
+ const Circle_squareExp = 2;
4144
4442
  class Circle extends Range {
4145
4443
  constructor(x, y, radius) {
4146
4444
  super(x, y);
@@ -4159,15 +4457,15 @@ class Circle extends Range {
4159
4457
  r = this.radius;
4160
4458
  if (range instanceof Circle) {
4161
4459
  const rSum = r + range.radius,
4162
- dist = Math.sqrt(distPos.x ** 2 + distPos.y ** 2);
4460
+ dist = Math.sqrt(distPos.x ** Circle_squareExp + distPos.y ** Circle_squareExp);
4163
4461
  return rSum > dist;
4164
4462
  } else if (range instanceof Rectangle) {
4165
4463
  const {
4166
4464
  width,
4167
4465
  height
4168
4466
  } = range.size,
4169
- edges = Math.pow(distPos.x - width, 2) + Math.pow(distPos.y - height, 2);
4170
- return edges <= r ** 2 || distPos.x <= r + width && distPos.y <= r + height || distPos.x <= width || distPos.y <= height;
4467
+ edges = Math.pow(distPos.x - width, Circle_squareExp) + Math.pow(distPos.y - height, Circle_squareExp);
4468
+ return edges <= r ** Circle_squareExp || distPos.x <= r + width && distPos.y <= r + height || distPos.x <= width || distPos.y <= height;
4171
4469
  }
4172
4470
  return false;
4173
4471
  }
@@ -4176,6 +4474,9 @@ class Circle extends Range {
4176
4474
 
4177
4475
 
4178
4476
 
4477
+ const QuadTree_half = 0.5,
4478
+ QuadTree_double = 2,
4479
+ subdivideCount = 4;
4179
4480
  class QuadTree {
4180
4481
  constructor(rectangle, capacity) {
4181
4482
  this.rectangle = rectangle;
@@ -4192,8 +4493,9 @@ class QuadTree {
4192
4493
  {
4193
4494
  capacity
4194
4495
  } = this;
4195
- for (let i = 0; i < 4; i++) {
4196
- this._subs.push(new QuadTree(new Rectangle(x + width * 0.5 * (i % 2), y + height * 0.5 * (Math.round(i * 0.5) - i % 2), width * 0.5, height * 0.5), capacity));
4496
+ for (let i = 0; i < subdivideCount; i++) {
4497
+ const fixedIndex = i % QuadTree_double;
4498
+ this._subs.push(new QuadTree(new Rectangle(x + width * QuadTree_half * fixedIndex, y + height * QuadTree_half * (Math.round(i * QuadTree_half) - fixedIndex), width * QuadTree_half, height * QuadTree_half), capacity));
4197
4499
  }
4198
4500
  this._divided = true;
4199
4501
  };
@@ -4215,7 +4517,7 @@ class QuadTree {
4215
4517
  return this._subs.some(sub => sub.insert(point));
4216
4518
  }
4217
4519
  query(range, check, found) {
4218
- const res = found || [];
4520
+ const res = found ?? [];
4219
4521
  if (!range.intersects(this.rectangle)) {
4220
4522
  return [];
4221
4523
  }
@@ -4247,7 +4549,9 @@ class QuadTree {
4247
4549
 
4248
4550
 
4249
4551
 
4250
- const qTreeCapacity = 4;
4552
+ const qTreeCapacity = 4,
4553
+ Particles_squareExp = 2,
4554
+ defaultRemoveQuantity = 1;
4251
4555
  const qTreeRectangle = canvasSize => {
4252
4556
  const {
4253
4557
  height,
@@ -4276,7 +4580,8 @@ class Particles {
4276
4580
  }
4277
4581
  const densityFactor = this._initDensityFactor(numberOptions.density),
4278
4582
  optParticlesNumber = numberOptions.value,
4279
- optParticlesLimit = numberOptions.limit.value > 0 ? numberOptions.limit.value : optParticlesNumber,
4583
+ minLimit = 0,
4584
+ optParticlesLimit = numberOptions.limit.value > minLimit ? numberOptions.limit.value : optParticlesNumber,
4280
4585
  particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount,
4281
4586
  particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
4282
4587
  if (group === undefined) {
@@ -4291,13 +4596,14 @@ class Particles {
4291
4596
  }
4292
4597
  };
4293
4598
  this._initDensityFactor = densityOptions => {
4294
- const container = this._container;
4599
+ const container = this._container,
4600
+ defaultFactor = 1;
4295
4601
  if (!container.canvas.element || !densityOptions.enable) {
4296
- return 1;
4602
+ return defaultFactor;
4297
4603
  }
4298
4604
  const canvas = container.canvas.element,
4299
4605
  pxRatio = container.retina.pixelRatio;
4300
- return canvas.width * canvas.height / (densityOptions.height * densityOptions.width * pxRatio ** 2);
4606
+ return canvas.width * canvas.height / (densityOptions.height * densityOptions.width * pxRatio ** Particles_squareExp);
4301
4607
  };
4302
4608
  this._pushParticle = (position, overrideOptions, group, initializer) => {
4303
4609
  try {
@@ -4326,7 +4632,6 @@ class Particles {
4326
4632
  return particle;
4327
4633
  } catch (e) {
4328
4634
  getLogger().warning(`${errorPrefix} adding particle: ${e}`);
4329
- return;
4330
4635
  }
4331
4636
  };
4332
4637
  this._removeParticle = (index, group, override) => {
@@ -4334,9 +4639,10 @@ class Particles {
4334
4639
  if (!particle || particle.group !== group) {
4335
4640
  return false;
4336
4641
  }
4337
- const zIdx = this._zArray.indexOf(particle);
4338
- this._array.splice(index, 1);
4339
- this._zArray.splice(zIdx, 1);
4642
+ const zIdx = this._zArray.indexOf(particle),
4643
+ deleteCount = 1;
4644
+ this._array.splice(index, deleteCount);
4645
+ this._zArray.splice(zIdx, deleteCount);
4340
4646
  particle.destroy(override);
4341
4647
  this._engine.dispatchEvent("particleRemoved", {
4342
4648
  container: this._container,
@@ -4376,11 +4682,14 @@ class Particles {
4376
4682
  addParticle(position, overrideOptions, group, initializer) {
4377
4683
  const limitOptions = this._container.actualOptions.particles.number.limit,
4378
4684
  limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit,
4379
- currentCount = this.count;
4380
- if (limit > 0) {
4685
+ currentCount = this.count,
4686
+ minLimit = 0;
4687
+ if (limit > minLimit) {
4381
4688
  if (limitOptions.mode === "delete") {
4382
- const countToRemove = currentCount + 1 - limit;
4383
- if (countToRemove > 0) {
4689
+ const countOffset = 1,
4690
+ minCount = 0,
4691
+ countToRemove = currentCount + countOffset - limit;
4692
+ if (countToRemove > minCount) {
4384
4693
  this.removeQuantity(countToRemove);
4385
4694
  }
4386
4695
  } else if (limitOptions.mode === "wait") {
@@ -4476,23 +4785,28 @@ class Particles {
4476
4785
  remove(particle, group, override) {
4477
4786
  this.removeAt(this._array.indexOf(particle), undefined, group, override);
4478
4787
  }
4479
- removeAt(index, quantity = 1, group, override) {
4480
- if (index < 0 || index > this.count) {
4788
+ removeAt(index, quantity = defaultRemoveQuantity, group, override) {
4789
+ const minIndex = 0;
4790
+ if (index < minIndex || index > this.count) {
4481
4791
  return;
4482
4792
  }
4483
4793
  let deleted = 0;
4484
4794
  for (let i = index; deleted < quantity && i < this.count; i++) {
4485
- this._removeParticle(i--, group, override) && deleted++;
4795
+ if (this._removeParticle(i--, group, override)) {
4796
+ deleted++;
4797
+ }
4486
4798
  }
4487
4799
  }
4488
4800
  removeQuantity(quantity, group) {
4489
- this.removeAt(0, quantity, group);
4801
+ const defaultIndex = 0;
4802
+ this.removeAt(defaultIndex, quantity, group);
4490
4803
  }
4491
4804
  setDensity() {
4492
4805
  const options = this._container.actualOptions,
4493
- groups = options.particles.groups;
4806
+ groups = options.particles.groups,
4807
+ manualCount = 0;
4494
4808
  for (const group in groups) {
4495
- this._applyDensity(groups[group], 0, group);
4809
+ this._applyDensity(groups[group], manualCount, group);
4496
4810
  }
4497
4811
  this._applyDensity(options.particles, options.manualParticles.length);
4498
4812
  }
@@ -4511,7 +4825,7 @@ class Particles {
4511
4825
  pathGenerator.update();
4512
4826
  }
4513
4827
  for (const [, plugin] of container.plugins) {
4514
- plugin.update && (await plugin.update(delta));
4828
+ await plugin.update?.(delta);
4515
4829
  }
4516
4830
  const resizeFactor = this._resizeFactor;
4517
4831
  for (const particle of this._array) {
@@ -4522,15 +4836,17 @@ class Particles {
4522
4836
  particle.initialPosition.y *= resizeFactor.height;
4523
4837
  }
4524
4838
  particle.ignoresResizeRatio = false;
4525
- await this._interactionManager.reset(particle);
4839
+ this._interactionManager.reset(particle);
4526
4840
  for (const [, plugin] of this._container.plugins) {
4527
4841
  if (particle.destroyed) {
4528
4842
  break;
4529
4843
  }
4530
- plugin.particleUpdate && plugin.particleUpdate(particle, delta);
4844
+ plugin.particleUpdate?.(particle, delta);
4531
4845
  }
4532
4846
  for (const mover of this.movers) {
4533
- mover.isEnabled(particle) && mover.move(particle, delta);
4847
+ if (mover.isEnabled(particle)) {
4848
+ mover.move(particle, delta);
4849
+ }
4534
4850
  }
4535
4851
  if (particle.destroyed) {
4536
4852
  particlesToDelete.add(particle);
@@ -4565,7 +4881,8 @@ class Particles {
4565
4881
  if (this._needsSort) {
4566
4882
  const zArray = this._zArray;
4567
4883
  zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
4568
- this._lastZIndex = zArray[zArray.length - 1].position.z;
4884
+ const lengthOffset = 1;
4885
+ this._lastZIndex = zArray[zArray.length - lengthOffset].position.z;
4569
4886
  this._needsSort = false;
4570
4887
  }
4571
4888
  }
@@ -4573,17 +4890,19 @@ class Particles {
4573
4890
  ;// CONCATENATED MODULE: ./dist/browser/Core/Retina.js
4574
4891
 
4575
4892
 
4893
+ const defaultRatio = 1,
4894
+ defaultReduceFactor = 1;
4576
4895
  class Retina {
4577
4896
  constructor(container) {
4578
4897
  this.container = container;
4579
- this.pixelRatio = 1;
4580
- this.reduceFactor = 1;
4898
+ this.pixelRatio = defaultRatio;
4899
+ this.reduceFactor = defaultReduceFactor;
4581
4900
  }
4582
4901
  init() {
4583
4902
  const container = this.container,
4584
4903
  options = container.actualOptions;
4585
- this.pixelRatio = !options.detectRetina || isSsr() ? 1 : window.devicePixelRatio;
4586
- this.reduceFactor = 1;
4904
+ this.pixelRatio = !options.detectRetina || isSsr() ? defaultRatio : window.devicePixelRatio;
4905
+ this.reduceFactor = defaultReduceFactor;
4587
4906
  const ratio = this.pixelRatio,
4588
4907
  canvas = container.canvas;
4589
4908
  if (canvas.element) {
@@ -4624,10 +4943,11 @@ class Retina {
4624
4943
  function guardCheck(container) {
4625
4944
  return container && !container.destroyed;
4626
4945
  }
4627
- function initDelta(value, fpsLimit = 60, smooth = false) {
4946
+ const defaultFps = 60;
4947
+ function initDelta(value, fpsLimit = defaultFps, smooth = false) {
4628
4948
  return {
4629
4949
  value,
4630
- factor: smooth ? 60 / fpsLimit : 60 * value / 1000
4950
+ factor: smooth ? defaultFps / fpsLimit : defaultFps * value / millisecondsToSeconds
4631
4951
  };
4632
4952
  }
4633
4953
  function loadContainerOptions(engine, container, ...sourceOptionsArr) {
@@ -4645,12 +4965,16 @@ class Container {
4645
4965
  if (entry.target !== this.interactivity.element) {
4646
4966
  continue;
4647
4967
  }
4648
- (entry.isIntersecting ? this.play : this.pause)();
4968
+ if (entry.isIntersecting) {
4969
+ this.play();
4970
+ } else {
4971
+ this.pause();
4972
+ }
4649
4973
  }
4650
4974
  };
4651
4975
  this._nextFrame = async timestamp => {
4652
4976
  try {
4653
- if (!this._smooth && this._lastFrameTime !== undefined && timestamp < this._lastFrameTime + 1000 / this.fpsLimit) {
4977
+ if (!this._smooth && this._lastFrameTime !== undefined && timestamp < this._lastFrameTime + millisecondsToSeconds / this.fpsLimit) {
4654
4978
  this.draw(false);
4655
4979
  return;
4656
4980
  }
@@ -4658,7 +4982,7 @@ class Container {
4658
4982
  const delta = initDelta(timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
4659
4983
  this.addLifeTime(delta.value);
4660
4984
  this._lastFrameTime = timestamp;
4661
- if (delta.value > 1000) {
4985
+ if (delta.value > millisecondsToSeconds) {
4662
4986
  this.draw(false);
4663
4987
  return;
4664
4988
  }
@@ -4745,8 +5069,9 @@ class Container {
4745
5069
  pos = {
4746
5070
  x: mouseEvent.offsetX || mouseEvent.clientX,
4747
5071
  y: mouseEvent.offsetY || mouseEvent.clientY
4748
- };
4749
- clickOrTouchHandler(e, pos, 1);
5072
+ },
5073
+ radius = 1;
5074
+ clickOrTouchHandler(e, pos, radius);
4750
5075
  };
4751
5076
  const touchStartHandler = () => {
4752
5077
  if (!guardCheck(this)) {
@@ -4767,18 +5092,20 @@ class Container {
4767
5092
  }
4768
5093
  if (touched && !touchMoved) {
4769
5094
  const touchEvent = e;
4770
- let lastTouch = touchEvent.touches[touchEvent.touches.length - 1];
5095
+ const lengthOffset = 1;
5096
+ let lastTouch = touchEvent.touches[touchEvent.touches.length - lengthOffset];
4771
5097
  if (!lastTouch) {
4772
- lastTouch = touchEvent.changedTouches[touchEvent.changedTouches.length - 1];
5098
+ lastTouch = touchEvent.changedTouches[touchEvent.changedTouches.length - lengthOffset];
4773
5099
  if (!lastTouch) {
4774
5100
  return;
4775
5101
  }
4776
5102
  }
4777
5103
  const element = this.canvas.element,
4778
5104
  canvasRect = element ? element.getBoundingClientRect() : undefined,
5105
+ minCoordinate = 0,
4779
5106
  pos = {
4780
- x: lastTouch.clientX - (canvasRect ? canvasRect.left : 0),
4781
- y: lastTouch.clientY - (canvasRect ? canvasRect.top : 0)
5107
+ x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
5108
+ y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate)
4782
5109
  };
4783
5110
  clickOrTouchHandler(e, pos, Math.max(lastTouch.radiusX, lastTouch.radiusY));
4784
5111
  }
@@ -4821,10 +5148,10 @@ class Container {
4821
5148
  this.particles.destroy();
4822
5149
  this.canvas.destroy();
4823
5150
  for (const [, effectDrawer] of this.effectDrawers) {
4824
- effectDrawer.destroy && effectDrawer.destroy(this);
5151
+ effectDrawer.destroy?.(this);
4825
5152
  }
4826
5153
  for (const [, shapeDrawer] of this.shapeDrawers) {
4827
- shapeDrawer.destroy && shapeDrawer.destroy(this);
5154
+ shapeDrawer.destroy?.(this);
4828
5155
  }
4829
5156
  for (const key of this.effectDrawers.keys()) {
4830
5157
  this.effectDrawers.delete(key);
@@ -4835,9 +5162,11 @@ class Container {
4835
5162
  this._engine.clearPlugins(this);
4836
5163
  this.destroyed = true;
4837
5164
  const mainArr = this._engine.dom(),
4838
- idx = mainArr.findIndex(t => t === this);
4839
- if (idx >= 0) {
4840
- mainArr.splice(idx, 1);
5165
+ idx = mainArr.findIndex(t => t === this),
5166
+ minIndex = 0;
5167
+ if (idx >= minIndex) {
5168
+ const deleteCount = 1;
5169
+ mainArr.splice(idx, deleteCount);
4841
5170
  }
4842
5171
  this._engine.dispatchEvent("containerDestroyed", {
4843
5172
  container: this
@@ -4848,13 +5177,14 @@ class Container {
4848
5177
  return;
4849
5178
  }
4850
5179
  let refreshTime = force;
4851
- this._drawAnimationFrame = requestAnimationFrame(async timestamp => {
5180
+ const frame = async timestamp => {
4852
5181
  if (refreshTime) {
4853
5182
  this._lastFrameTime = undefined;
4854
5183
  refreshTime = false;
4855
5184
  }
4856
5185
  await this._nextFrame(timestamp);
4857
- });
5186
+ };
5187
+ this._drawAnimationFrame = requestAnimationFrame(timestamp => void frame(timestamp));
4858
5188
  }
4859
5189
  async export(type, options = {}) {
4860
5190
  for (const [, plugin] of this.plugins) {
@@ -4878,7 +5208,7 @@ class Container {
4878
5208
  }
4879
5209
  this.particles.handleClickMode(mode);
4880
5210
  for (const [, plugin] of this.plugins) {
4881
- plugin.handleClickMode && plugin.handleClickMode(mode);
5211
+ plugin.handleClickMode?.(mode);
4882
5212
  }
4883
5213
  }
4884
5214
  async init() {
@@ -4911,19 +5241,21 @@ class Container {
4911
5241
  this.canvas.initBackground();
4912
5242
  this.canvas.resize();
4913
5243
  this.zLayers = this.actualOptions.zLayers;
4914
- this._duration = getRangeValue(this.actualOptions.duration) * 1000;
4915
- this._delay = getRangeValue(this.actualOptions.delay) * 1000;
5244
+ this._duration = getRangeValue(this.actualOptions.duration) * millisecondsToSeconds;
5245
+ this._delay = getRangeValue(this.actualOptions.delay) * millisecondsToSeconds;
4916
5246
  this._lifeTime = 0;
4917
- this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
5247
+ const defaultFpsLimit = 120,
5248
+ minFpsLimit = 0;
5249
+ this.fpsLimit = this.actualOptions.fpsLimit > minFpsLimit ? this.actualOptions.fpsLimit : defaultFpsLimit;
4918
5250
  this._smooth = this.actualOptions.smooth;
4919
5251
  for (const [, drawer] of this.effectDrawers) {
4920
- drawer.init && (await drawer.init(this));
5252
+ await drawer.init?.(this);
4921
5253
  }
4922
5254
  for (const [, drawer] of this.shapeDrawers) {
4923
- drawer.init && (await drawer.init(this));
5255
+ await drawer.init?.(this);
4924
5256
  }
4925
5257
  for (const [, plugin] of this.plugins) {
4926
- plugin.init && (await plugin.init());
5258
+ await plugin.init?.();
4927
5259
  }
4928
5260
  this._engine.dispatchEvent("containerInit", {
4929
5261
  container: this
@@ -4931,7 +5263,7 @@ class Container {
4931
5263
  this.particles.init();
4932
5264
  this.particles.setDensity();
4933
5265
  for (const [, plugin] of this.plugins) {
4934
- plugin.particlesSetup && plugin.particlesSetup();
5266
+ plugin.particlesSetup?.();
4935
5267
  }
4936
5268
  this._engine.dispatchEvent("particlesSetup", {
4937
5269
  container: this
@@ -4956,7 +5288,7 @@ class Container {
4956
5288
  return;
4957
5289
  }
4958
5290
  for (const [, plugin] of this.plugins) {
4959
- plugin.pause && plugin.pause();
5291
+ plugin.pause?.();
4960
5292
  }
4961
5293
  if (!this.pageHidden) {
4962
5294
  this._paused = true;
@@ -4987,7 +5319,7 @@ class Container {
4987
5319
  this._engine.dispatchEvent("containerPlay", {
4988
5320
  container: this
4989
5321
  });
4990
- this.draw(needsUpdate || false);
5322
+ this.draw(needsUpdate ?? false);
4991
5323
  }
4992
5324
  async refresh() {
4993
5325
  if (!guardCheck(this)) {
@@ -5012,20 +5344,21 @@ class Container {
5012
5344
  await this.init();
5013
5345
  this.started = true;
5014
5346
  await new Promise(resolve => {
5015
- this._delayTimeout = setTimeout(async () => {
5347
+ const start = async () => {
5016
5348
  this._eventListeners.addListeners();
5017
5349
  if (this.interactivity.element instanceof HTMLElement && this._intersectionObserver) {
5018
5350
  this._intersectionObserver.observe(this.interactivity.element);
5019
5351
  }
5020
5352
  for (const [, plugin] of this.plugins) {
5021
- plugin.start && (await plugin.start());
5353
+ await plugin.start?.();
5022
5354
  }
5023
5355
  this._engine.dispatchEvent("containerStarted", {
5024
5356
  container: this
5025
5357
  });
5026
5358
  this.play();
5027
5359
  resolve();
5028
- }, this._delay);
5360
+ };
5361
+ this._delayTimeout = setTimeout(() => void start(), this._delay);
5029
5362
  });
5030
5363
  }
5031
5364
  stop() {
@@ -5046,7 +5379,7 @@ class Container {
5046
5379
  this._intersectionObserver.unobserve(this.interactivity.element);
5047
5380
  }
5048
5381
  for (const [, plugin] of this.plugins) {
5049
- plugin.stop && plugin.stop();
5382
+ plugin.stop?.();
5050
5383
  }
5051
5384
  for (const key of this.plugins.keys()) {
5052
5385
  this.plugins.delete(key);
@@ -5083,7 +5416,7 @@ class EventDispatcher {
5083
5416
  }
5084
5417
  dispatchEvent(type, args) {
5085
5418
  const listeners = this._listeners.get(type);
5086
- listeners && listeners.forEach(handler => handler(args));
5419
+ listeners?.forEach(handler => handler(args));
5087
5420
  }
5088
5421
  hasEventListener(type) {
5089
5422
  return !!this._listeners.get(type);
@@ -5101,14 +5434,16 @@ class EventDispatcher {
5101
5434
  return;
5102
5435
  }
5103
5436
  const length = arr.length,
5104
- idx = arr.indexOf(listener);
5105
- if (idx < 0) {
5437
+ idx = arr.indexOf(listener),
5438
+ minIndex = 0;
5439
+ if (idx < minIndex) {
5106
5440
  return;
5107
5441
  }
5108
- if (length === 1) {
5442
+ const deleteCount = 1;
5443
+ if (length === deleteCount) {
5109
5444
  this._listeners.delete(type);
5110
5445
  } else {
5111
- arr.splice(idx, 1);
5446
+ arr.splice(idx, deleteCount);
5112
5447
  }
5113
5448
  }
5114
5449
  }
@@ -5166,21 +5501,23 @@ class Engine {
5166
5501
  return res;
5167
5502
  }
5168
5503
  get version() {
5169
- return "3.0.2";
5504
+ return "3.1.0";
5170
5505
  }
5171
5506
  addConfig(config) {
5172
- const name = config.name ?? "default";
5173
- this._configs.set(name, config);
5507
+ const key = config.key ?? config.name ?? "default";
5508
+ this._configs.set(key, config);
5174
5509
  this._eventDispatcher.dispatchEvent("configAdded", {
5175
5510
  data: {
5176
- name,
5511
+ name: key,
5177
5512
  config
5178
5513
  }
5179
5514
  });
5180
5515
  }
5181
5516
  async addEffect(effect, drawer, refresh = true) {
5182
5517
  executeOnSingleOrMultiple(effect, type => {
5183
- !this.getEffectDrawer(type) && this.effectDrawers.set(type, drawer);
5518
+ if (!this.getEffectDrawer(type)) {
5519
+ this.effectDrawers.set(type, drawer);
5520
+ }
5184
5521
  });
5185
5522
  await this.refresh(refresh);
5186
5523
  }
@@ -5200,20 +5537,28 @@ class Engine {
5200
5537
  await this.refresh(refresh);
5201
5538
  }
5202
5539
  async addPathGenerator(name, generator, refresh = true) {
5203
- !this.getPathGenerator(name) && this.pathGenerators.set(name, generator);
5540
+ if (!this.getPathGenerator(name)) {
5541
+ this.pathGenerators.set(name, generator);
5542
+ }
5204
5543
  await this.refresh(refresh);
5205
5544
  }
5206
5545
  async addPlugin(plugin, refresh = true) {
5207
- !this.getPlugin(plugin.id) && this.plugins.push(plugin);
5546
+ if (!this.getPlugin(plugin.id)) {
5547
+ this.plugins.push(plugin);
5548
+ }
5208
5549
  await this.refresh(refresh);
5209
5550
  }
5210
5551
  async addPreset(preset, options, override = false, refresh = true) {
5211
- (override || !this.getPreset(preset)) && this.presets.set(preset, options);
5552
+ if (override || !this.getPreset(preset)) {
5553
+ this.presets.set(preset, options);
5554
+ }
5212
5555
  await this.refresh(refresh);
5213
5556
  }
5214
5557
  async addShape(shape, drawer, refresh = true) {
5215
5558
  executeOnSingleOrMultiple(shape, type => {
5216
- !this.getShapeDrawer(type) && this.shapeDrawers.set(type, drawer);
5559
+ if (!this.getShapeDrawer(type)) {
5560
+ this.shapeDrawers.set(type, drawer);
5561
+ }
5217
5562
  });
5218
5563
  await this.refresh(refresh);
5219
5564
  }
@@ -5232,7 +5577,8 @@ class Engine {
5232
5577
  const dom = this.dom(),
5233
5578
  item = dom[index];
5234
5579
  if (!item || item.destroyed) {
5235
- dom.splice(index, 1);
5580
+ const deleteCount = 1;
5581
+ dom.splice(index, deleteCount);
5236
5582
  return;
5237
5583
  }
5238
5584
  return item;
@@ -5240,7 +5586,9 @@ class Engine {
5240
5586
  getAvailablePlugins(container) {
5241
5587
  const res = new Map();
5242
5588
  for (const plugin of this.plugins) {
5243
- plugin.needsPlugin(container.actualOptions) && res.set(plugin.id, plugin.getPlugin(container));
5589
+ if (plugin.needsPlugin(container.actualOptions)) {
5590
+ res.set(plugin.id, plugin.getPlugin(container));
5591
+ }
5244
5592
  }
5245
5593
  return res;
5246
5594
  }
@@ -5281,7 +5629,8 @@ class Engine {
5281
5629
  this._initialized = true;
5282
5630
  }
5283
5631
  async load(params) {
5284
- const id = params.id ?? `tsparticles${Math.floor(getRandom() * 10000)}`,
5632
+ const randomFactor = 10000,
5633
+ id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * randomFactor)}`,
5285
5634
  {
5286
5635
  index,
5287
5636
  url
@@ -5299,12 +5648,14 @@ class Engine {
5299
5648
  }
5300
5649
  const currentOptions = itemFromSingleOrMultiple(options, index),
5301
5650
  dom = this.dom(),
5302
- oldIndex = dom.findIndex(v => v.id.description === id);
5303
- if (oldIndex >= 0) {
5651
+ oldIndex = dom.findIndex(v => v.id.description === id),
5652
+ minIndex = 0;
5653
+ if (oldIndex >= minIndex) {
5304
5654
  const old = this.domItem(oldIndex);
5305
5655
  if (old && !old.destroyed) {
5306
5656
  old.destroy();
5307
- dom.splice(oldIndex, 1);
5657
+ const deleteCount = 1;
5658
+ dom.splice(oldIndex, deleteCount);
5308
5659
  }
5309
5660
  }
5310
5661
  let canvasEl;
@@ -5314,7 +5665,8 @@ class Engine {
5314
5665
  } else {
5315
5666
  const existingCanvases = domContainer.getElementsByTagName("canvas");
5316
5667
  if (existingCanvases.length) {
5317
- canvasEl = existingCanvases[0];
5668
+ const firstIndex = 0;
5669
+ canvasEl = existingCanvases[firstIndex];
5318
5670
  canvasEl.dataset[generatedAttribute] = "false";
5319
5671
  } else {
5320
5672
  canvasEl = document.createElement("canvas");
@@ -5329,8 +5681,9 @@ class Engine {
5329
5681
  canvasEl.style.height = "100%";
5330
5682
  }
5331
5683
  const newItem = new Container(this, id, currentOptions);
5332
- if (oldIndex >= 0) {
5333
- dom.splice(oldIndex, 0, newItem);
5684
+ if (oldIndex >= minIndex) {
5685
+ const deleteCount = 0;
5686
+ dom.splice(oldIndex, deleteCount, newItem);
5334
5687
  } else {
5335
5688
  dom.push(newItem);
5336
5689
  }
@@ -5349,14 +5702,14 @@ class Engine {
5349
5702
  return;
5350
5703
  }
5351
5704
  for (const updater of updaters) {
5352
- updater.loadOptions && updater.loadOptions(options, ...sourceOptions);
5705
+ updater.loadOptions?.(options, ...sourceOptions);
5353
5706
  }
5354
5707
  }
5355
5708
  async refresh(refresh = true) {
5356
5709
  if (!refresh) {
5357
5710
  return;
5358
5711
  }
5359
- this.dom().forEach(t => t.refresh());
5712
+ await Promise.allSettled(this.dom().map(t => t.refresh()));
5360
5713
  }
5361
5714
  removeEventListener(type, listener) {
5362
5715
  this._eventDispatcher.removeEventListener(type, listener);
@@ -5402,12 +5755,15 @@ class HslColorManager {
5402
5755
  return;
5403
5756
  }
5404
5757
  const regex = /hsla?\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*(,\s*([\d.%]+)\s*)?\)/i,
5405
- result = regex.exec(input);
5758
+ result = regex.exec(input),
5759
+ minLength = 4,
5760
+ defaultAlpha = 1,
5761
+ radix = 10;
5406
5762
  return result ? hslaToRgba({
5407
- a: result.length > 4 ? parseAlpha(result[5]) : 1,
5408
- h: parseInt(result[1], 10),
5409
- l: parseInt(result[3], 10),
5410
- s: parseInt(result[2], 10)
5763
+ a: result.length > minLength ? parseAlpha(result[5]) : defaultAlpha,
5764
+ h: parseInt(result[1], radix),
5765
+ l: parseInt(result[3], radix),
5766
+ s: parseInt(result[2], radix)
5411
5767
  }) : undefined;
5412
5768
  }
5413
5769
  }
@@ -5441,12 +5797,15 @@ class RgbColorManager {
5441
5797
  return;
5442
5798
  }
5443
5799
  const regex = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([\d.%]+)\s*)?\)/i,
5444
- result = regex.exec(input);
5800
+ result = regex.exec(input),
5801
+ radix = 10,
5802
+ minLength = 4,
5803
+ defaultAlpha = 1;
5445
5804
  return result ? {
5446
- a: result.length > 4 ? parseAlpha(result[5]) : 1,
5447
- b: parseInt(result[3], 10),
5448
- g: parseInt(result[2], 10),
5449
- r: parseInt(result[1], 10)
5805
+ a: result.length > minLength ? parseAlpha(result[5]) : defaultAlpha,
5806
+ b: parseInt(result[3], radix),
5807
+ g: parseInt(result[2], radix),
5808
+ r: parseInt(result[1], radix)
5450
5809
  } : undefined;
5451
5810
  }
5452
5811
  }
@@ -5467,15 +5826,15 @@ function init() {
5467
5826
  ;// CONCATENATED MODULE: ./dist/browser/Core/Utils/ExternalInteractorBase.js
5468
5827
  class ExternalInteractorBase {
5469
5828
  constructor(container) {
5470
- this.container = container;
5471
5829
  this.type = "external";
5830
+ this.container = container;
5472
5831
  }
5473
5832
  }
5474
5833
  ;// CONCATENATED MODULE: ./dist/browser/Core/Utils/ParticlesInteractorBase.js
5475
5834
  class ParticlesInteractorBase {
5476
5835
  constructor(container) {
5477
- this.container = container;
5478
5836
  this.type = "particles";
5837
+ this.container = container;
5479
5838
  }
5480
5839
  }
5481
5840
  ;// CONCATENATED MODULE: ./dist/browser/exports.js