@tsparticles/engine 3.0.0-beta.2 → 3.0.0-beta.4

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 (186) hide show
  1. package/browser/Core/Canvas.js +2 -2
  2. package/browser/Core/Container.js +39 -24
  3. package/browser/Core/Engine.js +26 -53
  4. package/browser/Core/Particle.js +88 -53
  5. package/browser/Core/Particles.js +51 -26
  6. package/browser/Core/Retina.js +0 -2
  7. package/browser/Core/Utils/QuadTree.js +1 -1
  8. package/browser/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  9. package/browser/Options/Classes/ColorAnimation.js +4 -24
  10. package/browser/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  11. package/browser/Options/Classes/Particles/Effect/Effect.js +32 -0
  12. package/browser/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  13. package/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js +17 -0
  14. package/browser/Options/Classes/Particles/Opacity/Opacity.js +2 -3
  15. package/browser/Options/Classes/Particles/ParticlesOptions.js +3 -0
  16. package/browser/Options/Classes/Particles/Size/Size.js +2 -3
  17. package/browser/Options/Classes/ValueWithRandom.js +1 -10
  18. package/browser/Utils/CanvasUtils.js +29 -21
  19. package/browser/Utils/ColorUtils.js +24 -38
  20. package/browser/Utils/NumberUtils.js +7 -16
  21. package/browser/Utils/Utils.js +13 -7
  22. package/browser/export-types.js +4 -2
  23. package/browser/exports.js +2 -3
  24. package/cjs/Core/Canvas.js +2 -2
  25. package/cjs/Core/Container.js +39 -24
  26. package/cjs/Core/Engine.js +25 -52
  27. package/cjs/Core/Particle.js +87 -52
  28. package/cjs/Core/Particles.js +51 -26
  29. package/cjs/Core/Retina.js +0 -2
  30. package/cjs/Core/Utils/QuadTree.js +1 -1
  31. package/cjs/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  32. package/cjs/Options/Classes/ColorAnimation.js +4 -24
  33. package/cjs/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  34. package/cjs/Options/Classes/Particles/Effect/Effect.js +36 -0
  35. package/cjs/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  36. package/cjs/Options/Classes/Particles/Number/ParticlesNumberLimit.js +21 -0
  37. package/cjs/Options/Classes/Particles/Opacity/Opacity.js +1 -2
  38. package/cjs/Options/Classes/Particles/ParticlesOptions.js +3 -0
  39. package/cjs/Options/Classes/Particles/Size/Size.js +2 -3
  40. package/cjs/Options/Classes/ValueWithRandom.js +1 -10
  41. package/cjs/Utils/CanvasUtils.js +32 -24
  42. package/cjs/Utils/ColorUtils.js +24 -38
  43. package/cjs/Utils/NumberUtils.js +8 -18
  44. package/cjs/Utils/Utils.js +14 -7
  45. package/cjs/export-types.js +4 -2
  46. package/cjs/exports.js +2 -3
  47. package/esm/Core/Canvas.js +2 -2
  48. package/esm/Core/Container.js +39 -24
  49. package/esm/Core/Engine.js +26 -53
  50. package/esm/Core/Particle.js +88 -53
  51. package/esm/Core/Particles.js +51 -26
  52. package/esm/Core/Retina.js +0 -2
  53. package/esm/Core/Utils/QuadTree.js +1 -1
  54. package/esm/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  55. package/esm/Options/Classes/ColorAnimation.js +4 -24
  56. package/esm/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  57. package/esm/Options/Classes/Particles/Effect/Effect.js +32 -0
  58. package/esm/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  59. package/esm/Options/Classes/Particles/Number/ParticlesNumberLimit.js +17 -0
  60. package/esm/Options/Classes/Particles/Opacity/Opacity.js +2 -3
  61. package/esm/Options/Classes/Particles/ParticlesOptions.js +3 -0
  62. package/esm/Options/Classes/Particles/Size/Size.js +2 -3
  63. package/esm/Options/Classes/ValueWithRandom.js +1 -10
  64. package/esm/Utils/CanvasUtils.js +29 -21
  65. package/esm/Utils/ColorUtils.js +24 -38
  66. package/esm/Utils/NumberUtils.js +7 -16
  67. package/esm/Utils/Utils.js +13 -7
  68. package/esm/export-types.js +4 -2
  69. package/esm/exports.js +2 -3
  70. package/package.json +1 -1
  71. package/report.html +4 -22
  72. package/tsparticles.engine.js +461 -347
  73. package/tsparticles.engine.min.js +1 -1
  74. package/tsparticles.engine.min.js.LICENSE.txt +1 -1
  75. package/types/Core/Canvas.d.ts +0 -1
  76. package/types/Core/Container.d.ts +9 -8
  77. package/types/Core/Engine.d.ts +9 -5
  78. package/types/Core/Interfaces/IContainerPlugin.d.ts +2 -3
  79. package/types/Core/Interfaces/IEffectDrawer.d.ts +10 -0
  80. package/types/Core/Interfaces/IExternalInteractor.d.ts +3 -4
  81. package/types/Core/Interfaces/IInteractor.d.ts +3 -3
  82. package/types/Core/Interfaces/IParticleRetinaProps.d.ts +0 -1
  83. package/types/Core/Interfaces/IParticlesInteractor.d.ts +3 -3
  84. package/types/Core/Interfaces/IShapeDrawData.d.ts +10 -0
  85. package/types/Core/Interfaces/IShapeDrawer.d.ts +11 -9
  86. package/types/Core/Particle.d.ts +7 -5
  87. package/types/Core/Particles.d.ts +10 -7
  88. package/types/Core/Retina.d.ts +0 -1
  89. package/types/Core/Utils/ExternalInteractorBase.d.ts +4 -4
  90. package/types/Core/Utils/InteractionManager.d.ts +1 -2
  91. package/types/Core/Utils/ParticlesInteractorBase.d.ts +5 -5
  92. package/types/Enums/Modes/LimitMode.d.ts +4 -0
  93. package/types/Enums/Types/EasingType.d.ts +3 -0
  94. package/types/Enums/Types/EventType.d.ts +1 -0
  95. package/types/Options/Classes/BackgroundMask/BackgroundMask.d.ts +1 -1
  96. package/types/Options/Classes/ColorAnimation.d.ts +2 -7
  97. package/types/Options/Classes/Interactivity/Events/ClickEvent.d.ts +1 -2
  98. package/types/Options/Classes/Interactivity/Events/DivEvent.d.ts +1 -2
  99. package/types/Options/Classes/Interactivity/Events/Events.d.ts +3 -3
  100. package/types/Options/Classes/Interactivity/Events/HoverEvent.d.ts +2 -3
  101. package/types/Options/Classes/Interactivity/Interactivity.d.ts +2 -2
  102. package/types/Options/Classes/Options.d.ts +6 -6
  103. package/types/Options/Classes/Particles/Bounce/ParticlesBounce.d.ts +2 -2
  104. package/types/Options/Classes/Particles/Collisions/Collisions.d.ts +3 -3
  105. package/types/Options/Classes/Particles/Effect/Effect.d.ts +13 -0
  106. package/types/Options/Classes/Particles/Move/Move.d.ts +8 -8
  107. package/types/Options/Classes/Particles/Move/MoveTrail.d.ts +1 -1
  108. package/types/Options/Classes/Particles/Number/ParticlesNumber.d.ts +3 -2
  109. package/types/Options/Classes/Particles/Number/ParticlesNumberLimit.d.ts +10 -0
  110. package/types/Options/Classes/Particles/Opacity/Opacity.d.ts +3 -3
  111. package/types/Options/Classes/Particles/ParticlesOptions.d.ts +12 -10
  112. package/types/Options/Classes/Particles/Size/Size.d.ts +3 -3
  113. package/types/Options/Classes/Theme/Theme.d.ts +1 -1
  114. package/types/Options/Classes/ValueWithRandom.d.ts +2 -4
  115. package/types/Options/Interfaces/IValueWithRandom.d.ts +0 -2
  116. package/types/Options/Interfaces/Interactivity/Events/IClickEvent.d.ts +1 -2
  117. package/types/Options/Interfaces/Interactivity/Events/IDivEvent.d.ts +1 -2
  118. package/types/Options/Interfaces/Interactivity/Events/IHoverEvent.d.ts +1 -2
  119. package/types/Options/Interfaces/Particles/Effect/IEffect.d.ts +8 -0
  120. package/types/Options/Interfaces/Particles/IParticlesOptions.d.ts +2 -0
  121. package/types/Options/Interfaces/Particles/Number/IParticlesNumber.d.ts +2 -1
  122. package/types/Options/Interfaces/Particles/Number/IParticlesNumberLimit.d.ts +5 -0
  123. package/types/Types/CustomEventArgs.d.ts +1 -1
  124. package/types/Utils/CanvasUtils.d.ts +12 -3
  125. package/types/Utils/ColorUtils.d.ts +2 -2
  126. package/types/Utils/NumberUtils.d.ts +0 -2
  127. package/types/Utils/Utils.d.ts +6 -6
  128. package/types/export-types.d.ts +5 -2
  129. package/types/exports.d.ts +2 -3
  130. package/umd/Core/Canvas.js +2 -2
  131. package/umd/Core/Container.js +40 -25
  132. package/umd/Core/Engine.js +25 -52
  133. package/umd/Core/Particle.js +87 -52
  134. package/umd/Core/Particles.js +51 -26
  135. package/umd/Core/Retina.js +0 -2
  136. package/umd/Core/Utils/QuadTree.js +1 -1
  137. package/umd/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  138. package/umd/Options/Classes/ColorAnimation.js +5 -25
  139. package/umd/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  140. package/umd/Options/Classes/Particles/Effect/Effect.js +46 -0
  141. package/umd/Options/Classes/Particles/Number/ParticlesNumber.js +4 -6
  142. package/umd/Options/Classes/{Random.js → Particles/Number/ParticlesNumberLimit.js} +9 -9
  143. package/umd/Options/Classes/Particles/Opacity/Opacity.js +1 -2
  144. package/umd/Options/Classes/Particles/ParticlesOptions.js +4 -1
  145. package/umd/Options/Classes/Particles/Size/Size.js +3 -4
  146. package/umd/Options/Classes/ValueWithRandom.js +2 -11
  147. package/umd/Utils/CanvasUtils.js +32 -24
  148. package/umd/Utils/ColorUtils.js +24 -38
  149. package/umd/Utils/NumberUtils.js +9 -19
  150. package/umd/Utils/Utils.js +14 -7
  151. package/umd/export-types.js +5 -3
  152. package/umd/exports.js +3 -4
  153. package/browser/Options/Classes/Random.js +0 -17
  154. package/cjs/Options/Classes/Random.js +0 -21
  155. package/cjs/Types/ShapeDrawerFunctions.js +0 -2
  156. package/esm/Options/Classes/Random.js +0 -17
  157. package/esm/Options/Interfaces/IRandom.js +0 -1
  158. package/esm/Types/ShapeDrawerFunctions.js +0 -1
  159. package/types/Core/Interfaces/IParticle.d.ts +0 -48
  160. package/types/Enums/Modes/ClickMode.d.ts +0 -9
  161. package/types/Enums/Modes/DivMode.d.ts +0 -5
  162. package/types/Enums/Modes/HoverMode.d.ts +0 -11
  163. package/types/Options/Classes/Random.d.ts +0 -9
  164. package/types/Options/Interfaces/IRandom.d.ts +0 -4
  165. package/types/Types/ShapeDrawerFunctions.d.ts +0 -10
  166. package/umd/Types/ShapeDrawerFunctions.js +0 -12
  167. /package/browser/Core/Interfaces/{IParticle.js → IEffectDrawer.js} +0 -0
  168. /package/browser/{Enums/Modes/ClickMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  169. /package/browser/Enums/Modes/{DivMode.js → LimitMode.js} +0 -0
  170. /package/browser/{Enums/Modes/HoverMode.js → Options/Interfaces/Particles/Effect/IEffect.js} +0 -0
  171. /package/browser/Options/Interfaces/{IRandom.js → Particles/Number/IParticlesNumberLimit.js} +0 -0
  172. /package/cjs/Core/Interfaces/{IParticle.js → IEffectDrawer.js} +0 -0
  173. /package/cjs/{Enums/Modes/ClickMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  174. /package/cjs/Enums/Modes/{DivMode.js → LimitMode.js} +0 -0
  175. /package/cjs/{Enums/Modes/HoverMode.js → Options/Interfaces/Particles/Effect/IEffect.js} +0 -0
  176. /package/cjs/Options/Interfaces/{IRandom.js → Particles/Number/IParticlesNumberLimit.js} +0 -0
  177. /package/{browser/Types/ShapeDrawerFunctions.js → esm/Core/Interfaces/IEffectDrawer.js} +0 -0
  178. /package/esm/Core/Interfaces/{IParticle.js → IShapeDrawData.js} +0 -0
  179. /package/esm/Enums/Modes/{ClickMode.js → LimitMode.js} +0 -0
  180. /package/esm/{Enums/Modes/DivMode.js → Options/Interfaces/Particles/Effect/IEffect.js} +0 -0
  181. /package/esm/{Enums/Modes/HoverMode.js → Options/Interfaces/Particles/Number/IParticlesNumberLimit.js} +0 -0
  182. /package/umd/Core/Interfaces/{IParticle.js → IEffectDrawer.js} +0 -0
  183. /package/umd/{Enums/Modes/ClickMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  184. /package/umd/Enums/Modes/{DivMode.js → LimitMode.js} +0 -0
  185. /package/umd/{Enums/Modes/HoverMode.js → Options/Interfaces/Particles/Effect/IEffect.js} +0 -0
  186. /package/umd/Options/Interfaces/{IRandom.js → Particles/Number/IParticlesNumberLimit.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * tsParticles Engine v3.0.0-beta.2
2
+ * tsParticles Engine v3.0.0-beta.4
3
3
  * Author: Matteo Bruni
4
4
  * MIT license: https://opensource.org/licenses/MIT
5
5
  * Website: https://particles.js.org/
@@ -99,6 +99,7 @@ __webpack_require__.d(__webpack_exports__, {
99
99
  ParticlesDensity: () => (/* reexport */ ParticlesDensity),
100
100
  ParticlesInteractorBase: () => (/* reexport */ ParticlesInteractorBase),
101
101
  ParticlesNumber: () => (/* reexport */ ParticlesNumber),
102
+ ParticlesNumberLimit: () => (/* reexport */ ParticlesNumberLimit),
102
103
  ParticlesOptions: () => (/* reexport */ ParticlesOptions),
103
104
  Point: () => (/* reexport */ Point),
104
105
  Range: () => (/* reexport */ Range),
@@ -142,13 +143,13 @@ __webpack_require__.d(__webpack_exports__, {
142
143
  deepExtend: () => (/* reexport */ deepExtend),
143
144
  divMode: () => (/* reexport */ divMode),
144
145
  divModeExecute: () => (/* reexport */ divModeExecute),
146
+ drawEffect: () => (/* reexport */ drawEffect),
145
147
  drawLine: () => (/* reexport */ drawLine),
146
148
  drawParticle: () => (/* reexport */ drawParticle),
147
149
  drawParticlePlugin: () => (/* reexport */ drawParticlePlugin),
148
150
  drawPlugin: () => (/* reexport */ drawPlugin),
149
151
  drawShape: () => (/* reexport */ drawShape),
150
- drawShapeAfterEffect: () => (/* reexport */ drawShapeAfterEffect),
151
- drawTriangle: () => (/* reexport */ drawTriangle),
152
+ drawShapeAfterDraw: () => (/* reexport */ drawShapeAfterDraw),
152
153
  errorPrefix: () => (/* reexport */ errorPrefix),
153
154
  executeOnSingleOrMultiple: () => (/* reexport */ executeOnSingleOrMultiple),
154
155
  findItemFromSingleOrMultiple: () => (/* reexport */ findItemFromSingleOrMultiple),
@@ -172,7 +173,6 @@ __webpack_require__.d(__webpack_exports__, {
172
173
  getSize: () => (/* reexport */ getSize),
173
174
  getStyleFromHsl: () => (/* reexport */ getStyleFromHsl),
174
175
  getStyleFromRgb: () => (/* reexport */ getStyleFromRgb),
175
- getValue: () => (/* reexport */ getValue),
176
176
  hasMatchMedia: () => (/* reexport */ hasMatchMedia),
177
177
  hslToRgb: () => (/* reexport */ hslToRgb),
178
178
  hslaToRgba: () => (/* reexport */ hslaToRgba),
@@ -207,6 +207,7 @@ __webpack_require__.d(__webpack_exports__, {
207
207
  rectBounce: () => (/* reexport */ rectBounce),
208
208
  resizeEvent: () => (/* reexport */ resizeEvent),
209
209
  rgbToHsl: () => (/* reexport */ rgbToHsl),
210
+ safeIntersectionObserver: () => (/* reexport */ safeIntersectionObserver),
210
211
  safeMatchMedia: () => (/* reexport */ safeMatchMedia),
211
212
  safeMutationObserver: () => (/* reexport */ safeMutationObserver),
212
213
  setLogger: () => (/* reexport */ setLogger),
@@ -410,17 +411,6 @@ function setRangeValue(source, value) {
410
411
  max: Math.max(max, value)
411
412
  } : setRangeValue(min, max);
412
413
  }
413
- function getValue(options) {
414
- const random = options.random,
415
- {
416
- enable,
417
- minimumValue
418
- } = isBoolean(random) ? {
419
- enable: random,
420
- minimumValue: 0
421
- } : random;
422
- return enable ? getRangeValue(setRangeValue(options.value, minimumValue)) : getRangeValue(options.value);
423
- }
424
414
  function getDistances(pointA, pointB) {
425
415
  const dx = pointA.x - pointB.x,
426
416
  dy = pointA.y - pointB.y;
@@ -439,21 +429,21 @@ function getParticleDirectionAngle(direction, position, center) {
439
429
  }
440
430
  switch (direction) {
441
431
  case "top":
442
- return -Math.PI / 2;
432
+ return -Math.PI * 0.5;
443
433
  case "top-right":
444
- return -Math.PI / 4;
434
+ return -Math.PI * 0.25;
445
435
  case "right":
446
436
  return 0;
447
437
  case "bottom-right":
448
- return Math.PI / 4;
438
+ return Math.PI * 0.25;
449
439
  case "bottom":
450
- return Math.PI / 2;
440
+ return Math.PI * 0.5;
451
441
  case "bottom-left":
452
- return 3 * Math.PI / 4;
442
+ return Math.PI * 0.75;
453
443
  case "left":
454
444
  return Math.PI;
455
445
  case "top-left":
456
- return -3 * Math.PI / 4;
446
+ return -Math.PI * 0.75;
457
447
  case "inside":
458
448
  return Math.atan2(center.y - position.y, center.x - position.x);
459
449
  case "outside":
@@ -549,7 +539,7 @@ function rectSideBounce(data) {
549
539
  if (pOtherSide.min < rectOtherSide.min || pOtherSide.min > rectOtherSide.max || pOtherSide.max < rectOtherSide.min || pOtherSide.max > rectOtherSide.max) {
550
540
  return res;
551
541
  }
552
- if (pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) / 2 && velocity > 0 || pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) / 2 && velocity < 0) {
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) {
553
543
  res.velocity = velocity * -factor;
554
544
  res.bounced = true;
555
545
  }
@@ -573,6 +563,12 @@ function safeMatchMedia(query) {
573
563
  }
574
564
  return matchMedia(query);
575
565
  }
566
+ function safeIntersectionObserver(callback) {
567
+ if (isSsr() || typeof IntersectionObserver === "undefined") {
568
+ return;
569
+ }
570
+ return new IntersectionObserver(callback);
571
+ }
576
572
  function safeMutationObserver(callback) {
577
573
  if (isSsr() || typeof MutationObserver === "undefined") {
578
574
  return;
@@ -679,7 +675,7 @@ function circleBounceDataFromParticle(p) {
679
675
  radius: p.getRadius(),
680
676
  mass: p.getMass(),
681
677
  velocity: p.velocity,
682
- factor: Vector.create(getValue(p.options.bounce.horizontal), getValue(p.options.bounce.vertical))
678
+ factor: Vector.create(getRangeValue(p.options.bounce.horizontal.value), getRangeValue(p.options.bounce.vertical.value))
683
679
  };
684
680
  }
685
681
  function circleBounce(p1, p2) {
@@ -713,6 +709,7 @@ function rectBounce(particle, divBounds) {
713
709
  const pPos = particle.getPosition(),
714
710
  size = particle.getRadius(),
715
711
  bounds = calculateBounds(pPos, size),
712
+ bounceOptions = particle.options.bounce,
716
713
  resH = rectSideBounce({
717
714
  pSide: {
718
715
  min: bounds.left,
@@ -731,7 +728,7 @@ function rectBounce(particle, divBounds) {
731
728
  max: divBounds.bottom
732
729
  },
733
730
  velocity: particle.velocity.x,
734
- factor: getValue(particle.options.bounce.horizontal)
731
+ factor: getRangeValue(bounceOptions.horizontal.value)
735
732
  });
736
733
  if (resH.bounced) {
737
734
  if (resH.velocity !== undefined) {
@@ -759,7 +756,7 @@ function rectBounce(particle, divBounds) {
759
756
  max: divBounds.right
760
757
  },
761
758
  velocity: particle.velocity.y,
762
- factor: getValue(particle.options.bounce.vertical)
759
+ factor: getRangeValue(bounceOptions.vertical.value)
763
760
  });
764
761
  if (resV.bounced) {
765
762
  if (resV.velocity !== undefined) {
@@ -886,24 +883,6 @@ const randomColorValue = "random",
886
883
  function addColorManager(manager) {
887
884
  colorManagers.set(manager.key, manager);
888
885
  }
889
- function hue2rgb(p, q, t) {
890
- if (t < 0) {
891
- t += 1;
892
- }
893
- if (t > 1) {
894
- t -= 1;
895
- }
896
- if (t < 1 / 6) {
897
- return p + (q - p) * 6 * t;
898
- }
899
- if (t < 1 / 2) {
900
- return q;
901
- }
902
- if (t < 2 / 3) {
903
- return p + (q - p) * (2 / 3 - t) * 6;
904
- }
905
- return p;
906
- }
907
886
  function stringToRgba(input) {
908
887
  for (const [, manager] of colorManagers) {
909
888
  if (input.startsWith(manager.stringPrefix)) {
@@ -983,7 +962,7 @@ function rgbToHsl(color) {
983
962
  min = Math.min(r1, g1, b1),
984
963
  res = {
985
964
  h: 0,
986
- l: (max + min) / 2,
965
+ l: (max + min) * 0.5,
987
966
  s: 0
988
967
  };
989
968
  if (max !== min) {
@@ -1008,29 +987,48 @@ function stringToRgb(input) {
1008
987
  return stringToRgba(input);
1009
988
  }
1010
989
  function hslToRgb(hsl) {
1011
- const result = {
1012
- b: 0,
1013
- g: 0,
1014
- r: 0
1015
- },
1016
- hslPercent = {
1017
- h: hsl.h / 360,
1018
- l: hsl.l / 100,
1019
- s: hsl.s / 100
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);
998
+ return {
999
+ r: grayscaleValue,
1000
+ g: grayscaleValue,
1001
+ b: grayscaleValue
1020
1002
  };
1021
- if (!hslPercent.s) {
1022
- result.r = result.g = result.b = hslPercent.l;
1023
- } else {
1024
- const q = hslPercent.l < 0.5 ? hslPercent.l * (1 + hslPercent.s) : hslPercent.l + hslPercent.s - hslPercent.l * hslPercent.s,
1025
- p = 2 * hslPercent.l - q;
1026
- result.r = hue2rgb(p, q, hslPercent.h + 1 / 3);
1027
- result.g = hue2rgb(p, q, hslPercent.h);
1028
- result.b = hue2rgb(p, q, hslPercent.h - 1 / 3);
1029
1003
  }
1030
- result.r = Math.floor(result.r * 255);
1031
- result.g = Math.floor(result.g * 255);
1032
- result.b = Math.floor(result.b * 255);
1033
- return result;
1004
+ const channel = (temp1, temp2, temp3) => {
1005
+ if (temp3 < 0) {
1006
+ temp3 += 1;
1007
+ }
1008
+ if (temp3 > 1) {
1009
+ temp3 -= 1;
1010
+ }
1011
+ if (temp3 * 6 < 1) {
1012
+ return temp1 + (temp2 - temp1) * 6 * temp3;
1013
+ }
1014
+ if (temp3 * 2 < 1) {
1015
+ return temp2;
1016
+ }
1017
+ if (temp3 * 3 < 2) {
1018
+ return temp1 + (temp2 - temp1) * (2 / 3 - temp3) * 6;
1019
+ }
1020
+ return temp1;
1021
+ },
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));
1027
+ return {
1028
+ r: Math.round(red),
1029
+ g: Math.round(green),
1030
+ b: Math.round(blue)
1031
+ };
1034
1032
  }
1035
1033
  function hslaToRgba(hsla) {
1036
1034
  const rgbResult = hslToRgb(hsla);
@@ -1164,13 +1162,6 @@ function drawLine(context, begin, end) {
1164
1162
  context.lineTo(end.x, end.y);
1165
1163
  context.closePath();
1166
1164
  }
1167
- function drawTriangle(context, p1, p2, p3) {
1168
- context.beginPath();
1169
- context.moveTo(p1.x, p1.y);
1170
- context.lineTo(p2.x, p2.y);
1171
- context.lineTo(p3.x, p3.y);
1172
- context.closePath();
1173
- }
1174
1165
  function paintBase(context, dimension, baseColor) {
1175
1166
  context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1176
1167
  context.fillRect(0, 0, dimension.width, dimension.height);
@@ -1213,7 +1204,6 @@ function drawParticle(data) {
1213
1204
  d: rotateData.cos * (transform.d ?? 1)
1214
1205
  };
1215
1206
  context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1216
- context.beginPath();
1217
1207
  if (backgroundMask) {
1218
1208
  context.globalCompositeOperation = composite;
1219
1209
  }
@@ -1232,39 +1222,104 @@ function drawParticle(data) {
1232
1222
  if (colorStyles.stroke) {
1233
1223
  context.strokeStyle = colorStyles.stroke;
1234
1224
  }
1235
- drawShape(container, context, particle, radius, opacity, delta);
1225
+ const drawData = {
1226
+ container,
1227
+ context,
1228
+ particle,
1229
+ radius,
1230
+ opacity,
1231
+ delta
1232
+ };
1233
+ context.beginPath();
1234
+ drawShape(drawData);
1235
+ if (particle.shapeClose) {
1236
+ context.closePath();
1237
+ }
1236
1238
  if (strokeWidth > 0) {
1237
1239
  context.stroke();
1238
1240
  }
1239
- if (particle.close) {
1240
- context.closePath();
1241
- }
1242
- if (particle.fill) {
1241
+ if (particle.shapeFill) {
1243
1242
  context.fill();
1244
1243
  }
1245
- drawShapeAfterEffect(container, context, particle, radius, opacity, delta);
1244
+ drawShapeAfterDraw(drawData);
1245
+ drawEffect(drawData);
1246
1246
  context.globalCompositeOperation = "source-over";
1247
1247
  context.setTransform(1, 0, 0, 1, 0, 0);
1248
1248
  }
1249
- function drawShape(container, context, particle, radius, opacity, delta) {
1249
+ function drawEffect(data) {
1250
+ const {
1251
+ container,
1252
+ context,
1253
+ particle,
1254
+ radius,
1255
+ opacity,
1256
+ delta
1257
+ } = data;
1258
+ if (!particle.effect) {
1259
+ return;
1260
+ }
1261
+ const drawer = container.effectDrawers.get(particle.effect);
1262
+ if (!drawer) {
1263
+ return;
1264
+ }
1265
+ drawer.draw({
1266
+ context,
1267
+ particle,
1268
+ radius,
1269
+ opacity,
1270
+ delta,
1271
+ pixelRatio: container.retina.pixelRatio
1272
+ });
1273
+ }
1274
+ function drawShape(data) {
1275
+ const {
1276
+ container,
1277
+ context,
1278
+ particle,
1279
+ radius,
1280
+ opacity,
1281
+ delta
1282
+ } = data;
1250
1283
  if (!particle.shape) {
1251
1284
  return;
1252
1285
  }
1253
- const drawer = container.drawers.get(particle.shape);
1286
+ const drawer = container.shapeDrawers.get(particle.shape);
1254
1287
  if (!drawer) {
1255
1288
  return;
1256
1289
  }
1257
- drawer.draw(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1290
+ drawer.draw({
1291
+ context,
1292
+ particle,
1293
+ radius,
1294
+ opacity,
1295
+ delta,
1296
+ pixelRatio: container.retina.pixelRatio
1297
+ });
1258
1298
  }
1259
- function drawShapeAfterEffect(container, context, particle, radius, opacity, delta) {
1299
+ function drawShapeAfterDraw(data) {
1300
+ const {
1301
+ container,
1302
+ context,
1303
+ particle,
1304
+ radius,
1305
+ opacity,
1306
+ delta
1307
+ } = data;
1260
1308
  if (!particle.shape) {
1261
1309
  return;
1262
1310
  }
1263
- const drawer = container.drawers.get(particle.shape);
1264
- if (!drawer || !drawer.afterEffect) {
1311
+ const drawer = container.shapeDrawers.get(particle.shape);
1312
+ if (!drawer || !drawer.afterDraw) {
1265
1313
  return;
1266
1314
  }
1267
- drawer.afterEffect(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1315
+ drawer.afterDraw({
1316
+ context,
1317
+ particle,
1318
+ radius,
1319
+ opacity,
1320
+ delta,
1321
+ pixelRatio: container.retina.pixelRatio
1322
+ });
1268
1323
  }
1269
1324
  function drawPlugin(context, plugin, delta) {
1270
1325
  if (!plugin.draw) {
@@ -1711,10 +1766,10 @@ class Canvas {
1711
1766
  this.element.width = size.width = this.element.offsetWidth * pxRatio;
1712
1767
  this.element.height = size.height = this.element.offsetHeight * pxRatio;
1713
1768
  if (this.container.started) {
1714
- this.resizeFactor = {
1769
+ container.particles.setResizeFactor({
1715
1770
  width: size.width / oldSize.width,
1716
1771
  height: size.height / oldSize.height
1717
- };
1772
+ });
1718
1773
  }
1719
1774
  return true;
1720
1775
  }
@@ -2184,10 +2239,10 @@ class BackgroundMask {
2184
2239
  this.composite = data.composite;
2185
2240
  }
2186
2241
  if (data.cover !== undefined) {
2187
- const cover = data.cover;
2188
- const color = isString(data.cover) ? {
2189
- color: data.cover
2190
- } : data.cover;
2242
+ const cover = data.cover,
2243
+ color = isString(data.cover) ? {
2244
+ color: data.cover
2245
+ } : data.cover;
2191
2246
  this.cover.load(cover.color !== undefined ? cover : {
2192
2247
  color: color
2193
2248
  });
@@ -2489,17 +2544,16 @@ class Theme {
2489
2544
  }
2490
2545
  }
2491
2546
  }
2492
- ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ColorAnimation.js
2547
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/AnimationOptions.js
2493
2548
 
2494
- class ColorAnimation {
2549
+ class AnimationOptions {
2495
2550
  constructor() {
2496
2551
  this.count = 0;
2497
2552
  this.enable = false;
2498
- this.offset = 0;
2499
2553
  this.speed = 1;
2500
- this.delay = 0;
2501
2554
  this.decay = 0;
2502
- this.sync = true;
2555
+ this.delay = 0;
2556
+ this.sync = false;
2503
2557
  }
2504
2558
  load(data) {
2505
2559
  if (!data) {
@@ -2511,9 +2565,6 @@ class ColorAnimation {
2511
2565
  if (data.enable !== undefined) {
2512
2566
  this.enable = data.enable;
2513
2567
  }
2514
- if (data.offset !== undefined) {
2515
- this.offset = setRangeValue(data.offset);
2516
- }
2517
2568
  if (data.speed !== undefined) {
2518
2569
  this.speed = setRangeValue(data.speed);
2519
2570
  }
@@ -2528,6 +2579,44 @@ class ColorAnimation {
2528
2579
  }
2529
2580
  }
2530
2581
  }
2582
+ class RangedAnimationOptions extends AnimationOptions {
2583
+ constructor() {
2584
+ super();
2585
+ this.mode = "auto";
2586
+ this.startValue = "random";
2587
+ }
2588
+ load(data) {
2589
+ super.load(data);
2590
+ if (!data) {
2591
+ return;
2592
+ }
2593
+ if (data.mode !== undefined) {
2594
+ this.mode = data.mode;
2595
+ }
2596
+ if (data.startValue !== undefined) {
2597
+ this.startValue = data.startValue;
2598
+ }
2599
+ }
2600
+ }
2601
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ColorAnimation.js
2602
+
2603
+
2604
+ class ColorAnimation extends AnimationOptions {
2605
+ constructor() {
2606
+ super();
2607
+ this.offset = 0;
2608
+ this.sync = true;
2609
+ }
2610
+ load(data) {
2611
+ super.load(data);
2612
+ if (!data) {
2613
+ return;
2614
+ }
2615
+ if (data.offset !== undefined) {
2616
+ this.offset = setRangeValue(data.offset);
2617
+ }
2618
+ }
2619
+ }
2531
2620
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/HslAnimation.js
2532
2621
 
2533
2622
  class HslAnimation {
@@ -2615,99 +2704,19 @@ class CollisionsOverlap {
2615
2704
  }
2616
2705
  }
2617
2706
  }
2618
- ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/AnimationOptions.js
2619
-
2620
- class AnimationOptions {
2621
- constructor() {
2622
- this.count = 0;
2623
- this.enable = false;
2624
- this.speed = 1;
2625
- this.decay = 0;
2626
- this.delay = 0;
2627
- this.sync = false;
2628
- }
2629
- load(data) {
2630
- if (!data) {
2631
- return;
2632
- }
2633
- if (data.count !== undefined) {
2634
- this.count = setRangeValue(data.count);
2635
- }
2636
- if (data.enable !== undefined) {
2637
- this.enable = data.enable;
2638
- }
2639
- if (data.speed !== undefined) {
2640
- this.speed = setRangeValue(data.speed);
2641
- }
2642
- if (data.decay !== undefined) {
2643
- this.decay = setRangeValue(data.decay);
2644
- }
2645
- if (data.delay !== undefined) {
2646
- this.delay = setRangeValue(data.delay);
2647
- }
2648
- if (data.sync !== undefined) {
2649
- this.sync = data.sync;
2650
- }
2651
- }
2652
- }
2653
- class RangedAnimationOptions extends AnimationOptions {
2654
- constructor() {
2655
- super();
2656
- this.mode = "auto";
2657
- this.startValue = "random";
2658
- }
2659
- load(data) {
2660
- super.load(data);
2661
- if (!data) {
2662
- return;
2663
- }
2664
- if (data.mode !== undefined) {
2665
- this.mode = data.mode;
2666
- }
2667
- if (data.startValue !== undefined) {
2668
- this.startValue = data.startValue;
2669
- }
2670
- }
2671
- }
2672
- ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Random.js
2673
- class Random {
2674
- constructor() {
2675
- this.enable = false;
2676
- this.minimumValue = 0;
2677
- }
2678
- load(data) {
2679
- if (!data) {
2680
- return;
2681
- }
2682
- if (data.enable !== undefined) {
2683
- this.enable = data.enable;
2684
- }
2685
- if (data.minimumValue !== undefined) {
2686
- this.minimumValue = data.minimumValue;
2687
- }
2688
- }
2689
- }
2690
2707
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ValueWithRandom.js
2691
2708
 
2692
2709
 
2693
-
2694
-
2695
2710
  class ValueWithRandom {
2696
2711
  constructor() {
2697
- this.random = new Random();
2698
2712
  this.value = 0;
2699
2713
  }
2700
2714
  load(data) {
2701
2715
  if (!data) {
2702
2716
  return;
2703
2717
  }
2704
- if (isBoolean(data.random)) {
2705
- this.random.enable = data.random;
2706
- } else {
2707
- this.random.load(data.random);
2708
- }
2709
2718
  if (data.value !== undefined) {
2710
- this.value = setRangeValue(data.value, this.random.enable ? this.random.minimumValue : undefined);
2719
+ this.value = setRangeValue(data.value);
2711
2720
  }
2712
2721
  }
2713
2722
  }
@@ -2741,7 +2750,6 @@ class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
2741
2750
  class ParticlesBounceFactor extends ValueWithRandom {
2742
2751
  constructor() {
2743
2752
  super();
2744
- this.random.minimumValue = 0.1;
2745
2753
  this.value = 1;
2746
2754
  }
2747
2755
  }
@@ -2792,6 +2800,39 @@ class Collisions {
2792
2800
  this.overlap.load(data.overlap);
2793
2801
  }
2794
2802
  }
2803
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Effect/Effect.js
2804
+
2805
+ class Effect {
2806
+ constructor() {
2807
+ this.close = true;
2808
+ this.fill = true;
2809
+ this.options = {};
2810
+ this.type = [];
2811
+ }
2812
+ load(data) {
2813
+ if (!data) {
2814
+ return;
2815
+ }
2816
+ const options = data.options;
2817
+ if (options !== undefined) {
2818
+ for (const effect in options) {
2819
+ const item = options[effect];
2820
+ if (item) {
2821
+ this.options[effect] = deepExtend(this.options[effect] ?? {}, item);
2822
+ }
2823
+ }
2824
+ }
2825
+ if (data.close !== undefined) {
2826
+ this.close = data.close;
2827
+ }
2828
+ if (data.fill !== undefined) {
2829
+ this.fill = data.fill;
2830
+ }
2831
+ if (data.type !== undefined) {
2832
+ this.type = data.type;
2833
+ }
2834
+ }
2835
+ }
2795
2836
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Move/MoveAngle.js
2796
2837
 
2797
2838
  class MoveAngle {
@@ -3120,11 +3161,10 @@ class OpacityAnimation extends RangedAnimationOptions {
3120
3161
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Opacity/Opacity.js
3121
3162
 
3122
3163
 
3123
- class Opacity extends ValueWithRandom {
3164
+ class Opacity extends RangedAnimationValueWithRandom {
3124
3165
  constructor() {
3125
3166
  super();
3126
3167
  this.animation = new OpacityAnimation();
3127
- this.random.minimumValue = 0.1;
3128
3168
  this.value = 1;
3129
3169
  }
3130
3170
  load(data) {
@@ -3162,12 +3202,31 @@ class ParticlesDensity {
3162
3202
  }
3163
3203
  }
3164
3204
  }
3205
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js
3206
+ class ParticlesNumberLimit {
3207
+ constructor() {
3208
+ this.mode = "delete";
3209
+ this.value = 0;
3210
+ }
3211
+ load(data) {
3212
+ if (!data) {
3213
+ return;
3214
+ }
3215
+ if (data.mode !== undefined) {
3216
+ this.mode = data.mode;
3217
+ }
3218
+ if (data.value !== undefined) {
3219
+ this.value = data.value;
3220
+ }
3221
+ }
3222
+ }
3165
3223
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Number/ParticlesNumber.js
3166
3224
 
3225
+
3167
3226
  class ParticlesNumber {
3168
3227
  constructor() {
3169
3228
  this.density = new ParticlesDensity();
3170
- this.limit = 0;
3229
+ this.limit = new ParticlesNumberLimit();
3171
3230
  this.value = 0;
3172
3231
  }
3173
3232
  load(data) {
@@ -3175,10 +3234,7 @@ class ParticlesNumber {
3175
3234
  return;
3176
3235
  }
3177
3236
  this.density.load(data.density);
3178
- const limit = data.limit;
3179
- if (limit !== undefined) {
3180
- this.limit = limit;
3181
- }
3237
+ this.limit.load(data.limit);
3182
3238
  if (data.value !== undefined) {
3183
3239
  this.value = data.value;
3184
3240
  }
@@ -3273,11 +3329,10 @@ class SizeAnimation extends RangedAnimationOptions {
3273
3329
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Size/Size.js
3274
3330
 
3275
3331
 
3276
- class Size extends ValueWithRandom {
3332
+ class Size extends RangedAnimationValueWithRandom {
3277
3333
  constructor() {
3278
3334
  super();
3279
3335
  this.animation = new SizeAnimation();
3280
- this.random.minimumValue = 1;
3281
3336
  this.value = 3;
3282
3337
  }
3283
3338
  load(data) {
@@ -3351,6 +3406,7 @@ class ZIndex extends ValueWithRandom {
3351
3406
 
3352
3407
 
3353
3408
 
3409
+
3354
3410
  class ParticlesOptions {
3355
3411
  constructor(engine, container) {
3356
3412
  this._engine = engine;
@@ -3359,6 +3415,7 @@ class ParticlesOptions {
3359
3415
  this.collisions = new Collisions();
3360
3416
  this.color = new AnimatableColor();
3361
3417
  this.color.value = "#fff";
3418
+ this.effect = new Effect();
3362
3419
  this.groups = {};
3363
3420
  this.move = new Move();
3364
3421
  this.number = new ParticlesNumber();
@@ -3376,6 +3433,7 @@ class ParticlesOptions {
3376
3433
  }
3377
3434
  this.bounce.load(data.bounce);
3378
3435
  this.color.load(AnimatableColor.create(this.color, data.color));
3436
+ this.effect.load(data.effect);
3379
3437
  if (data.groups !== undefined) {
3380
3438
  for (const group in data.groups) {
3381
3439
  const item = data.groups[group];
@@ -3648,7 +3706,27 @@ class InteractionManager {
3648
3706
 
3649
3707
 
3650
3708
 
3651
- const fixOutMode = data => {
3709
+ function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
3710
+ const effectData = effectOptions.options[effect];
3711
+ if (!effectData) {
3712
+ return;
3713
+ }
3714
+ return deepExtend({
3715
+ close: effectOptions.close,
3716
+ fill: effectOptions.fill
3717
+ }, itemFromSingleOrMultiple(effectData, id, reduceDuplicates));
3718
+ }
3719
+ function loadShapeData(shape, shapeOptions, id, reduceDuplicates) {
3720
+ const shapeData = shapeOptions.options[shape];
3721
+ if (!shapeData) {
3722
+ return;
3723
+ }
3724
+ return deepExtend({
3725
+ close: shapeOptions.close,
3726
+ fill: shapeOptions.fill
3727
+ }, itemFromSingleOrMultiple(shapeData, id, reduceDuplicates));
3728
+ }
3729
+ function fixOutMode(data) {
3652
3730
  if (!isInArray(data.outMode, data.checkModes)) {
3653
3731
  return;
3654
3732
  }
@@ -3658,7 +3736,7 @@ const fixOutMode = data => {
3658
3736
  } else if (data.coord < diameter) {
3659
3737
  data.setCb(data.radius);
3660
3738
  }
3661
- };
3739
+ }
3662
3740
  class Particle {
3663
3741
  constructor(engine, id, container, position, overrideOptions, group) {
3664
3742
  this.container = container;
@@ -3716,8 +3794,8 @@ class Particle {
3716
3794
  const rad = Math.PI / 180 * getRangeValue(moveOptions.angle.value),
3717
3795
  radOffset = Math.PI / 180 * getRangeValue(moveOptions.angle.offset),
3718
3796
  range = {
3719
- left: radOffset - rad / 2,
3720
- right: radOffset + rad / 2
3797
+ left: radOffset - rad * 0.5,
3798
+ right: radOffset + rad * 0.5
3721
3799
  };
3722
3800
  if (!moveOptions.straight) {
3723
3801
  res.angle += randomInRange(setRangeValue(range.left, range.right));
@@ -3748,7 +3826,7 @@ class Particle {
3748
3826
  return color;
3749
3827
  }
3750
3828
  const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1,
3751
- backSum = this.roll.horizontal ? Math.PI / 2 : 0,
3829
+ backSum = this.roll.horizontal ? Math.PI * 0.5 : 0,
3752
3830
  rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
3753
3831
  if (!rolled) {
3754
3832
  return color;
@@ -3783,16 +3861,6 @@ class Particle {
3783
3861
  }
3784
3862
  this.offset = Vector.origin;
3785
3863
  };
3786
- this._loadShapeData = (shapeOptions, reduceDuplicates) => {
3787
- const shapeData = shapeOptions.options[this.shape];
3788
- if (!shapeData) {
3789
- return;
3790
- }
3791
- return deepExtend({
3792
- close: shapeOptions.close,
3793
- fill: shapeOptions.fill
3794
- }, itemFromSingleOrMultiple(shapeData, this.id, reduceDuplicates));
3795
- };
3796
3864
  this._engine = engine;
3797
3865
  this.init(id, position, overrideOptions, group);
3798
3866
  }
@@ -3806,18 +3874,12 @@ class Particle {
3806
3874
  const container = this.container,
3807
3875
  pathGenerator = this.pathGenerator;
3808
3876
  for (const [, plugin] of container.plugins) {
3809
- if (plugin.particleDestroyed) {
3810
- plugin.particleDestroyed(this, override);
3811
- }
3877
+ plugin.particleDestroyed && plugin.particleDestroyed(this, override);
3812
3878
  }
3813
3879
  for (const updater of container.particles.updaters) {
3814
- if (updater.particleDestroyed) {
3815
- updater.particleDestroyed(this, override);
3816
- }
3817
- }
3818
- if (pathGenerator) {
3819
- pathGenerator.reset(this);
3880
+ updater.particleDestroyed && updater.particleDestroyed(this, override);
3820
3881
  }
3882
+ pathGenerator && pathGenerator.reset(this);
3821
3883
  }
3822
3884
  draw(delta) {
3823
3885
  const container = this.container,
@@ -3831,7 +3893,7 @@ class Particle {
3831
3893
  return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.color));
3832
3894
  }
3833
3895
  getMass() {
3834
- return this.getRadius() ** 2 * Math.PI / 2;
3896
+ return this.getRadius() ** 2 * Math.PI * 0.5;
3835
3897
  }
3836
3898
  getPosition() {
3837
3899
  return {
@@ -3851,9 +3913,11 @@ class Particle {
3851
3913
  engine = this._engine;
3852
3914
  this.id = id;
3853
3915
  this.group = group;
3854
- this.fill = true;
3916
+ this.effectClose = true;
3917
+ this.effectFill = true;
3918
+ this.shapeClose = true;
3919
+ this.shapeFill = true;
3855
3920
  this.pathRotation = false;
3856
- this.close = true;
3857
3921
  this.lastPathTime = 0;
3858
3922
  this.destroyed = false;
3859
3923
  this.unbreakable = false;
@@ -3867,22 +3931,40 @@ class Particle {
3867
3931
  const pxRatio = container.retina.pixelRatio,
3868
3932
  mainOptions = container.actualOptions,
3869
3933
  particlesOptions = loadParticlesOptions(this._engine, container, mainOptions.particles),
3934
+ effectType = particlesOptions.effect.type,
3870
3935
  shapeType = particlesOptions.shape.type,
3871
3936
  {
3872
3937
  reduceDuplicates
3873
3938
  } = particlesOptions;
3939
+ this.effect = itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
3874
3940
  this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
3875
- const shapeOptions = particlesOptions.shape;
3876
- if (overrideOptions && overrideOptions.shape && overrideOptions.shape.type) {
3877
- const overrideShapeType = overrideOptions.shape.type,
3878
- shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3879
- if (shape) {
3880
- this.shape = shape;
3881
- shapeOptions.load(overrideOptions.shape);
3941
+ const effectOptions = particlesOptions.effect,
3942
+ shapeOptions = particlesOptions.shape;
3943
+ if (overrideOptions) {
3944
+ if (overrideOptions.effect && overrideOptions.effect.type) {
3945
+ const overrideEffectType = overrideOptions.effect.type,
3946
+ effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
3947
+ if (effect) {
3948
+ this.effect = effect;
3949
+ effectOptions.load(overrideOptions.effect);
3950
+ }
3951
+ }
3952
+ if (overrideOptions.shape && overrideOptions.shape.type) {
3953
+ const overrideShapeType = overrideOptions.shape.type,
3954
+ shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3955
+ if (shape) {
3956
+ this.shape = shape;
3957
+ shapeOptions.load(overrideOptions.shape);
3958
+ }
3882
3959
  }
3883
3960
  }
3884
- this.shapeData = this._loadShapeData(shapeOptions, reduceDuplicates);
3961
+ this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
3962
+ this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
3885
3963
  particlesOptions.load(overrideOptions);
3964
+ const effectData = this.effectData;
3965
+ if (effectData) {
3966
+ particlesOptions.load(effectData.particles);
3967
+ }
3886
3968
  const shapeData = this.shapeData;
3887
3969
  if (shapeData) {
3888
3970
  particlesOptions.load(shapeData.particles);
@@ -3891,11 +3973,13 @@ class Particle {
3891
3973
  interactivity.load(container.actualOptions.interactivity);
3892
3974
  interactivity.load(particlesOptions.interactivity);
3893
3975
  this.interactivity = interactivity;
3894
- this.fill = shapeData?.fill ?? particlesOptions.shape.fill;
3895
- this.close = shapeData?.close ?? particlesOptions.shape.close;
3976
+ this.effectFill = effectData?.fill ?? particlesOptions.effect.fill;
3977
+ this.effectClose = effectData?.close ?? particlesOptions.effect.close;
3978
+ this.shapeFill = shapeData?.fill ?? particlesOptions.shape.fill;
3979
+ this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
3896
3980
  this.options = particlesOptions;
3897
3981
  const pathOptions = this.options.move.path;
3898
- this.pathDelay = getValue(pathOptions.delay) * 1000;
3982
+ this.pathDelay = getRangeValue(pathOptions.delay.value) * 1000;
3899
3983
  if (pathOptions.generator) {
3900
3984
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
3901
3985
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
@@ -3916,34 +4000,46 @@ class Particle {
3916
4000
  this.velocity = this.initialVelocity.copy();
3917
4001
  this.moveDecay = 1 - getRangeValue(this.options.move.decay);
3918
4002
  const particles = container.particles;
3919
- particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
3920
- particles.lastZIndex = this.position.z;
4003
+ particles.setLastZIndex(this.position.z);
3921
4004
  this.zIndexFactor = this.position.z / container.zLayers;
3922
4005
  this.sides = 24;
3923
- let drawer = container.drawers.get(this.shape);
3924
- if (!drawer) {
3925
- drawer = this._engine.getShapeDrawer(this.shape);
3926
- if (drawer) {
3927
- container.drawers.set(this.shape, drawer);
4006
+ let effectDrawer = container.effectDrawers.get(this.effect);
4007
+ if (!effectDrawer) {
4008
+ effectDrawer = this._engine.getEffectDrawer(this.effect);
4009
+ if (effectDrawer) {
4010
+ container.effectDrawers.set(this.effect, effectDrawer);
3928
4011
  }
3929
4012
  }
3930
- if (drawer && drawer.loadShape) {
3931
- drawer.loadShape(this);
4013
+ if (effectDrawer && effectDrawer.loadEffect) {
4014
+ effectDrawer.loadEffect(this);
4015
+ }
4016
+ let shapeDrawer = container.shapeDrawers.get(this.shape);
4017
+ if (!shapeDrawer) {
4018
+ shapeDrawer = this._engine.getShapeDrawer(this.shape);
4019
+ if (shapeDrawer) {
4020
+ container.shapeDrawers.set(this.shape, shapeDrawer);
4021
+ }
3932
4022
  }
3933
- const sideCountFunc = drawer?.getSidesCount;
4023
+ if (shapeDrawer && shapeDrawer.loadShape) {
4024
+ shapeDrawer.loadShape(this);
4025
+ }
4026
+ const sideCountFunc = shapeDrawer?.getSidesCount;
3934
4027
  if (sideCountFunc) {
3935
4028
  this.sides = sideCountFunc(this);
3936
4029
  }
3937
4030
  this.spawning = false;
3938
4031
  this.shadowColor = rangeColorToRgb(this.options.shadow.color);
3939
- for (const updater of container.particles.updaters) {
4032
+ for (const updater of particles.updaters) {
3940
4033
  updater.init(this);
3941
4034
  }
3942
- for (const mover of container.particles.movers) {
4035
+ for (const mover of particles.movers) {
3943
4036
  mover.init && mover.init(this);
3944
4037
  }
3945
- if (drawer && drawer.particleInit) {
3946
- drawer.particleInit(container, this);
4038
+ if (effectDrawer && effectDrawer.particleInit) {
4039
+ effectDrawer.particleInit(container, this);
4040
+ }
4041
+ if (shapeDrawer && shapeDrawer.particleInit) {
4042
+ shapeDrawer.particleInit(container, this);
3947
4043
  }
3948
4044
  for (const [, plugin] of container.plugins) {
3949
4045
  plugin.particleCreated && plugin.particleCreated(this);
@@ -4070,7 +4166,7 @@ class QuadTree {
4070
4166
  capacity
4071
4167
  } = this;
4072
4168
  for (let i = 0; i < 4; i++) {
4073
- this._subs.push(new QuadTree(new Rectangle(x + width / 2 * (i % 2), y + height / 2 * (Math.round(i / 2) - i % 2), width / 2, height / 2), capacity));
4169
+ 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));
4074
4170
  }
4075
4171
  this._divided = true;
4076
4172
  };
@@ -4126,21 +4222,36 @@ class QuadTree {
4126
4222
 
4127
4223
  const qTreeCapacity = 4;
4128
4224
  const qTreeRectangle = canvasSize => {
4129
- return new Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, canvasSize.width * 3 / 2, canvasSize.height * 3 / 2);
4225
+ const {
4226
+ height,
4227
+ width
4228
+ } = canvasSize,
4229
+ posOffset = -0.25,
4230
+ sizeFactor = 1.5;
4231
+ return new Rectangle(posOffset * width, posOffset * height, sizeFactor * width, sizeFactor * height);
4130
4232
  };
4131
4233
  class Particles {
4132
4234
  constructor(engine, container) {
4133
4235
  this._applyDensity = (options, manualCount, group) => {
4236
+ const numberOptions = options.number;
4134
4237
  if (!options.number.density?.enable) {
4238
+ if (group === undefined) {
4239
+ this._limit = numberOptions.limit.value;
4240
+ } else {
4241
+ this._groupLimits.set(group, numberOptions.limit.value);
4242
+ }
4135
4243
  return;
4136
4244
  }
4137
- const numberOptions = options.number,
4138
- densityFactor = this._initDensityFactor(numberOptions.density),
4245
+ const densityFactor = this._initDensityFactor(numberOptions.density),
4139
4246
  optParticlesNumber = numberOptions.value,
4140
- optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber,
4247
+ optParticlesLimit = numberOptions.limit.value > 0 ? numberOptions.limit.value : optParticlesNumber,
4141
4248
  particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount,
4142
4249
  particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
4143
- this.limit = numberOptions.limit * densityFactor;
4250
+ if (group === undefined) {
4251
+ this._limit = numberOptions.limit.value * densityFactor;
4252
+ } else {
4253
+ this._groupLimits.set(group, numberOptions.limit.value * densityFactor);
4254
+ }
4144
4255
  if (particlesCount < particlesNumber) {
4145
4256
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
4146
4257
  } else if (particlesCount > particlesNumber) {
@@ -4158,7 +4269,7 @@ class Particles {
4158
4269
  };
4159
4270
  this._pushParticle = (position, overrideOptions, group, initializer) => {
4160
4271
  try {
4161
- let particle = this.pool.pop();
4272
+ let particle = this._pool.pop();
4162
4273
  if (particle) {
4163
4274
  particle.init(this._nextId, position, overrideOptions, group);
4164
4275
  } else {
@@ -4195,7 +4306,7 @@ class Particles {
4195
4306
  const zIdx = this._zArray.indexOf(particle);
4196
4307
  this._array.splice(index, 1);
4197
4308
  this._zArray.splice(zIdx, 1);
4198
- this.pool.push(particle);
4309
+ this._pool.push(particle);
4199
4310
  this._engine.dispatchEvent("particleRemoved", {
4200
4311
  container: this._container,
4201
4312
  data: {
@@ -4209,10 +4320,11 @@ class Particles {
4209
4320
  this._nextId = 0;
4210
4321
  this._array = [];
4211
4322
  this._zArray = [];
4212
- this.pool = [];
4213
- this.limit = 0;
4214
- this.needsSort = false;
4215
- this.lastZIndex = 0;
4323
+ this._pool = [];
4324
+ this._limit = 0;
4325
+ this._groupLimits = new Map();
4326
+ this._needsSort = false;
4327
+ this._lastZIndex = 0;
4216
4328
  this._interactionManager = new InteractionManager(engine, container);
4217
4329
  const canvasSize = container.canvas.size;
4218
4330
  this.quadTree = new QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
@@ -4230,19 +4342,22 @@ class Particles {
4230
4342
  }
4231
4343
  }
4232
4344
  addParticle(position, overrideOptions, group, initializer) {
4233
- this.pushing = true;
4234
- const container = this._container,
4235
- options = container.actualOptions,
4236
- limit = options.particles.number.limit;
4345
+ const limitOptions = this._container.actualOptions.particles.number.limit,
4346
+ limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit,
4347
+ currentCount = this.count;
4237
4348
  if (limit > 0) {
4238
- const countToRemove = this.count + 1 - limit;
4239
- if (countToRemove > 0) {
4240
- this.removeQuantity(countToRemove);
4349
+ if (limitOptions.mode === "delete") {
4350
+ const countToRemove = currentCount + 1 - limit;
4351
+ if (countToRemove > 0) {
4352
+ this.removeQuantity(countToRemove);
4353
+ }
4354
+ } else if (limitOptions.mode === "wait") {
4355
+ if (currentCount >= limit) {
4356
+ return;
4357
+ }
4241
4358
  }
4242
4359
  }
4243
- const res = this._pushParticle(position, overrideOptions, group, initializer);
4244
- this.pushing = false;
4245
- return res;
4360
+ return this._pushParticle(position, overrideOptions, group, initializer);
4246
4361
  }
4247
4362
  clear() {
4248
4363
  this._array = [];
@@ -4281,8 +4396,8 @@ class Particles {
4281
4396
  init() {
4282
4397
  const container = this._container,
4283
4398
  options = container.actualOptions;
4284
- this.lastZIndex = 0;
4285
- this.needsSort = false;
4399
+ this._lastZIndex = 0;
4400
+ this._needsSort = false;
4286
4401
  let handled = false;
4287
4402
  this.updaters = this._engine.getUpdaters(container, true);
4288
4403
  this._interactionManager.init();
@@ -4349,6 +4464,13 @@ class Particles {
4349
4464
  }
4350
4465
  this._applyDensity(options.particles, options.manualParticles.length);
4351
4466
  }
4467
+ setLastZIndex(zIndex) {
4468
+ this._lastZIndex = zIndex;
4469
+ this._needsSort = this._needsSort || this._lastZIndex < zIndex;
4470
+ }
4471
+ setResizeFactor(factor) {
4472
+ this._resizeFactor = factor;
4473
+ }
4352
4474
  async update(delta) {
4353
4475
  const container = this._container,
4354
4476
  particlesToDelete = new Set();
@@ -4357,10 +4479,10 @@ class Particles {
4357
4479
  pathGenerator.update();
4358
4480
  }
4359
4481
  for (const [, plugin] of container.plugins) {
4360
- plugin.update && plugin.update(delta);
4482
+ plugin.update && (await plugin.update(delta));
4361
4483
  }
4484
+ const resizeFactor = this._resizeFactor;
4362
4485
  for (const particle of this._array) {
4363
- const resizeFactor = container.canvas.resizeFactor;
4364
4486
  if (resizeFactor && !particle.ignoresResizeRatio) {
4365
4487
  particle.position.x *= resizeFactor.width;
4366
4488
  particle.position.y *= resizeFactor.height;
@@ -4388,7 +4510,7 @@ class Particles {
4388
4510
  const checkDelete = p => !particlesToDelete.has(p);
4389
4511
  this._array = this.filter(checkDelete);
4390
4512
  this._zArray = this._zArray.filter(checkDelete);
4391
- this.pool.push(...particlesToDelete);
4513
+ this._pool.push(...particlesToDelete);
4392
4514
  }
4393
4515
  await this._interactionManager.externalInteract(delta);
4394
4516
  for (const particle of this._array) {
@@ -4399,12 +4521,12 @@ class Particles {
4399
4521
  await this._interactionManager.particlesInteract(particle, delta);
4400
4522
  }
4401
4523
  }
4402
- delete container.canvas.resizeFactor;
4403
- if (this.needsSort) {
4524
+ delete this._resizeFactor;
4525
+ if (this._needsSort) {
4404
4526
  const zArray = this._zArray;
4405
4527
  zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
4406
- this.lastZIndex = zArray[zArray.length - 1].position.z;
4407
- this.needsSort = false;
4528
+ this._lastZIndex = zArray[zArray.length - 1].position.z;
4529
+ this._needsSort = false;
4408
4530
  }
4409
4531
  }
4410
4532
  }
@@ -4431,7 +4553,6 @@ class Retina {
4431
4553
  }
4432
4554
  const particles = options.particles,
4433
4555
  moveOptions = particles.move;
4434
- this.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4435
4556
  this.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
4436
4557
  this.sizeAnimationSpeed = getRangeValue(particles.size.animation.speed) * ratio;
4437
4558
  }
@@ -4441,7 +4562,6 @@ class Retina {
4441
4562
  moveOptions = options.move,
4442
4563
  moveDistance = moveOptions.distance,
4443
4564
  props = particle.retina;
4444
- props.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4445
4565
  props.moveDrift = getRangeValue(moveOptions.drift) * ratio;
4446
4566
  props.moveSpeed = getRangeValue(moveOptions.speed) * ratio;
4447
4567
  props.sizeAnimationSpeed = getRangeValue(options.size.animation.speed) * ratio;
@@ -4477,7 +4597,6 @@ function loadContainerOptions(engine, container, ...sourceOptionsArr) {
4477
4597
  }
4478
4598
  class Container {
4479
4599
  constructor(engine, id, sourceOptions) {
4480
- this.id = id;
4481
4600
  this._intersectionManager = entries => {
4482
4601
  if (!guardCheck(this) || !this.actualOptions.pauseOnOutsideViewport) {
4483
4602
  return;
@@ -4491,14 +4610,14 @@ class Container {
4491
4610
  };
4492
4611
  this._nextFrame = async timestamp => {
4493
4612
  try {
4494
- if (!this.smooth && this.lastFrameTime !== undefined && timestamp < this.lastFrameTime + 1000 / this.fpsLimit) {
4613
+ if (!this._smooth && this._lastFrameTime !== undefined && timestamp < this._lastFrameTime + 1000 / this.fpsLimit) {
4495
4614
  this.draw(false);
4496
4615
  return;
4497
4616
  }
4498
- this.lastFrameTime ??= timestamp;
4499
- const delta = initDelta(timestamp - this.lastFrameTime, this.fpsLimit, this.smooth);
4617
+ this._lastFrameTime ??= timestamp;
4618
+ const delta = initDelta(timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
4500
4619
  this.addLifeTime(delta.value);
4501
- this.lastFrameTime = timestamp;
4620
+ this._lastFrameTime = timestamp;
4502
4621
  if (delta.value > 1000) {
4503
4622
  this.draw(false);
4504
4623
  return;
@@ -4516,8 +4635,9 @@ class Container {
4516
4635
  }
4517
4636
  };
4518
4637
  this._engine = engine;
4638
+ this.id = Symbol(id);
4519
4639
  this.fpsLimit = 120;
4520
- this.smooth = false;
4640
+ this._smooth = false;
4521
4641
  this._delay = 0;
4522
4642
  this._duration = 0;
4523
4643
  this._lifeTime = 0;
@@ -4525,7 +4645,7 @@ class Container {
4525
4645
  this.started = false;
4526
4646
  this.destroyed = false;
4527
4647
  this._paused = true;
4528
- this.lastFrameTime = 0;
4648
+ this._lastFrameTime = 0;
4529
4649
  this.zLayers = 100;
4530
4650
  this.pageHidden = false;
4531
4651
  this._sourceOptions = sourceOptions;
@@ -4541,13 +4661,12 @@ class Container {
4541
4661
  }
4542
4662
  };
4543
4663
  this.plugins = new Map();
4544
- this.drawers = new Map();
4664
+ this.effectDrawers = new Map();
4665
+ this.shapeDrawers = new Map();
4545
4666
  this._options = loadContainerOptions(this._engine, this);
4546
4667
  this.actualOptions = loadContainerOptions(this._engine, this);
4547
4668
  this._eventListeners = new EventListeners(this);
4548
- if (typeof IntersectionObserver !== "undefined" && IntersectionObserver) {
4549
- this._intersectionObserver = new IntersectionObserver(entries => this._intersectionManager(entries));
4550
- }
4669
+ this._intersectionObserver = safeIntersectionObserver(entries => this._intersectionManager(entries));
4551
4670
  this._engine.dispatchEvent("containerBuilt", {
4552
4671
  container: this
4553
4672
  });
@@ -4661,11 +4780,17 @@ class Container {
4661
4780
  this.stop();
4662
4781
  this.particles.destroy();
4663
4782
  this.canvas.destroy();
4664
- for (const [, drawer] of this.drawers) {
4665
- drawer.destroy && drawer.destroy(this);
4783
+ for (const [, effectDrawer] of this.effectDrawers) {
4784
+ effectDrawer.destroy && effectDrawer.destroy(this);
4785
+ }
4786
+ for (const [, shapeDrawer] of this.shapeDrawers) {
4787
+ shapeDrawer.destroy && shapeDrawer.destroy(this);
4666
4788
  }
4667
- for (const key of this.drawers.keys()) {
4668
- this.drawers.delete(key);
4789
+ for (const key of this.effectDrawers.keys()) {
4790
+ this.effectDrawers.delete(key);
4791
+ }
4792
+ for (const key of this.shapeDrawers.keys()) {
4793
+ this.shapeDrawers.delete(key);
4669
4794
  }
4670
4795
  this._engine.clearPlugins(this);
4671
4796
  this.destroyed = true;
@@ -4685,7 +4810,7 @@ class Container {
4685
4810
  let refreshTime = force;
4686
4811
  this._drawAnimationFrame = requestAnimationFrame(async timestamp => {
4687
4812
  if (refreshTime) {
4688
- this.lastFrameTime = undefined;
4813
+ this._lastFrameTime = undefined;
4689
4814
  refreshTime = false;
4690
4815
  }
4691
4816
  await this._nextFrame(timestamp);
@@ -4720,11 +4845,18 @@ class Container {
4720
4845
  if (!guardCheck(this)) {
4721
4846
  return;
4722
4847
  }
4848
+ const effects = this._engine.getSupportedEffects();
4849
+ for (const type of effects) {
4850
+ const drawer = this._engine.getEffectDrawer(type);
4851
+ if (drawer) {
4852
+ this.effectDrawers.set(type, drawer);
4853
+ }
4854
+ }
4723
4855
  const shapes = this._engine.getSupportedShapes();
4724
4856
  for (const type of shapes) {
4725
4857
  const drawer = this._engine.getShapeDrawer(type);
4726
4858
  if (drawer) {
4727
- this.drawers.set(type, drawer);
4859
+ this.shapeDrawers.set(type, drawer);
4728
4860
  }
4729
4861
  }
4730
4862
  this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
@@ -4743,8 +4875,11 @@ class Container {
4743
4875
  this._delay = getRangeValue(this.actualOptions.delay) * 1000;
4744
4876
  this._lifeTime = 0;
4745
4877
  this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
4746
- this.smooth = this.actualOptions.smooth;
4747
- for (const [, drawer] of this.drawers) {
4878
+ this._smooth = this.actualOptions.smooth;
4879
+ for (const [, drawer] of this.effectDrawers) {
4880
+ drawer.init && (await drawer.init(this));
4881
+ }
4882
+ for (const [, drawer] of this.shapeDrawers) {
4748
4883
  drawer.init && (await drawer.init(this));
4749
4884
  }
4750
4885
  for (const [, plugin] of this.plugins) {
@@ -4885,10 +5020,10 @@ class Container {
4885
5020
  this.actualOptions.responsive = [];
4886
5021
  const newMaxWidth = this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
4887
5022
  this.actualOptions.setTheme(this._currentTheme);
4888
- if (this.responsiveMaxWidth === newMaxWidth) {
5023
+ if (this._responsiveMaxWidth === newMaxWidth) {
4889
5024
  return false;
4890
5025
  }
4891
- this.responsiveMaxWidth = newMaxWidth;
5026
+ this._responsiveMaxWidth = newMaxWidth;
4892
5027
  return true;
4893
5028
  }
4894
5029
  }
@@ -4979,7 +5114,8 @@ class Engine {
4979
5114
  this.movers = new Map();
4980
5115
  this.updaters = new Map();
4981
5116
  this.presets = new Map();
4982
- this.drawers = new Map();
5117
+ this.effectDrawers = new Map();
5118
+ this.shapeDrawers = new Map();
4983
5119
  this.pathGenerators = new Map();
4984
5120
  }
4985
5121
  get configs() {
@@ -4990,17 +5126,23 @@ class Engine {
4990
5126
  return res;
4991
5127
  }
4992
5128
  get version() {
4993
- return "3.0.0-beta.2";
5129
+ return "3.0.0-beta.4";
4994
5130
  }
4995
- addConfig(nameOrConfig, config) {
4996
- if (isString(nameOrConfig)) {
4997
- if (config) {
4998
- config.name = nameOrConfig;
4999
- this._configs.set(nameOrConfig, config);
5131
+ addConfig(config) {
5132
+ const name = config.name ?? "default";
5133
+ this._configs.set(name, config);
5134
+ this._eventDispatcher.dispatchEvent("configAdded", {
5135
+ data: {
5136
+ name,
5137
+ config
5000
5138
  }
5001
- } else {
5002
- this._configs.set(nameOrConfig.name ?? "default", nameOrConfig);
5003
- }
5139
+ });
5140
+ }
5141
+ async addEffect(effect, drawer, refresh = true) {
5142
+ executeOnSingleOrMultiple(effect, type => {
5143
+ !this.getEffectDrawer(type) && this.effectDrawers.set(type, drawer);
5144
+ });
5145
+ await this.refresh(refresh);
5004
5146
  }
5005
5147
  addEventListener(type, listener) {
5006
5148
  this._eventDispatcher.addEventListener(type, listener);
@@ -5029,44 +5171,11 @@ class Engine {
5029
5171
  (override || !this.getPreset(preset)) && this.presets.set(preset, options);
5030
5172
  await this.refresh(refresh);
5031
5173
  }
5032
- async addShape(shape, drawer, initOrRefresh, afterEffectOrRefresh, destroyOrRefresh, refresh = true) {
5033
- let customDrawer;
5034
- let realRefresh = refresh,
5035
- realInit,
5036
- realAfterEffect,
5037
- realDestroy;
5038
- if (isBoolean(initOrRefresh)) {
5039
- realRefresh = initOrRefresh;
5040
- realInit = undefined;
5041
- } else {
5042
- realInit = initOrRefresh;
5043
- }
5044
- if (isBoolean(afterEffectOrRefresh)) {
5045
- realRefresh = afterEffectOrRefresh;
5046
- realAfterEffect = undefined;
5047
- } else {
5048
- realAfterEffect = afterEffectOrRefresh;
5049
- }
5050
- if (isBoolean(destroyOrRefresh)) {
5051
- realRefresh = destroyOrRefresh;
5052
- realDestroy = undefined;
5053
- } else {
5054
- realDestroy = destroyOrRefresh;
5055
- }
5056
- if (isFunction(drawer)) {
5057
- customDrawer = {
5058
- afterEffect: realAfterEffect,
5059
- destroy: realDestroy,
5060
- draw: drawer,
5061
- init: realInit
5062
- };
5063
- } else {
5064
- customDrawer = drawer;
5065
- }
5174
+ async addShape(shape, drawer, refresh = true) {
5066
5175
  executeOnSingleOrMultiple(shape, type => {
5067
- !this.getShapeDrawer(type) && this.drawers.set(type, customDrawer);
5176
+ !this.getShapeDrawer(type) && this.shapeDrawers.set(type, drawer);
5068
5177
  });
5069
- await this.refresh(realRefresh);
5178
+ await this.refresh(refresh);
5070
5179
  }
5071
5180
  clearPlugins(container) {
5072
5181
  this.updaters.delete(container);
@@ -5095,6 +5204,9 @@ class Engine {
5095
5204
  }
5096
5205
  return res;
5097
5206
  }
5207
+ getEffectDrawer(type) {
5208
+ return this.effectDrawers.get(type);
5209
+ }
5098
5210
  getInteractors(container, force = false) {
5099
5211
  return getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
5100
5212
  }
@@ -5111,10 +5223,13 @@ class Engine {
5111
5223
  return this.presets.get(preset);
5112
5224
  }
5113
5225
  getShapeDrawer(type) {
5114
- return this.drawers.get(type);
5226
+ return this.shapeDrawers.get(type);
5227
+ }
5228
+ getSupportedEffects() {
5229
+ return this.effectDrawers.keys();
5115
5230
  }
5116
5231
  getSupportedShapes() {
5117
- return this.drawers.keys();
5232
+ return this.shapeDrawers.keys();
5118
5233
  }
5119
5234
  getUpdaters(container, force = false) {
5120
5235
  return getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
@@ -5144,7 +5259,7 @@ class Engine {
5144
5259
  }
5145
5260
  const currentOptions = itemFromSingleOrMultiple(options, index),
5146
5261
  dom = this.dom(),
5147
- oldIndex = dom.findIndex(v => v.id === id);
5262
+ oldIndex = dom.findIndex(v => v.id.description === id);
5148
5263
  if (oldIndex >= 0) {
5149
5264
  const old = this.domItem(oldIndex);
5150
5265
  if (old && !old.destroyed) {
@@ -5410,7 +5525,6 @@ class ParticlesInteractorBase {
5410
5525
 
5411
5526
 
5412
5527
 
5413
-
5414
5528
 
5415
5529
 
5416
5530
  ;// CONCATENATED MODULE: ./dist/browser/index.js