@tsparticles/engine 3.0.0-beta.3 → 3.0.0-beta.5

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 (182) hide show
  1. package/browser/Core/Canvas.js +2 -2
  2. package/browser/Core/Container.js +36 -19
  3. package/browser/Core/Engine.js +18 -5
  4. package/browser/Core/Particle.js +77 -41
  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/Interactivity/Events/Events.js +2 -7
  11. package/browser/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  12. package/browser/Options/Classes/Particles/Effect/Effect.js +32 -0
  13. package/browser/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  14. package/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js +17 -0
  15. package/browser/Options/Classes/Particles/Opacity/Opacity.js +2 -3
  16. package/browser/Options/Classes/Particles/ParticlesOptions.js +12 -6
  17. package/browser/Options/Classes/Particles/Size/Size.js +2 -3
  18. package/browser/Options/Classes/ValueWithRandom.js +1 -10
  19. package/browser/Utils/CanvasUtils.js +23 -18
  20. package/browser/Utils/ColorUtils.js +24 -38
  21. package/browser/Utils/NumberUtils.js +7 -16
  22. package/browser/Utils/Utils.js +7 -7
  23. package/browser/export-types.js +4 -0
  24. package/browser/exports.js +2 -3
  25. package/cjs/Core/Canvas.js +2 -2
  26. package/cjs/Core/Container.js +36 -19
  27. package/cjs/Core/Engine.js +18 -5
  28. package/cjs/Core/Particle.js +76 -40
  29. package/cjs/Core/Particles.js +51 -26
  30. package/cjs/Core/Retina.js +0 -2
  31. package/cjs/Core/Utils/QuadTree.js +1 -1
  32. package/cjs/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  33. package/cjs/Options/Classes/ColorAnimation.js +4 -24
  34. package/cjs/Options/Classes/Interactivity/Events/Events.js +2 -7
  35. package/cjs/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  36. package/cjs/Options/Classes/Particles/Effect/Effect.js +36 -0
  37. package/cjs/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  38. package/cjs/Options/Classes/Particles/Number/ParticlesNumberLimit.js +21 -0
  39. package/cjs/Options/Classes/Particles/Opacity/Opacity.js +1 -2
  40. package/cjs/Options/Classes/Particles/ParticlesOptions.js +12 -6
  41. package/cjs/Options/Classes/Particles/Size/Size.js +2 -3
  42. package/cjs/Options/Classes/ValueWithRandom.js +1 -10
  43. package/cjs/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js +2 -0
  44. package/cjs/Utils/CanvasUtils.js +26 -21
  45. package/cjs/Utils/ColorUtils.js +24 -38
  46. package/cjs/Utils/NumberUtils.js +8 -18
  47. package/cjs/Utils/Utils.js +6 -6
  48. package/cjs/export-types.js +4 -0
  49. package/cjs/exports.js +2 -3
  50. package/esm/Core/Canvas.js +2 -2
  51. package/esm/Core/Container.js +36 -19
  52. package/esm/Core/Engine.js +18 -5
  53. package/esm/Core/Particle.js +77 -41
  54. package/esm/Core/Particles.js +51 -26
  55. package/esm/Core/Retina.js +0 -2
  56. package/esm/Core/Utils/QuadTree.js +1 -1
  57. package/esm/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  58. package/esm/Options/Classes/ColorAnimation.js +4 -24
  59. package/esm/Options/Classes/Interactivity/Events/Events.js +2 -7
  60. package/esm/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  61. package/esm/Options/Classes/Particles/Effect/Effect.js +32 -0
  62. package/esm/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  63. package/esm/Options/Classes/Particles/Number/ParticlesNumberLimit.js +17 -0
  64. package/esm/Options/Classes/Particles/Opacity/Opacity.js +2 -3
  65. package/esm/Options/Classes/Particles/ParticlesOptions.js +12 -6
  66. package/esm/Options/Classes/Particles/Size/Size.js +2 -3
  67. package/esm/Options/Classes/ValueWithRandom.js +1 -10
  68. package/esm/Options/Interfaces/Particles/Effect/IEffect.js +1 -0
  69. package/esm/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js +1 -0
  70. package/esm/Utils/CanvasUtils.js +23 -18
  71. package/esm/Utils/ColorUtils.js +24 -38
  72. package/esm/Utils/NumberUtils.js +7 -16
  73. package/esm/Utils/Utils.js +7 -7
  74. package/esm/export-types.js +4 -0
  75. package/esm/exports.js +2 -3
  76. package/package.json +1 -1
  77. package/report.html +4 -22
  78. package/tsparticles.engine.js +400 -295
  79. package/tsparticles.engine.min.js +1 -1
  80. package/tsparticles.engine.min.js.LICENSE.txt +1 -1
  81. package/types/Core/Canvas.d.ts +0 -1
  82. package/types/Core/Container.d.ts +8 -7
  83. package/types/Core/Engine.d.ts +7 -2
  84. package/types/Core/Interfaces/IContainerPlugin.d.ts +2 -3
  85. package/types/Core/Interfaces/IEffectDrawer.d.ts +10 -0
  86. package/types/Core/Interfaces/IExternalInteractor.d.ts +3 -4
  87. package/types/Core/Interfaces/IInteractor.d.ts +3 -3
  88. package/types/Core/Interfaces/IParticleRetinaProps.d.ts +0 -1
  89. package/types/Core/Interfaces/IParticlesInteractor.d.ts +3 -3
  90. package/types/Core/Interfaces/IShapeDrawData.d.ts +10 -0
  91. package/types/Core/Interfaces/IShapeDrawer.d.ts +3 -10
  92. package/types/Core/Particle.d.ts +6 -2
  93. package/types/Core/Particles.d.ts +10 -7
  94. package/types/Core/Retina.d.ts +0 -1
  95. package/types/Core/Utils/ExternalInteractorBase.d.ts +4 -4
  96. package/types/Core/Utils/InteractionManager.d.ts +1 -2
  97. package/types/Core/Utils/ParticlesInteractorBase.d.ts +5 -5
  98. package/types/Enums/Modes/LimitMode.d.ts +4 -0
  99. package/types/Enums/Types/EasingType.d.ts +3 -0
  100. package/types/Options/Classes/BackgroundMask/BackgroundMask.d.ts +1 -1
  101. package/types/Options/Classes/ColorAnimation.d.ts +2 -7
  102. package/types/Options/Classes/Interactivity/Events/ClickEvent.d.ts +1 -2
  103. package/types/Options/Classes/Interactivity/Events/DivEvent.d.ts +1 -2
  104. package/types/Options/Classes/Interactivity/Events/Events.d.ts +3 -3
  105. package/types/Options/Classes/Interactivity/Events/HoverEvent.d.ts +2 -3
  106. package/types/Options/Classes/Interactivity/Interactivity.d.ts +2 -2
  107. package/types/Options/Classes/Options.d.ts +6 -6
  108. package/types/Options/Classes/Particles/Bounce/ParticlesBounce.d.ts +2 -2
  109. package/types/Options/Classes/Particles/Collisions/Collisions.d.ts +3 -3
  110. package/types/Options/Classes/Particles/Effect/Effect.d.ts +13 -0
  111. package/types/Options/Classes/Particles/Move/Move.d.ts +8 -8
  112. package/types/Options/Classes/Particles/Move/MoveTrail.d.ts +1 -1
  113. package/types/Options/Classes/Particles/Number/ParticlesNumber.d.ts +3 -2
  114. package/types/Options/Classes/Particles/Number/ParticlesNumberLimit.d.ts +10 -0
  115. package/types/Options/Classes/Particles/Opacity/Opacity.d.ts +3 -3
  116. package/types/Options/Classes/Particles/ParticlesOptions.d.ts +12 -10
  117. package/types/Options/Classes/Particles/Size/Size.d.ts +3 -3
  118. package/types/Options/Classes/Theme/Theme.d.ts +1 -1
  119. package/types/Options/Classes/ValueWithRandom.d.ts +2 -4
  120. package/types/Options/Interfaces/IValueWithRandom.d.ts +0 -2
  121. package/types/Options/Interfaces/Interactivity/Events/IClickEvent.d.ts +1 -2
  122. package/types/Options/Interfaces/Interactivity/Events/IDivEvent.d.ts +1 -2
  123. package/types/Options/Interfaces/Interactivity/Events/IEvents.d.ts +1 -1
  124. package/types/Options/Interfaces/Interactivity/Events/IHoverEvent.d.ts +1 -2
  125. package/types/Options/Interfaces/Particles/Effect/IEffect.d.ts +8 -0
  126. package/types/Options/Interfaces/Particles/IParticlesOptions.d.ts +2 -0
  127. package/types/Options/Interfaces/Particles/Number/IParticlesNumber.d.ts +2 -1
  128. package/types/Options/Interfaces/Particles/Number/IParticlesNumberLimit.d.ts +5 -0
  129. package/types/Utils/CanvasUtils.d.ts +2 -2
  130. package/types/Utils/NumberUtils.d.ts +0 -2
  131. package/types/Utils/Utils.d.ts +2 -3
  132. package/types/export-types.d.ts +5 -0
  133. package/types/exports.d.ts +2 -3
  134. package/umd/Core/Canvas.js +2 -2
  135. package/umd/Core/Container.js +36 -19
  136. package/umd/Core/Engine.js +18 -5
  137. package/umd/Core/Particle.js +76 -40
  138. package/umd/Core/Particles.js +51 -26
  139. package/umd/Core/Retina.js +0 -2
  140. package/umd/Core/Utils/QuadTree.js +1 -1
  141. package/umd/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  142. package/umd/Options/Classes/ColorAnimation.js +5 -25
  143. package/umd/Options/Classes/Interactivity/Events/Events.js +3 -8
  144. package/umd/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  145. package/umd/Options/Classes/Particles/Effect/Effect.js +46 -0
  146. package/umd/Options/Classes/Particles/Number/ParticlesNumber.js +4 -6
  147. package/umd/Options/Classes/{Random.js → Particles/Number/ParticlesNumberLimit.js} +9 -9
  148. package/umd/Options/Classes/Particles/Opacity/Opacity.js +1 -2
  149. package/umd/Options/Classes/Particles/ParticlesOptions.js +13 -7
  150. package/umd/Options/Classes/Particles/Size/Size.js +3 -4
  151. package/umd/Options/Classes/ValueWithRandom.js +2 -11
  152. package/umd/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js +12 -0
  153. package/umd/Utils/CanvasUtils.js +26 -21
  154. package/umd/Utils/ColorUtils.js +24 -38
  155. package/umd/Utils/NumberUtils.js +9 -19
  156. package/umd/Utils/Utils.js +6 -6
  157. package/umd/export-types.js +5 -1
  158. package/umd/exports.js +3 -4
  159. package/browser/Options/Classes/Random.js +0 -17
  160. package/cjs/Options/Classes/Random.js +0 -21
  161. package/esm/Options/Classes/Random.js +0 -17
  162. package/types/Enums/Modes/ClickMode.d.ts +0 -9
  163. package/types/Enums/Modes/DivMode.d.ts +0 -5
  164. package/types/Enums/Modes/HoverMode.d.ts +0 -11
  165. package/types/Options/Classes/Random.d.ts +0 -9
  166. package/types/Options/Interfaces/IRandom.d.ts +0 -4
  167. /package/browser/{Enums/Modes/ClickMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  168. /package/browser/{Enums/Modes/DivMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  169. /package/browser/Enums/Modes/{HoverMode.js → LimitMode.js} +0 -0
  170. /package/browser/Options/Interfaces/{IRandom.js → Particles/Effect/IEffect.js} +0 -0
  171. /package/{esm/Enums/Modes/ClickMode.js → browser/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js} +0 -0
  172. /package/cjs/{Enums/Modes/ClickMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  173. /package/cjs/{Enums/Modes/DivMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  174. /package/cjs/Enums/Modes/{HoverMode.js → LimitMode.js} +0 -0
  175. /package/cjs/Options/Interfaces/{IRandom.js → Particles/Effect/IEffect.js} +0 -0
  176. /package/esm/{Enums/Modes/DivMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  177. /package/esm/{Enums/Modes/HoverMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  178. /package/esm/{Options/Interfaces/IRandom.js → Enums/Modes/LimitMode.js} +0 -0
  179. /package/umd/{Enums/Modes/ClickMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  180. /package/umd/{Enums/Modes/DivMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  181. /package/umd/Enums/Modes/{HoverMode.js → LimitMode.js} +0 -0
  182. /package/umd/Options/Interfaces/{IRandom.js → Particles/Effect/IEffect.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * tsParticles Engine v3.0.0-beta.3
2
+ * tsParticles Engine v3.0.0-beta.5
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),
@@ -411,17 +411,6 @@ function setRangeValue(source, value) {
411
411
  max: Math.max(max, value)
412
412
  } : setRangeValue(min, max);
413
413
  }
414
- function getValue(options) {
415
- const random = options.random,
416
- {
417
- enable,
418
- minimumValue
419
- } = isBoolean(random) ? {
420
- enable: random,
421
- minimumValue: 0
422
- } : random;
423
- return enable ? getRangeValue(setRangeValue(options.value, minimumValue)) : getRangeValue(options.value);
424
- }
425
414
  function getDistances(pointA, pointB) {
426
415
  const dx = pointA.x - pointB.x,
427
416
  dy = pointA.y - pointB.y;
@@ -440,21 +429,21 @@ function getParticleDirectionAngle(direction, position, center) {
440
429
  }
441
430
  switch (direction) {
442
431
  case "top":
443
- return -Math.PI / 2;
432
+ return -Math.PI * 0.5;
444
433
  case "top-right":
445
- return -Math.PI / 4;
434
+ return -Math.PI * 0.25;
446
435
  case "right":
447
436
  return 0;
448
437
  case "bottom-right":
449
- return Math.PI / 4;
438
+ return Math.PI * 0.25;
450
439
  case "bottom":
451
- return Math.PI / 2;
440
+ return Math.PI * 0.5;
452
441
  case "bottom-left":
453
- return 3 * Math.PI / 4;
442
+ return Math.PI * 0.75;
454
443
  case "left":
455
444
  return Math.PI;
456
445
  case "top-left":
457
- return -3 * Math.PI / 4;
446
+ return -Math.PI * 0.75;
458
447
  case "inside":
459
448
  return Math.atan2(center.y - position.y, center.x - position.x);
460
449
  case "outside":
@@ -550,7 +539,7 @@ function rectSideBounce(data) {
550
539
  if (pOtherSide.min < rectOtherSide.min || pOtherSide.min > rectOtherSide.max || pOtherSide.max < rectOtherSide.min || pOtherSide.max > rectOtherSide.max) {
551
540
  return res;
552
541
  }
553
- 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) {
554
543
  res.velocity = velocity * -factor;
555
544
  res.bounced = true;
556
545
  }
@@ -686,7 +675,7 @@ function circleBounceDataFromParticle(p) {
686
675
  radius: p.getRadius(),
687
676
  mass: p.getMass(),
688
677
  velocity: p.velocity,
689
- 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))
690
679
  };
691
680
  }
692
681
  function circleBounce(p1, p2) {
@@ -720,6 +709,7 @@ function rectBounce(particle, divBounds) {
720
709
  const pPos = particle.getPosition(),
721
710
  size = particle.getRadius(),
722
711
  bounds = calculateBounds(pPos, size),
712
+ bounceOptions = particle.options.bounce,
723
713
  resH = rectSideBounce({
724
714
  pSide: {
725
715
  min: bounds.left,
@@ -738,7 +728,7 @@ function rectBounce(particle, divBounds) {
738
728
  max: divBounds.bottom
739
729
  },
740
730
  velocity: particle.velocity.x,
741
- factor: getValue(particle.options.bounce.horizontal)
731
+ factor: getRangeValue(bounceOptions.horizontal.value)
742
732
  });
743
733
  if (resH.bounced) {
744
734
  if (resH.velocity !== undefined) {
@@ -766,7 +756,7 @@ function rectBounce(particle, divBounds) {
766
756
  max: divBounds.right
767
757
  },
768
758
  velocity: particle.velocity.y,
769
- factor: getValue(particle.options.bounce.vertical)
759
+ factor: getRangeValue(bounceOptions.vertical.value)
770
760
  });
771
761
  if (resV.bounced) {
772
762
  if (resV.velocity !== undefined) {
@@ -893,24 +883,6 @@ const randomColorValue = "random",
893
883
  function addColorManager(manager) {
894
884
  colorManagers.set(manager.key, manager);
895
885
  }
896
- function hue2rgb(p, q, t) {
897
- if (t < 0) {
898
- t += 1;
899
- }
900
- if (t > 1) {
901
- t -= 1;
902
- }
903
- if (t < 1 / 6) {
904
- return p + (q - p) * 6 * t;
905
- }
906
- if (t < 1 / 2) {
907
- return q;
908
- }
909
- if (t < 2 / 3) {
910
- return p + (q - p) * (2 / 3 - t) * 6;
911
- }
912
- return p;
913
- }
914
886
  function stringToRgba(input) {
915
887
  for (const [, manager] of colorManagers) {
916
888
  if (input.startsWith(manager.stringPrefix)) {
@@ -990,7 +962,7 @@ function rgbToHsl(color) {
990
962
  min = Math.min(r1, g1, b1),
991
963
  res = {
992
964
  h: 0,
993
- l: (max + min) / 2,
965
+ l: (max + min) * 0.5,
994
966
  s: 0
995
967
  };
996
968
  if (max !== min) {
@@ -1015,29 +987,48 @@ function stringToRgb(input) {
1015
987
  return stringToRgba(input);
1016
988
  }
1017
989
  function hslToRgb(hsl) {
1018
- const result = {
1019
- b: 0,
1020
- g: 0,
1021
- r: 0
1022
- },
1023
- hslPercent = {
1024
- h: hsl.h / 360,
1025
- l: hsl.l / 100,
1026
- 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
1027
1002
  };
1028
- if (!hslPercent.s) {
1029
- result.r = result.g = result.b = hslPercent.l;
1030
- } else {
1031
- const q = hslPercent.l < 0.5 ? hslPercent.l * (1 + hslPercent.s) : hslPercent.l + hslPercent.s - hslPercent.l * hslPercent.s,
1032
- p = 2 * hslPercent.l - q;
1033
- result.r = hue2rgb(p, q, hslPercent.h + 1 / 3);
1034
- result.g = hue2rgb(p, q, hslPercent.h);
1035
- result.b = hue2rgb(p, q, hslPercent.h - 1 / 3);
1036
1003
  }
1037
- result.r = Math.floor(result.r * 255);
1038
- result.g = Math.floor(result.g * 255);
1039
- result.b = Math.floor(result.b * 255);
1040
- 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
+ };
1041
1032
  }
1042
1033
  function hslaToRgba(hsla) {
1043
1034
  const rgbResult = hslToRgb(hsla);
@@ -1171,13 +1162,6 @@ function drawLine(context, begin, end) {
1171
1162
  context.lineTo(end.x, end.y);
1172
1163
  context.closePath();
1173
1164
  }
1174
- function drawTriangle(context, p1, p2, p3) {
1175
- context.beginPath();
1176
- context.moveTo(p1.x, p1.y);
1177
- context.lineTo(p2.x, p2.y);
1178
- context.lineTo(p3.x, p3.y);
1179
- context.closePath();
1180
- }
1181
1165
  function paintBase(context, dimension, baseColor) {
1182
1166
  context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1183
1167
  context.fillRect(0, 0, dimension.width, dimension.height);
@@ -1220,7 +1204,6 @@ function drawParticle(data) {
1220
1204
  d: rotateData.cos * (transform.d ?? 1)
1221
1205
  };
1222
1206
  context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1223
- context.beginPath();
1224
1207
  if (backgroundMask) {
1225
1208
  context.globalCompositeOperation = composite;
1226
1209
  }
@@ -1247,20 +1230,47 @@ function drawParticle(data) {
1247
1230
  opacity,
1248
1231
  delta
1249
1232
  };
1233
+ context.beginPath();
1250
1234
  drawShape(drawData);
1235
+ if (particle.shapeClose) {
1236
+ context.closePath();
1237
+ }
1251
1238
  if (strokeWidth > 0) {
1252
1239
  context.stroke();
1253
1240
  }
1254
- if (particle.close) {
1255
- context.closePath();
1256
- }
1257
- if (particle.fill) {
1241
+ if (particle.shapeFill) {
1258
1242
  context.fill();
1259
1243
  }
1260
- drawShapeAfterEffect(drawData);
1244
+ drawShapeAfterDraw(drawData);
1245
+ drawEffect(drawData);
1261
1246
  context.globalCompositeOperation = "source-over";
1262
1247
  context.setTransform(1, 0, 0, 1, 0, 0);
1263
1248
  }
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
+ }
1264
1274
  function drawShape(data) {
1265
1275
  const {
1266
1276
  container,
@@ -1273,7 +1283,7 @@ function drawShape(data) {
1273
1283
  if (!particle.shape) {
1274
1284
  return;
1275
1285
  }
1276
- const drawer = container.drawers.get(particle.shape);
1286
+ const drawer = container.shapeDrawers.get(particle.shape);
1277
1287
  if (!drawer) {
1278
1288
  return;
1279
1289
  }
@@ -1286,7 +1296,7 @@ function drawShape(data) {
1286
1296
  pixelRatio: container.retina.pixelRatio
1287
1297
  });
1288
1298
  }
1289
- function drawShapeAfterEffect(data) {
1299
+ function drawShapeAfterDraw(data) {
1290
1300
  const {
1291
1301
  container,
1292
1302
  context,
@@ -1298,11 +1308,11 @@ function drawShapeAfterEffect(data) {
1298
1308
  if (!particle.shape) {
1299
1309
  return;
1300
1310
  }
1301
- const drawer = container.drawers.get(particle.shape);
1302
- if (!drawer || !drawer.afterEffect) {
1311
+ const drawer = container.shapeDrawers.get(particle.shape);
1312
+ if (!drawer || !drawer.afterDraw) {
1303
1313
  return;
1304
1314
  }
1305
- drawer.afterEffect({
1315
+ drawer.afterDraw({
1306
1316
  context,
1307
1317
  particle,
1308
1318
  radius,
@@ -1756,10 +1766,10 @@ class Canvas {
1756
1766
  this.element.width = size.width = this.element.offsetWidth * pxRatio;
1757
1767
  this.element.height = size.height = this.element.offsetHeight * pxRatio;
1758
1768
  if (this.container.started) {
1759
- this.resizeFactor = {
1769
+ container.particles.setResizeFactor({
1760
1770
  width: size.width / oldSize.width,
1761
1771
  height: size.height / oldSize.height
1762
- };
1772
+ });
1763
1773
  }
1764
1774
  return true;
1765
1775
  }
@@ -2229,10 +2239,10 @@ class BackgroundMask {
2229
2239
  this.composite = data.composite;
2230
2240
  }
2231
2241
  if (data.cover !== undefined) {
2232
- const cover = data.cover;
2233
- const color = isString(data.cover) ? {
2234
- color: data.cover
2235
- } : data.cover;
2242
+ const cover = data.cover,
2243
+ color = isString(data.cover) ? {
2244
+ color: data.cover
2245
+ } : data.cover;
2236
2246
  this.cover.load(cover.color !== undefined ? cover : {
2237
2247
  color: color
2238
2248
  });
@@ -2392,11 +2402,7 @@ class Events {
2392
2402
  });
2393
2403
  }
2394
2404
  this.onHover.load(data.onHover);
2395
- if (isBoolean(data.resize)) {
2396
- this.resize.enable = data.resize;
2397
- } else {
2398
- this.resize.load(data.resize);
2399
- }
2405
+ this.resize.load(data.resize);
2400
2406
  }
2401
2407
  }
2402
2408
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Interactivity/Modes/Modes.js
@@ -2534,17 +2540,16 @@ class Theme {
2534
2540
  }
2535
2541
  }
2536
2542
  }
2537
- ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ColorAnimation.js
2543
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/AnimationOptions.js
2538
2544
 
2539
- class ColorAnimation {
2545
+ class AnimationOptions {
2540
2546
  constructor() {
2541
2547
  this.count = 0;
2542
2548
  this.enable = false;
2543
- this.offset = 0;
2544
2549
  this.speed = 1;
2545
- this.delay = 0;
2546
2550
  this.decay = 0;
2547
- this.sync = true;
2551
+ this.delay = 0;
2552
+ this.sync = false;
2548
2553
  }
2549
2554
  load(data) {
2550
2555
  if (!data) {
@@ -2556,9 +2561,6 @@ class ColorAnimation {
2556
2561
  if (data.enable !== undefined) {
2557
2562
  this.enable = data.enable;
2558
2563
  }
2559
- if (data.offset !== undefined) {
2560
- this.offset = setRangeValue(data.offset);
2561
- }
2562
2564
  if (data.speed !== undefined) {
2563
2565
  this.speed = setRangeValue(data.speed);
2564
2566
  }
@@ -2573,6 +2575,44 @@ class ColorAnimation {
2573
2575
  }
2574
2576
  }
2575
2577
  }
2578
+ class RangedAnimationOptions extends AnimationOptions {
2579
+ constructor() {
2580
+ super();
2581
+ this.mode = "auto";
2582
+ this.startValue = "random";
2583
+ }
2584
+ load(data) {
2585
+ super.load(data);
2586
+ if (!data) {
2587
+ return;
2588
+ }
2589
+ if (data.mode !== undefined) {
2590
+ this.mode = data.mode;
2591
+ }
2592
+ if (data.startValue !== undefined) {
2593
+ this.startValue = data.startValue;
2594
+ }
2595
+ }
2596
+ }
2597
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ColorAnimation.js
2598
+
2599
+
2600
+ class ColorAnimation extends AnimationOptions {
2601
+ constructor() {
2602
+ super();
2603
+ this.offset = 0;
2604
+ this.sync = true;
2605
+ }
2606
+ load(data) {
2607
+ super.load(data);
2608
+ if (!data) {
2609
+ return;
2610
+ }
2611
+ if (data.offset !== undefined) {
2612
+ this.offset = setRangeValue(data.offset);
2613
+ }
2614
+ }
2615
+ }
2576
2616
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/HslAnimation.js
2577
2617
 
2578
2618
  class HslAnimation {
@@ -2660,99 +2700,19 @@ class CollisionsOverlap {
2660
2700
  }
2661
2701
  }
2662
2702
  }
2663
- ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/AnimationOptions.js
2664
-
2665
- class AnimationOptions {
2666
- constructor() {
2667
- this.count = 0;
2668
- this.enable = false;
2669
- this.speed = 1;
2670
- this.decay = 0;
2671
- this.delay = 0;
2672
- this.sync = false;
2673
- }
2674
- load(data) {
2675
- if (!data) {
2676
- return;
2677
- }
2678
- if (data.count !== undefined) {
2679
- this.count = setRangeValue(data.count);
2680
- }
2681
- if (data.enable !== undefined) {
2682
- this.enable = data.enable;
2683
- }
2684
- if (data.speed !== undefined) {
2685
- this.speed = setRangeValue(data.speed);
2686
- }
2687
- if (data.decay !== undefined) {
2688
- this.decay = setRangeValue(data.decay);
2689
- }
2690
- if (data.delay !== undefined) {
2691
- this.delay = setRangeValue(data.delay);
2692
- }
2693
- if (data.sync !== undefined) {
2694
- this.sync = data.sync;
2695
- }
2696
- }
2697
- }
2698
- class RangedAnimationOptions extends AnimationOptions {
2699
- constructor() {
2700
- super();
2701
- this.mode = "auto";
2702
- this.startValue = "random";
2703
- }
2704
- load(data) {
2705
- super.load(data);
2706
- if (!data) {
2707
- return;
2708
- }
2709
- if (data.mode !== undefined) {
2710
- this.mode = data.mode;
2711
- }
2712
- if (data.startValue !== undefined) {
2713
- this.startValue = data.startValue;
2714
- }
2715
- }
2716
- }
2717
- ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Random.js
2718
- class Random {
2719
- constructor() {
2720
- this.enable = false;
2721
- this.minimumValue = 0;
2722
- }
2723
- load(data) {
2724
- if (!data) {
2725
- return;
2726
- }
2727
- if (data.enable !== undefined) {
2728
- this.enable = data.enable;
2729
- }
2730
- if (data.minimumValue !== undefined) {
2731
- this.minimumValue = data.minimumValue;
2732
- }
2733
- }
2734
- }
2735
2703
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ValueWithRandom.js
2736
2704
 
2737
2705
 
2738
-
2739
-
2740
2706
  class ValueWithRandom {
2741
2707
  constructor() {
2742
- this.random = new Random();
2743
2708
  this.value = 0;
2744
2709
  }
2745
2710
  load(data) {
2746
2711
  if (!data) {
2747
2712
  return;
2748
2713
  }
2749
- if (isBoolean(data.random)) {
2750
- this.random.enable = data.random;
2751
- } else {
2752
- this.random.load(data.random);
2753
- }
2754
2714
  if (data.value !== undefined) {
2755
- this.value = setRangeValue(data.value, this.random.enable ? this.random.minimumValue : undefined);
2715
+ this.value = setRangeValue(data.value);
2756
2716
  }
2757
2717
  }
2758
2718
  }
@@ -2786,7 +2746,6 @@ class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
2786
2746
  class ParticlesBounceFactor extends ValueWithRandom {
2787
2747
  constructor() {
2788
2748
  super();
2789
- this.random.minimumValue = 0.1;
2790
2749
  this.value = 1;
2791
2750
  }
2792
2751
  }
@@ -2837,6 +2796,39 @@ class Collisions {
2837
2796
  this.overlap.load(data.overlap);
2838
2797
  }
2839
2798
  }
2799
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Effect/Effect.js
2800
+
2801
+ class Effect {
2802
+ constructor() {
2803
+ this.close = true;
2804
+ this.fill = true;
2805
+ this.options = {};
2806
+ this.type = [];
2807
+ }
2808
+ load(data) {
2809
+ if (!data) {
2810
+ return;
2811
+ }
2812
+ const options = data.options;
2813
+ if (options !== undefined) {
2814
+ for (const effect in options) {
2815
+ const item = options[effect];
2816
+ if (item) {
2817
+ this.options[effect] = deepExtend(this.options[effect] ?? {}, item);
2818
+ }
2819
+ }
2820
+ }
2821
+ if (data.close !== undefined) {
2822
+ this.close = data.close;
2823
+ }
2824
+ if (data.fill !== undefined) {
2825
+ this.fill = data.fill;
2826
+ }
2827
+ if (data.type !== undefined) {
2828
+ this.type = data.type;
2829
+ }
2830
+ }
2831
+ }
2840
2832
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Move/MoveAngle.js
2841
2833
 
2842
2834
  class MoveAngle {
@@ -3165,11 +3157,10 @@ class OpacityAnimation extends RangedAnimationOptions {
3165
3157
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Opacity/Opacity.js
3166
3158
 
3167
3159
 
3168
- class Opacity extends ValueWithRandom {
3160
+ class Opacity extends RangedAnimationValueWithRandom {
3169
3161
  constructor() {
3170
3162
  super();
3171
3163
  this.animation = new OpacityAnimation();
3172
- this.random.minimumValue = 0.1;
3173
3164
  this.value = 1;
3174
3165
  }
3175
3166
  load(data) {
@@ -3207,12 +3198,31 @@ class ParticlesDensity {
3207
3198
  }
3208
3199
  }
3209
3200
  }
3201
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js
3202
+ class ParticlesNumberLimit {
3203
+ constructor() {
3204
+ this.mode = "delete";
3205
+ this.value = 0;
3206
+ }
3207
+ load(data) {
3208
+ if (!data) {
3209
+ return;
3210
+ }
3211
+ if (data.mode !== undefined) {
3212
+ this.mode = data.mode;
3213
+ }
3214
+ if (data.value !== undefined) {
3215
+ this.value = data.value;
3216
+ }
3217
+ }
3218
+ }
3210
3219
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Number/ParticlesNumber.js
3211
3220
 
3221
+
3212
3222
  class ParticlesNumber {
3213
3223
  constructor() {
3214
3224
  this.density = new ParticlesDensity();
3215
- this.limit = 0;
3225
+ this.limit = new ParticlesNumberLimit();
3216
3226
  this.value = 0;
3217
3227
  }
3218
3228
  load(data) {
@@ -3220,10 +3230,7 @@ class ParticlesNumber {
3220
3230
  return;
3221
3231
  }
3222
3232
  this.density.load(data.density);
3223
- const limit = data.limit;
3224
- if (limit !== undefined) {
3225
- this.limit = limit;
3226
- }
3233
+ this.limit.load(data.limit);
3227
3234
  if (data.value !== undefined) {
3228
3235
  this.value = data.value;
3229
3236
  }
@@ -3318,11 +3325,10 @@ class SizeAnimation extends RangedAnimationOptions {
3318
3325
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/Particles/Size/Size.js
3319
3326
 
3320
3327
 
3321
- class Size extends ValueWithRandom {
3328
+ class Size extends RangedAnimationValueWithRandom {
3322
3329
  constructor() {
3323
3330
  super();
3324
3331
  this.animation = new SizeAnimation();
3325
- this.random.minimumValue = 1;
3326
3332
  this.value = 3;
3327
3333
  }
3328
3334
  load(data) {
@@ -3396,6 +3402,7 @@ class ZIndex extends ValueWithRandom {
3396
3402
 
3397
3403
 
3398
3404
 
3405
+
3399
3406
  class ParticlesOptions {
3400
3407
  constructor(engine, container) {
3401
3408
  this._engine = engine;
@@ -3404,6 +3411,7 @@ class ParticlesOptions {
3404
3411
  this.collisions = new Collisions();
3405
3412
  this.color = new AnimatableColor();
3406
3413
  this.color.value = "#fff";
3414
+ this.effect = new Effect();
3407
3415
  this.groups = {};
3408
3416
  this.move = new Move();
3409
3417
  this.number = new ParticlesNumber();
@@ -3419,22 +3427,26 @@ class ParticlesOptions {
3419
3427
  if (!data) {
3420
3428
  return;
3421
3429
  }
3422
- this.bounce.load(data.bounce);
3423
- this.color.load(AnimatableColor.create(this.color, data.color));
3424
3430
  if (data.groups !== undefined) {
3425
- for (const group in data.groups) {
3431
+ for (const group of Object.keys(data.groups)) {
3432
+ if (!Object.hasOwn(data.groups, group)) {
3433
+ continue;
3434
+ }
3426
3435
  const item = data.groups[group];
3427
3436
  if (item !== undefined) {
3428
3437
  this.groups[group] = deepExtend(this.groups[group] ?? {}, item);
3429
3438
  }
3430
3439
  }
3431
3440
  }
3432
- this.move.load(data.move);
3433
- this.number.load(data.number);
3434
- this.opacity.load(data.opacity);
3435
3441
  if (data.reduceDuplicates !== undefined) {
3436
3442
  this.reduceDuplicates = data.reduceDuplicates;
3437
3443
  }
3444
+ this.bounce.load(data.bounce);
3445
+ this.color.load(AnimatableColor.create(this.color, data.color));
3446
+ this.effect.load(data.effect);
3447
+ this.move.load(data.move);
3448
+ this.number.load(data.number);
3449
+ this.opacity.load(data.opacity);
3438
3450
  this.shape.load(data.shape);
3439
3451
  this.size.load(data.size);
3440
3452
  this.shadow.load(data.shadow);
@@ -3693,6 +3705,16 @@ class InteractionManager {
3693
3705
 
3694
3706
 
3695
3707
 
3708
+ function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
3709
+ const effectData = effectOptions.options[effect];
3710
+ if (!effectData) {
3711
+ return;
3712
+ }
3713
+ return deepExtend({
3714
+ close: effectOptions.close,
3715
+ fill: effectOptions.fill
3716
+ }, itemFromSingleOrMultiple(effectData, id, reduceDuplicates));
3717
+ }
3696
3718
  function loadShapeData(shape, shapeOptions, id, reduceDuplicates) {
3697
3719
  const shapeData = shapeOptions.options[shape];
3698
3720
  if (!shapeData) {
@@ -3771,8 +3793,8 @@ class Particle {
3771
3793
  const rad = Math.PI / 180 * getRangeValue(moveOptions.angle.value),
3772
3794
  radOffset = Math.PI / 180 * getRangeValue(moveOptions.angle.offset),
3773
3795
  range = {
3774
- left: radOffset - rad / 2,
3775
- right: radOffset + rad / 2
3796
+ left: radOffset - rad * 0.5,
3797
+ right: radOffset + rad * 0.5
3776
3798
  };
3777
3799
  if (!moveOptions.straight) {
3778
3800
  res.angle += randomInRange(setRangeValue(range.left, range.right));
@@ -3803,7 +3825,7 @@ class Particle {
3803
3825
  return color;
3804
3826
  }
3805
3827
  const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1,
3806
- backSum = this.roll.horizontal ? Math.PI / 2 : 0,
3828
+ backSum = this.roll.horizontal ? Math.PI * 0.5 : 0,
3807
3829
  rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
3808
3830
  if (!rolled) {
3809
3831
  return color;
@@ -3849,20 +3871,16 @@ class Particle {
3849
3871
  this.bubble.inRange = false;
3850
3872
  this.slow.inRange = false;
3851
3873
  const container = this.container,
3852
- pathGenerator = this.pathGenerator;
3874
+ pathGenerator = this.pathGenerator,
3875
+ shapeDrawer = container.shapeDrawers.get(this.shape);
3876
+ shapeDrawer && shapeDrawer.particleDestroy && shapeDrawer.particleDestroy(this);
3853
3877
  for (const [, plugin] of container.plugins) {
3854
- if (plugin.particleDestroyed) {
3855
- plugin.particleDestroyed(this, override);
3856
- }
3878
+ plugin.particleDestroyed && plugin.particleDestroyed(this, override);
3857
3879
  }
3858
3880
  for (const updater of container.particles.updaters) {
3859
- if (updater.particleDestroyed) {
3860
- updater.particleDestroyed(this, override);
3861
- }
3862
- }
3863
- if (pathGenerator) {
3864
- pathGenerator.reset(this);
3881
+ updater.particleDestroyed && updater.particleDestroyed(this, override);
3865
3882
  }
3883
+ pathGenerator && pathGenerator.reset(this);
3866
3884
  }
3867
3885
  draw(delta) {
3868
3886
  const container = this.container,
@@ -3876,7 +3894,7 @@ class Particle {
3876
3894
  return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.color));
3877
3895
  }
3878
3896
  getMass() {
3879
- return this.getRadius() ** 2 * Math.PI / 2;
3897
+ return this.getRadius() ** 2 * Math.PI * 0.5;
3880
3898
  }
3881
3899
  getPosition() {
3882
3900
  return {
@@ -3896,9 +3914,11 @@ class Particle {
3896
3914
  engine = this._engine;
3897
3915
  this.id = id;
3898
3916
  this.group = group;
3899
- this.fill = true;
3917
+ this.effectClose = true;
3918
+ this.effectFill = true;
3919
+ this.shapeClose = true;
3920
+ this.shapeFill = true;
3900
3921
  this.pathRotation = false;
3901
- this.close = true;
3902
3922
  this.lastPathTime = 0;
3903
3923
  this.destroyed = false;
3904
3924
  this.unbreakable = false;
@@ -3912,22 +3932,40 @@ class Particle {
3912
3932
  const pxRatio = container.retina.pixelRatio,
3913
3933
  mainOptions = container.actualOptions,
3914
3934
  particlesOptions = loadParticlesOptions(this._engine, container, mainOptions.particles),
3935
+ effectType = particlesOptions.effect.type,
3915
3936
  shapeType = particlesOptions.shape.type,
3916
3937
  {
3917
3938
  reduceDuplicates
3918
3939
  } = particlesOptions;
3940
+ this.effect = itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
3919
3941
  this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
3920
- const shapeOptions = particlesOptions.shape;
3921
- if (overrideOptions && overrideOptions.shape && overrideOptions.shape.type) {
3922
- const overrideShapeType = overrideOptions.shape.type,
3923
- shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3924
- if (shape) {
3925
- this.shape = shape;
3926
- shapeOptions.load(overrideOptions.shape);
3942
+ const effectOptions = particlesOptions.effect,
3943
+ shapeOptions = particlesOptions.shape;
3944
+ if (overrideOptions) {
3945
+ if (overrideOptions.effect && overrideOptions.effect.type) {
3946
+ const overrideEffectType = overrideOptions.effect.type,
3947
+ effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
3948
+ if (effect) {
3949
+ this.effect = effect;
3950
+ effectOptions.load(overrideOptions.effect);
3951
+ }
3952
+ }
3953
+ if (overrideOptions.shape && overrideOptions.shape.type) {
3954
+ const overrideShapeType = overrideOptions.shape.type,
3955
+ shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3956
+ if (shape) {
3957
+ this.shape = shape;
3958
+ shapeOptions.load(overrideOptions.shape);
3959
+ }
3927
3960
  }
3928
3961
  }
3962
+ this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
3929
3963
  this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
3930
3964
  particlesOptions.load(overrideOptions);
3965
+ const effectData = this.effectData;
3966
+ if (effectData) {
3967
+ particlesOptions.load(effectData.particles);
3968
+ }
3931
3969
  const shapeData = this.shapeData;
3932
3970
  if (shapeData) {
3933
3971
  particlesOptions.load(shapeData.particles);
@@ -3936,11 +3974,13 @@ class Particle {
3936
3974
  interactivity.load(container.actualOptions.interactivity);
3937
3975
  interactivity.load(particlesOptions.interactivity);
3938
3976
  this.interactivity = interactivity;
3939
- this.fill = shapeData?.fill ?? particlesOptions.shape.fill;
3940
- this.close = shapeData?.close ?? particlesOptions.shape.close;
3977
+ this.effectFill = effectData?.fill ?? particlesOptions.effect.fill;
3978
+ this.effectClose = effectData?.close ?? particlesOptions.effect.close;
3979
+ this.shapeFill = shapeData?.fill ?? particlesOptions.shape.fill;
3980
+ this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
3941
3981
  this.options = particlesOptions;
3942
3982
  const pathOptions = this.options.move.path;
3943
- this.pathDelay = getValue(pathOptions.delay) * 1000;
3983
+ this.pathDelay = getRangeValue(pathOptions.delay.value) * 1000;
3944
3984
  if (pathOptions.generator) {
3945
3985
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
3946
3986
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
@@ -3961,34 +4001,46 @@ class Particle {
3961
4001
  this.velocity = this.initialVelocity.copy();
3962
4002
  this.moveDecay = 1 - getRangeValue(this.options.move.decay);
3963
4003
  const particles = container.particles;
3964
- particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
3965
- particles.lastZIndex = this.position.z;
4004
+ particles.setLastZIndex(this.position.z);
3966
4005
  this.zIndexFactor = this.position.z / container.zLayers;
3967
4006
  this.sides = 24;
3968
- let drawer = container.drawers.get(this.shape);
3969
- if (!drawer) {
3970
- drawer = this._engine.getShapeDrawer(this.shape);
3971
- if (drawer) {
3972
- container.drawers.set(this.shape, drawer);
4007
+ let effectDrawer = container.effectDrawers.get(this.effect);
4008
+ if (!effectDrawer) {
4009
+ effectDrawer = this._engine.getEffectDrawer(this.effect);
4010
+ if (effectDrawer) {
4011
+ container.effectDrawers.set(this.effect, effectDrawer);
3973
4012
  }
3974
4013
  }
3975
- if (drawer && drawer.loadShape) {
3976
- drawer.loadShape(this);
4014
+ if (effectDrawer && effectDrawer.loadEffect) {
4015
+ effectDrawer.loadEffect(this);
4016
+ }
4017
+ let shapeDrawer = container.shapeDrawers.get(this.shape);
4018
+ if (!shapeDrawer) {
4019
+ shapeDrawer = this._engine.getShapeDrawer(this.shape);
4020
+ if (shapeDrawer) {
4021
+ container.shapeDrawers.set(this.shape, shapeDrawer);
4022
+ }
3977
4023
  }
3978
- const sideCountFunc = drawer?.getSidesCount;
4024
+ if (shapeDrawer && shapeDrawer.loadShape) {
4025
+ shapeDrawer.loadShape(this);
4026
+ }
4027
+ const sideCountFunc = shapeDrawer?.getSidesCount;
3979
4028
  if (sideCountFunc) {
3980
4029
  this.sides = sideCountFunc(this);
3981
4030
  }
3982
4031
  this.spawning = false;
3983
4032
  this.shadowColor = rangeColorToRgb(this.options.shadow.color);
3984
- for (const updater of container.particles.updaters) {
4033
+ for (const updater of particles.updaters) {
3985
4034
  updater.init(this);
3986
4035
  }
3987
- for (const mover of container.particles.movers) {
4036
+ for (const mover of particles.movers) {
3988
4037
  mover.init && mover.init(this);
3989
4038
  }
3990
- if (drawer && drawer.particleInit) {
3991
- drawer.particleInit(container, this);
4039
+ if (effectDrawer && effectDrawer.particleInit) {
4040
+ effectDrawer.particleInit(container, this);
4041
+ }
4042
+ if (shapeDrawer && shapeDrawer.particleInit) {
4043
+ shapeDrawer.particleInit(container, this);
3992
4044
  }
3993
4045
  for (const [, plugin] of container.plugins) {
3994
4046
  plugin.particleCreated && plugin.particleCreated(this);
@@ -4115,7 +4167,7 @@ class QuadTree {
4115
4167
  capacity
4116
4168
  } = this;
4117
4169
  for (let i = 0; i < 4; i++) {
4118
- 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));
4170
+ 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));
4119
4171
  }
4120
4172
  this._divided = true;
4121
4173
  };
@@ -4171,21 +4223,36 @@ class QuadTree {
4171
4223
 
4172
4224
  const qTreeCapacity = 4;
4173
4225
  const qTreeRectangle = canvasSize => {
4174
- return new Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, canvasSize.width * 3 / 2, canvasSize.height * 3 / 2);
4226
+ const {
4227
+ height,
4228
+ width
4229
+ } = canvasSize,
4230
+ posOffset = -0.25,
4231
+ sizeFactor = 1.5;
4232
+ return new Rectangle(posOffset * width, posOffset * height, sizeFactor * width, sizeFactor * height);
4175
4233
  };
4176
4234
  class Particles {
4177
4235
  constructor(engine, container) {
4178
4236
  this._applyDensity = (options, manualCount, group) => {
4237
+ const numberOptions = options.number;
4179
4238
  if (!options.number.density?.enable) {
4239
+ if (group === undefined) {
4240
+ this._limit = numberOptions.limit.value;
4241
+ } else {
4242
+ this._groupLimits.set(group, numberOptions.limit.value);
4243
+ }
4180
4244
  return;
4181
4245
  }
4182
- const numberOptions = options.number,
4183
- densityFactor = this._initDensityFactor(numberOptions.density),
4246
+ const densityFactor = this._initDensityFactor(numberOptions.density),
4184
4247
  optParticlesNumber = numberOptions.value,
4185
- optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber,
4248
+ optParticlesLimit = numberOptions.limit.value > 0 ? numberOptions.limit.value : optParticlesNumber,
4186
4249
  particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount,
4187
4250
  particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
4188
- this.limit = numberOptions.limit * densityFactor;
4251
+ if (group === undefined) {
4252
+ this._limit = numberOptions.limit.value * densityFactor;
4253
+ } else {
4254
+ this._groupLimits.set(group, numberOptions.limit.value * densityFactor);
4255
+ }
4189
4256
  if (particlesCount < particlesNumber) {
4190
4257
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
4191
4258
  } else if (particlesCount > particlesNumber) {
@@ -4203,7 +4270,7 @@ class Particles {
4203
4270
  };
4204
4271
  this._pushParticle = (position, overrideOptions, group, initializer) => {
4205
4272
  try {
4206
- let particle = this.pool.pop();
4273
+ let particle = this._pool.pop();
4207
4274
  if (particle) {
4208
4275
  particle.init(this._nextId, position, overrideOptions, group);
4209
4276
  } else {
@@ -4240,7 +4307,7 @@ class Particles {
4240
4307
  const zIdx = this._zArray.indexOf(particle);
4241
4308
  this._array.splice(index, 1);
4242
4309
  this._zArray.splice(zIdx, 1);
4243
- this.pool.push(particle);
4310
+ this._pool.push(particle);
4244
4311
  this._engine.dispatchEvent("particleRemoved", {
4245
4312
  container: this._container,
4246
4313
  data: {
@@ -4254,10 +4321,11 @@ class Particles {
4254
4321
  this._nextId = 0;
4255
4322
  this._array = [];
4256
4323
  this._zArray = [];
4257
- this.pool = [];
4258
- this.limit = 0;
4259
- this.needsSort = false;
4260
- this.lastZIndex = 0;
4324
+ this._pool = [];
4325
+ this._limit = 0;
4326
+ this._groupLimits = new Map();
4327
+ this._needsSort = false;
4328
+ this._lastZIndex = 0;
4261
4329
  this._interactionManager = new InteractionManager(engine, container);
4262
4330
  const canvasSize = container.canvas.size;
4263
4331
  this.quadTree = new QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
@@ -4275,19 +4343,22 @@ class Particles {
4275
4343
  }
4276
4344
  }
4277
4345
  addParticle(position, overrideOptions, group, initializer) {
4278
- this.pushing = true;
4279
- const container = this._container,
4280
- options = container.actualOptions,
4281
- limit = options.particles.number.limit;
4346
+ const limitOptions = this._container.actualOptions.particles.number.limit,
4347
+ limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit,
4348
+ currentCount = this.count;
4282
4349
  if (limit > 0) {
4283
- const countToRemove = this.count + 1 - limit;
4284
- if (countToRemove > 0) {
4285
- this.removeQuantity(countToRemove);
4350
+ if (limitOptions.mode === "delete") {
4351
+ const countToRemove = currentCount + 1 - limit;
4352
+ if (countToRemove > 0) {
4353
+ this.removeQuantity(countToRemove);
4354
+ }
4355
+ } else if (limitOptions.mode === "wait") {
4356
+ if (currentCount >= limit) {
4357
+ return;
4358
+ }
4286
4359
  }
4287
4360
  }
4288
- const res = this._pushParticle(position, overrideOptions, group, initializer);
4289
- this.pushing = false;
4290
- return res;
4361
+ return this._pushParticle(position, overrideOptions, group, initializer);
4291
4362
  }
4292
4363
  clear() {
4293
4364
  this._array = [];
@@ -4326,8 +4397,8 @@ class Particles {
4326
4397
  init() {
4327
4398
  const container = this._container,
4328
4399
  options = container.actualOptions;
4329
- this.lastZIndex = 0;
4330
- this.needsSort = false;
4400
+ this._lastZIndex = 0;
4401
+ this._needsSort = false;
4331
4402
  let handled = false;
4332
4403
  this.updaters = this._engine.getUpdaters(container, true);
4333
4404
  this._interactionManager.init();
@@ -4394,6 +4465,13 @@ class Particles {
4394
4465
  }
4395
4466
  this._applyDensity(options.particles, options.manualParticles.length);
4396
4467
  }
4468
+ setLastZIndex(zIndex) {
4469
+ this._lastZIndex = zIndex;
4470
+ this._needsSort = this._needsSort || this._lastZIndex < zIndex;
4471
+ }
4472
+ setResizeFactor(factor) {
4473
+ this._resizeFactor = factor;
4474
+ }
4397
4475
  async update(delta) {
4398
4476
  const container = this._container,
4399
4477
  particlesToDelete = new Set();
@@ -4402,10 +4480,10 @@ class Particles {
4402
4480
  pathGenerator.update();
4403
4481
  }
4404
4482
  for (const [, plugin] of container.plugins) {
4405
- plugin.update && plugin.update(delta);
4483
+ plugin.update && (await plugin.update(delta));
4406
4484
  }
4485
+ const resizeFactor = this._resizeFactor;
4407
4486
  for (const particle of this._array) {
4408
- const resizeFactor = container.canvas.resizeFactor;
4409
4487
  if (resizeFactor && !particle.ignoresResizeRatio) {
4410
4488
  particle.position.x *= resizeFactor.width;
4411
4489
  particle.position.y *= resizeFactor.height;
@@ -4433,7 +4511,7 @@ class Particles {
4433
4511
  const checkDelete = p => !particlesToDelete.has(p);
4434
4512
  this._array = this.filter(checkDelete);
4435
4513
  this._zArray = this._zArray.filter(checkDelete);
4436
- this.pool.push(...particlesToDelete);
4514
+ this._pool.push(...particlesToDelete);
4437
4515
  }
4438
4516
  await this._interactionManager.externalInteract(delta);
4439
4517
  for (const particle of this._array) {
@@ -4444,12 +4522,12 @@ class Particles {
4444
4522
  await this._interactionManager.particlesInteract(particle, delta);
4445
4523
  }
4446
4524
  }
4447
- delete container.canvas.resizeFactor;
4448
- if (this.needsSort) {
4525
+ delete this._resizeFactor;
4526
+ if (this._needsSort) {
4449
4527
  const zArray = this._zArray;
4450
4528
  zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
4451
- this.lastZIndex = zArray[zArray.length - 1].position.z;
4452
- this.needsSort = false;
4529
+ this._lastZIndex = zArray[zArray.length - 1].position.z;
4530
+ this._needsSort = false;
4453
4531
  }
4454
4532
  }
4455
4533
  }
@@ -4476,7 +4554,6 @@ class Retina {
4476
4554
  }
4477
4555
  const particles = options.particles,
4478
4556
  moveOptions = particles.move;
4479
- this.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4480
4557
  this.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
4481
4558
  this.sizeAnimationSpeed = getRangeValue(particles.size.animation.speed) * ratio;
4482
4559
  }
@@ -4486,7 +4563,6 @@ class Retina {
4486
4563
  moveOptions = options.move,
4487
4564
  moveDistance = moveOptions.distance,
4488
4565
  props = particle.retina;
4489
- props.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4490
4566
  props.moveDrift = getRangeValue(moveOptions.drift) * ratio;
4491
4567
  props.moveSpeed = getRangeValue(moveOptions.speed) * ratio;
4492
4568
  props.sizeAnimationSpeed = getRangeValue(options.size.animation.speed) * ratio;
@@ -4535,14 +4611,14 @@ class Container {
4535
4611
  };
4536
4612
  this._nextFrame = async timestamp => {
4537
4613
  try {
4538
- if (!this.smooth && this.lastFrameTime !== undefined && timestamp < this.lastFrameTime + 1000 / this.fpsLimit) {
4614
+ if (!this._smooth && this._lastFrameTime !== undefined && timestamp < this._lastFrameTime + 1000 / this.fpsLimit) {
4539
4615
  this.draw(false);
4540
4616
  return;
4541
4617
  }
4542
- this.lastFrameTime ??= timestamp;
4543
- const delta = initDelta(timestamp - this.lastFrameTime, this.fpsLimit, this.smooth);
4618
+ this._lastFrameTime ??= timestamp;
4619
+ const delta = initDelta(timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
4544
4620
  this.addLifeTime(delta.value);
4545
- this.lastFrameTime = timestamp;
4621
+ this._lastFrameTime = timestamp;
4546
4622
  if (delta.value > 1000) {
4547
4623
  this.draw(false);
4548
4624
  return;
@@ -4562,7 +4638,7 @@ class Container {
4562
4638
  this._engine = engine;
4563
4639
  this.id = Symbol(id);
4564
4640
  this.fpsLimit = 120;
4565
- this.smooth = false;
4641
+ this._smooth = false;
4566
4642
  this._delay = 0;
4567
4643
  this._duration = 0;
4568
4644
  this._lifeTime = 0;
@@ -4570,7 +4646,7 @@ class Container {
4570
4646
  this.started = false;
4571
4647
  this.destroyed = false;
4572
4648
  this._paused = true;
4573
- this.lastFrameTime = 0;
4649
+ this._lastFrameTime = 0;
4574
4650
  this.zLayers = 100;
4575
4651
  this.pageHidden = false;
4576
4652
  this._sourceOptions = sourceOptions;
@@ -4586,7 +4662,8 @@ class Container {
4586
4662
  }
4587
4663
  };
4588
4664
  this.plugins = new Map();
4589
- this.drawers = new Map();
4665
+ this.effectDrawers = new Map();
4666
+ this.shapeDrawers = new Map();
4590
4667
  this._options = loadContainerOptions(this._engine, this);
4591
4668
  this.actualOptions = loadContainerOptions(this._engine, this);
4592
4669
  this._eventListeners = new EventListeners(this);
@@ -4704,11 +4781,17 @@ class Container {
4704
4781
  this.stop();
4705
4782
  this.particles.destroy();
4706
4783
  this.canvas.destroy();
4707
- for (const [, drawer] of this.drawers) {
4708
- drawer.destroy && drawer.destroy(this);
4784
+ for (const [, effectDrawer] of this.effectDrawers) {
4785
+ effectDrawer.destroy && effectDrawer.destroy(this);
4786
+ }
4787
+ for (const [, shapeDrawer] of this.shapeDrawers) {
4788
+ shapeDrawer.destroy && shapeDrawer.destroy(this);
4709
4789
  }
4710
- for (const key of this.drawers.keys()) {
4711
- this.drawers.delete(key);
4790
+ for (const key of this.effectDrawers.keys()) {
4791
+ this.effectDrawers.delete(key);
4792
+ }
4793
+ for (const key of this.shapeDrawers.keys()) {
4794
+ this.shapeDrawers.delete(key);
4712
4795
  }
4713
4796
  this._engine.clearPlugins(this);
4714
4797
  this.destroyed = true;
@@ -4728,7 +4811,7 @@ class Container {
4728
4811
  let refreshTime = force;
4729
4812
  this._drawAnimationFrame = requestAnimationFrame(async timestamp => {
4730
4813
  if (refreshTime) {
4731
- this.lastFrameTime = undefined;
4814
+ this._lastFrameTime = undefined;
4732
4815
  refreshTime = false;
4733
4816
  }
4734
4817
  await this._nextFrame(timestamp);
@@ -4763,11 +4846,18 @@ class Container {
4763
4846
  if (!guardCheck(this)) {
4764
4847
  return;
4765
4848
  }
4849
+ const effects = this._engine.getSupportedEffects();
4850
+ for (const type of effects) {
4851
+ const drawer = this._engine.getEffectDrawer(type);
4852
+ if (drawer) {
4853
+ this.effectDrawers.set(type, drawer);
4854
+ }
4855
+ }
4766
4856
  const shapes = this._engine.getSupportedShapes();
4767
4857
  for (const type of shapes) {
4768
4858
  const drawer = this._engine.getShapeDrawer(type);
4769
4859
  if (drawer) {
4770
- this.drawers.set(type, drawer);
4860
+ this.shapeDrawers.set(type, drawer);
4771
4861
  }
4772
4862
  }
4773
4863
  this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
@@ -4786,8 +4876,11 @@ class Container {
4786
4876
  this._delay = getRangeValue(this.actualOptions.delay) * 1000;
4787
4877
  this._lifeTime = 0;
4788
4878
  this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
4789
- this.smooth = this.actualOptions.smooth;
4790
- for (const [, drawer] of this.drawers) {
4879
+ this._smooth = this.actualOptions.smooth;
4880
+ for (const [, drawer] of this.effectDrawers) {
4881
+ drawer.init && (await drawer.init(this));
4882
+ }
4883
+ for (const [, drawer] of this.shapeDrawers) {
4791
4884
  drawer.init && (await drawer.init(this));
4792
4885
  }
4793
4886
  for (const [, plugin] of this.plugins) {
@@ -4928,10 +5021,10 @@ class Container {
4928
5021
  this.actualOptions.responsive = [];
4929
5022
  const newMaxWidth = this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
4930
5023
  this.actualOptions.setTheme(this._currentTheme);
4931
- if (this.responsiveMaxWidth === newMaxWidth) {
5024
+ if (this._responsiveMaxWidth === newMaxWidth) {
4932
5025
  return false;
4933
5026
  }
4934
- this.responsiveMaxWidth = newMaxWidth;
5027
+ this._responsiveMaxWidth = newMaxWidth;
4935
5028
  return true;
4936
5029
  }
4937
5030
  }
@@ -5022,7 +5115,8 @@ class Engine {
5022
5115
  this.movers = new Map();
5023
5116
  this.updaters = new Map();
5024
5117
  this.presets = new Map();
5025
- this.drawers = new Map();
5118
+ this.effectDrawers = new Map();
5119
+ this.shapeDrawers = new Map();
5026
5120
  this.pathGenerators = new Map();
5027
5121
  }
5028
5122
  get configs() {
@@ -5033,7 +5127,7 @@ class Engine {
5033
5127
  return res;
5034
5128
  }
5035
5129
  get version() {
5036
- return "3.0.0-beta.3";
5130
+ return "3.0.0-beta.5";
5037
5131
  }
5038
5132
  addConfig(config) {
5039
5133
  const name = config.name ?? "default";
@@ -5045,6 +5139,12 @@ class Engine {
5045
5139
  }
5046
5140
  });
5047
5141
  }
5142
+ async addEffect(effect, drawer, refresh = true) {
5143
+ executeOnSingleOrMultiple(effect, type => {
5144
+ !this.getEffectDrawer(type) && this.effectDrawers.set(type, drawer);
5145
+ });
5146
+ await this.refresh(refresh);
5147
+ }
5048
5148
  addEventListener(type, listener) {
5049
5149
  this._eventDispatcher.addEventListener(type, listener);
5050
5150
  }
@@ -5074,7 +5174,7 @@ class Engine {
5074
5174
  }
5075
5175
  async addShape(shape, drawer, refresh = true) {
5076
5176
  executeOnSingleOrMultiple(shape, type => {
5077
- !this.getShapeDrawer(type) && this.drawers.set(type, drawer);
5177
+ !this.getShapeDrawer(type) && this.shapeDrawers.set(type, drawer);
5078
5178
  });
5079
5179
  await this.refresh(refresh);
5080
5180
  }
@@ -5105,6 +5205,9 @@ class Engine {
5105
5205
  }
5106
5206
  return res;
5107
5207
  }
5208
+ getEffectDrawer(type) {
5209
+ return this.effectDrawers.get(type);
5210
+ }
5108
5211
  getInteractors(container, force = false) {
5109
5212
  return getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
5110
5213
  }
@@ -5121,10 +5224,13 @@ class Engine {
5121
5224
  return this.presets.get(preset);
5122
5225
  }
5123
5226
  getShapeDrawer(type) {
5124
- return this.drawers.get(type);
5227
+ return this.shapeDrawers.get(type);
5228
+ }
5229
+ getSupportedEffects() {
5230
+ return this.effectDrawers.keys();
5125
5231
  }
5126
5232
  getSupportedShapes() {
5127
- return this.drawers.keys();
5233
+ return this.shapeDrawers.keys();
5128
5234
  }
5129
5235
  getUpdaters(container, force = false) {
5130
5236
  return getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
@@ -5420,7 +5526,6 @@ class ParticlesInteractorBase {
5420
5526
 
5421
5527
 
5422
5528
 
5423
-
5424
5529
 
5425
5530
 
5426
5531
  ;// CONCATENATED MODULE: ./dist/browser/index.js