@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
@@ -39,16 +39,16 @@ class Container {
39
39
  };
40
40
  this._nextFrame = async (timestamp) => {
41
41
  try {
42
- if (!this.smooth &&
43
- this.lastFrameTime !== undefined &&
44
- timestamp < this.lastFrameTime + 1000 / this.fpsLimit) {
42
+ if (!this._smooth &&
43
+ this._lastFrameTime !== undefined &&
44
+ timestamp < this._lastFrameTime + 1000 / this.fpsLimit) {
45
45
  this.draw(false);
46
46
  return;
47
47
  }
48
- this.lastFrameTime ??= timestamp;
49
- const delta = initDelta(timestamp - this.lastFrameTime, this.fpsLimit, this.smooth);
48
+ this._lastFrameTime ??= timestamp;
49
+ const delta = initDelta(timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
50
50
  this.addLifeTime(delta.value);
51
- this.lastFrameTime = timestamp;
51
+ this._lastFrameTime = timestamp;
52
52
  if (delta.value > 1000) {
53
53
  this.draw(false);
54
54
  return;
@@ -69,7 +69,7 @@ class Container {
69
69
  this._engine = engine;
70
70
  this.id = Symbol(id);
71
71
  this.fpsLimit = 120;
72
- this.smooth = false;
72
+ this._smooth = false;
73
73
  this._delay = 0;
74
74
  this._duration = 0;
75
75
  this._lifeTime = 0;
@@ -77,7 +77,7 @@ class Container {
77
77
  this.started = false;
78
78
  this.destroyed = false;
79
79
  this._paused = true;
80
- this.lastFrameTime = 0;
80
+ this._lastFrameTime = 0;
81
81
  this.zLayers = 100;
82
82
  this.pageHidden = false;
83
83
  this._sourceOptions = sourceOptions;
@@ -93,7 +93,8 @@ class Container {
93
93
  },
94
94
  };
95
95
  this.plugins = new Map();
96
- this.drawers = new Map();
96
+ this.effectDrawers = new Map();
97
+ this.shapeDrawers = new Map();
97
98
  this._options = loadContainerOptions(this._engine, this);
98
99
  this.actualOptions = loadContainerOptions(this._engine, this);
99
100
  this._eventListeners = new EventListeners_js_1.EventListeners(this);
@@ -203,11 +204,17 @@ class Container {
203
204
  this.stop();
204
205
  this.particles.destroy();
205
206
  this.canvas.destroy();
206
- for (const [, drawer] of this.drawers) {
207
- drawer.destroy && drawer.destroy(this);
207
+ for (const [, effectDrawer] of this.effectDrawers) {
208
+ effectDrawer.destroy && effectDrawer.destroy(this);
208
209
  }
209
- for (const key of this.drawers.keys()) {
210
- this.drawers.delete(key);
210
+ for (const [, shapeDrawer] of this.shapeDrawers) {
211
+ shapeDrawer.destroy && shapeDrawer.destroy(this);
212
+ }
213
+ for (const key of this.effectDrawers.keys()) {
214
+ this.effectDrawers.delete(key);
215
+ }
216
+ for (const key of this.shapeDrawers.keys()) {
217
+ this.shapeDrawers.delete(key);
211
218
  }
212
219
  this._engine.clearPlugins(this);
213
220
  this.destroyed = true;
@@ -224,7 +231,7 @@ class Container {
224
231
  let refreshTime = force;
225
232
  this._drawAnimationFrame = requestAnimationFrame(async (timestamp) => {
226
233
  if (refreshTime) {
227
- this.lastFrameTime = undefined;
234
+ this._lastFrameTime = undefined;
228
235
  refreshTime = false;
229
236
  }
230
237
  await this._nextFrame(timestamp);
@@ -259,11 +266,18 @@ class Container {
259
266
  if (!guardCheck(this)) {
260
267
  return;
261
268
  }
269
+ const effects = this._engine.getSupportedEffects();
270
+ for (const type of effects) {
271
+ const drawer = this._engine.getEffectDrawer(type);
272
+ if (drawer) {
273
+ this.effectDrawers.set(type, drawer);
274
+ }
275
+ }
262
276
  const shapes = this._engine.getSupportedShapes();
263
277
  for (const type of shapes) {
264
278
  const drawer = this._engine.getShapeDrawer(type);
265
279
  if (drawer) {
266
- this.drawers.set(type, drawer);
280
+ this.shapeDrawers.set(type, drawer);
267
281
  }
268
282
  }
269
283
  this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
@@ -282,8 +296,11 @@ class Container {
282
296
  this._delay = (0, NumberUtils_js_1.getRangeValue)(this.actualOptions.delay) * 1000;
283
297
  this._lifeTime = 0;
284
298
  this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
285
- this.smooth = this.actualOptions.smooth;
286
- for (const [, drawer] of this.drawers) {
299
+ this._smooth = this.actualOptions.smooth;
300
+ for (const [, drawer] of this.effectDrawers) {
301
+ drawer.init && (await drawer.init(this));
302
+ }
303
+ for (const [, drawer] of this.shapeDrawers) {
287
304
  drawer.init && (await drawer.init(this));
288
305
  }
289
306
  for (const [, plugin] of this.plugins) {
@@ -412,10 +429,10 @@ class Container {
412
429
  this.actualOptions.responsive = [];
413
430
  const newMaxWidth = this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
414
431
  this.actualOptions.setTheme(this._currentTheme);
415
- if (this.responsiveMaxWidth === newMaxWidth) {
432
+ if (this._responsiveMaxWidth === newMaxWidth) {
416
433
  return false;
417
434
  }
418
- this.responsiveMaxWidth = newMaxWidth;
435
+ this._responsiveMaxWidth = newMaxWidth;
419
436
  return true;
420
437
  }
421
438
  }
@@ -42,7 +42,8 @@ class Engine {
42
42
  this.movers = new Map();
43
43
  this.updaters = new Map();
44
44
  this.presets = new Map();
45
- this.drawers = new Map();
45
+ this.effectDrawers = new Map();
46
+ this.shapeDrawers = new Map();
46
47
  this.pathGenerators = new Map();
47
48
  }
48
49
  get configs() {
@@ -53,13 +54,19 @@ class Engine {
53
54
  return res;
54
55
  }
55
56
  get version() {
56
- return "3.0.0-beta.3";
57
+ return "3.0.0-beta.5";
57
58
  }
58
59
  addConfig(config) {
59
60
  const name = config.name ?? "default";
60
61
  this._configs.set(name, config);
61
62
  this._eventDispatcher.dispatchEvent("configAdded", { data: { name, config } });
62
63
  }
64
+ async addEffect(effect, drawer, refresh = true) {
65
+ (0, Utils_js_1.executeOnSingleOrMultiple)(effect, (type) => {
66
+ !this.getEffectDrawer(type) && this.effectDrawers.set(type, drawer);
67
+ });
68
+ await this.refresh(refresh);
69
+ }
63
70
  addEventListener(type, listener) {
64
71
  this._eventDispatcher.addEventListener(type, listener);
65
72
  }
@@ -89,7 +96,7 @@ class Engine {
89
96
  }
90
97
  async addShape(shape, drawer, refresh = true) {
91
98
  (0, Utils_js_1.executeOnSingleOrMultiple)(shape, (type) => {
92
- !this.getShapeDrawer(type) && this.drawers.set(type, drawer);
99
+ !this.getShapeDrawer(type) && this.shapeDrawers.set(type, drawer);
93
100
  });
94
101
  await this.refresh(refresh);
95
102
  }
@@ -119,6 +126,9 @@ class Engine {
119
126
  }
120
127
  return res;
121
128
  }
129
+ getEffectDrawer(type) {
130
+ return this.effectDrawers.get(type);
131
+ }
122
132
  getInteractors(container, force = false) {
123
133
  return getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
124
134
  }
@@ -135,10 +145,13 @@ class Engine {
135
145
  return this.presets.get(preset);
136
146
  }
137
147
  getShapeDrawer(type) {
138
- return this.drawers.get(type);
148
+ return this.shapeDrawers.get(type);
149
+ }
150
+ getSupportedEffects() {
151
+ return this.effectDrawers.keys();
139
152
  }
140
153
  getSupportedShapes() {
141
- return this.drawers.keys();
154
+ return this.shapeDrawers.keys();
142
155
  }
143
156
  getUpdaters(container, force = false) {
144
157
  return getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
@@ -10,6 +10,16 @@ const Vector3d_js_1 = require("./Utils/Vector3d.js");
10
10
  const CanvasUtils_js_1 = require("../Utils/CanvasUtils.js");
11
11
  const Constants_js_1 = require("./Utils/Constants.js");
12
12
  const OptionsUtils_js_1 = require("../Utils/OptionsUtils.js");
13
+ function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
14
+ const effectData = effectOptions.options[effect];
15
+ if (!effectData) {
16
+ return;
17
+ }
18
+ return (0, Utils_js_1.deepExtend)({
19
+ close: effectOptions.close,
20
+ fill: effectOptions.fill,
21
+ }, (0, Utils_js_1.itemFromSingleOrMultiple)(effectData, id, reduceDuplicates));
22
+ }
13
23
  function loadShapeData(shape, shapeOptions, id, reduceDuplicates) {
14
24
  const shapeData = shapeOptions.options[shape];
15
25
  if (!shapeData) {
@@ -79,8 +89,8 @@ class Particle {
79
89
  return res;
80
90
  }
81
91
  const rad = (Math.PI / 180) * (0, NumberUtils_js_1.getRangeValue)(moveOptions.angle.value), radOffset = (Math.PI / 180) * (0, NumberUtils_js_1.getRangeValue)(moveOptions.angle.offset), range = {
82
- left: radOffset - rad / 2,
83
- right: radOffset + rad / 2,
92
+ left: radOffset - rad * 0.5,
93
+ right: radOffset + rad * 0.5,
84
94
  };
85
95
  if (!moveOptions.straight) {
86
96
  res.angle += (0, NumberUtils_js_1.randomInRange)((0, NumberUtils_js_1.setRangeValue)(range.left, range.right));
@@ -109,7 +119,7 @@ class Particle {
109
119
  if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
110
120
  return color;
111
121
  }
112
- const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1, backSum = this.roll.horizontal ? Math.PI / 2 : 0, rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
122
+ const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1, backSum = this.roll.horizontal ? Math.PI * 0.5 : 0, rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
113
123
  if (!rolled) {
114
124
  return color;
115
125
  }
@@ -152,20 +162,15 @@ class Particle {
152
162
  this.destroyed = true;
153
163
  this.bubble.inRange = false;
154
164
  this.slow.inRange = false;
155
- const container = this.container, pathGenerator = this.pathGenerator;
165
+ const container = this.container, pathGenerator = this.pathGenerator, shapeDrawer = container.shapeDrawers.get(this.shape);
166
+ shapeDrawer && shapeDrawer.particleDestroy && shapeDrawer.particleDestroy(this);
156
167
  for (const [, plugin] of container.plugins) {
157
- if (plugin.particleDestroyed) {
158
- plugin.particleDestroyed(this, override);
159
- }
168
+ plugin.particleDestroyed && plugin.particleDestroyed(this, override);
160
169
  }
161
170
  for (const updater of container.particles.updaters) {
162
- if (updater.particleDestroyed) {
163
- updater.particleDestroyed(this, override);
164
- }
165
- }
166
- if (pathGenerator) {
167
- pathGenerator.reset(this);
171
+ updater.particleDestroyed && updater.particleDestroyed(this, override);
168
172
  }
173
+ pathGenerator && pathGenerator.reset(this);
169
174
  }
170
175
  draw(delta) {
171
176
  const container = this.container, canvas = container.canvas;
@@ -178,7 +183,7 @@ class Particle {
178
183
  return this._getRollColor(this.bubble.color ?? (0, ColorUtils_js_1.getHslFromAnimation)(this.color));
179
184
  }
180
185
  getMass() {
181
- return (this.getRadius() ** 2 * Math.PI) / 2;
186
+ return this.getRadius() ** 2 * Math.PI * 0.5;
182
187
  }
183
188
  getPosition() {
184
189
  return {
@@ -197,9 +202,11 @@ class Particle {
197
202
  const container = this.container, engine = this._engine;
198
203
  this.id = id;
199
204
  this.group = group;
200
- this.fill = true;
205
+ this.effectClose = true;
206
+ this.effectFill = true;
207
+ this.shapeClose = true;
208
+ this.shapeFill = true;
201
209
  this.pathRotation = false;
202
- this.close = true;
203
210
  this.lastPathTime = 0;
204
211
  this.destroyed = false;
205
212
  this.unbreakable = false;
@@ -210,18 +217,33 @@ class Particle {
210
217
  };
211
218
  this.outType = "normal";
212
219
  this.ignoresResizeRatio = true;
213
- const pxRatio = container.retina.pixelRatio, mainOptions = container.actualOptions, particlesOptions = (0, OptionsUtils_js_1.loadParticlesOptions)(this._engine, container, mainOptions.particles), shapeType = particlesOptions.shape.type, { reduceDuplicates } = particlesOptions;
220
+ const pxRatio = container.retina.pixelRatio, mainOptions = container.actualOptions, particlesOptions = (0, OptionsUtils_js_1.loadParticlesOptions)(this._engine, container, mainOptions.particles), effectType = particlesOptions.effect.type, shapeType = particlesOptions.shape.type, { reduceDuplicates } = particlesOptions;
221
+ this.effect = (0, Utils_js_1.itemFromSingleOrMultiple)(effectType, this.id, reduceDuplicates);
214
222
  this.shape = (0, Utils_js_1.itemFromSingleOrMultiple)(shapeType, this.id, reduceDuplicates);
215
- const shapeOptions = particlesOptions.shape;
216
- if (overrideOptions && overrideOptions.shape && overrideOptions.shape.type) {
217
- const overrideShapeType = overrideOptions.shape.type, shape = (0, Utils_js_1.itemFromSingleOrMultiple)(overrideShapeType, this.id, reduceDuplicates);
218
- if (shape) {
219
- this.shape = shape;
220
- shapeOptions.load(overrideOptions.shape);
223
+ const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
224
+ if (overrideOptions) {
225
+ if (overrideOptions.effect && overrideOptions.effect.type) {
226
+ const overrideEffectType = overrideOptions.effect.type, effect = (0, Utils_js_1.itemFromSingleOrMultiple)(overrideEffectType, this.id, reduceDuplicates);
227
+ if (effect) {
228
+ this.effect = effect;
229
+ effectOptions.load(overrideOptions.effect);
230
+ }
231
+ }
232
+ if (overrideOptions.shape && overrideOptions.shape.type) {
233
+ const overrideShapeType = overrideOptions.shape.type, shape = (0, Utils_js_1.itemFromSingleOrMultiple)(overrideShapeType, this.id, reduceDuplicates);
234
+ if (shape) {
235
+ this.shape = shape;
236
+ shapeOptions.load(overrideOptions.shape);
237
+ }
221
238
  }
222
239
  }
240
+ this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
223
241
  this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
224
242
  particlesOptions.load(overrideOptions);
243
+ const effectData = this.effectData;
244
+ if (effectData) {
245
+ particlesOptions.load(effectData.particles);
246
+ }
225
247
  const shapeData = this.shapeData;
226
248
  if (shapeData) {
227
249
  particlesOptions.load(shapeData.particles);
@@ -230,11 +252,13 @@ class Particle {
230
252
  interactivity.load(container.actualOptions.interactivity);
231
253
  interactivity.load(particlesOptions.interactivity);
232
254
  this.interactivity = interactivity;
233
- this.fill = shapeData?.fill ?? particlesOptions.shape.fill;
234
- this.close = shapeData?.close ?? particlesOptions.shape.close;
255
+ this.effectFill = effectData?.fill ?? particlesOptions.effect.fill;
256
+ this.effectClose = effectData?.close ?? particlesOptions.effect.close;
257
+ this.shapeFill = shapeData?.fill ?? particlesOptions.shape.fill;
258
+ this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
235
259
  this.options = particlesOptions;
236
260
  const pathOptions = this.options.move.path;
237
- this.pathDelay = (0, NumberUtils_js_1.getValue)(pathOptions.delay) * 1000;
261
+ this.pathDelay = (0, NumberUtils_js_1.getRangeValue)(pathOptions.delay.value) * 1000;
238
262
  if (pathOptions.generator) {
239
263
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
240
264
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
@@ -255,34 +279,46 @@ class Particle {
255
279
  this.velocity = this.initialVelocity.copy();
256
280
  this.moveDecay = 1 - (0, NumberUtils_js_1.getRangeValue)(this.options.move.decay);
257
281
  const particles = container.particles;
258
- particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
259
- particles.lastZIndex = this.position.z;
282
+ particles.setLastZIndex(this.position.z);
260
283
  this.zIndexFactor = this.position.z / container.zLayers;
261
284
  this.sides = 24;
262
- let drawer = container.drawers.get(this.shape);
263
- if (!drawer) {
264
- drawer = this._engine.getShapeDrawer(this.shape);
265
- if (drawer) {
266
- container.drawers.set(this.shape, drawer);
285
+ let effectDrawer = container.effectDrawers.get(this.effect);
286
+ if (!effectDrawer) {
287
+ effectDrawer = this._engine.getEffectDrawer(this.effect);
288
+ if (effectDrawer) {
289
+ container.effectDrawers.set(this.effect, effectDrawer);
290
+ }
291
+ }
292
+ if (effectDrawer && effectDrawer.loadEffect) {
293
+ effectDrawer.loadEffect(this);
294
+ }
295
+ let shapeDrawer = container.shapeDrawers.get(this.shape);
296
+ if (!shapeDrawer) {
297
+ shapeDrawer = this._engine.getShapeDrawer(this.shape);
298
+ if (shapeDrawer) {
299
+ container.shapeDrawers.set(this.shape, shapeDrawer);
267
300
  }
268
301
  }
269
- if (drawer && drawer.loadShape) {
270
- drawer.loadShape(this);
302
+ if (shapeDrawer && shapeDrawer.loadShape) {
303
+ shapeDrawer.loadShape(this);
271
304
  }
272
- const sideCountFunc = drawer?.getSidesCount;
305
+ const sideCountFunc = shapeDrawer?.getSidesCount;
273
306
  if (sideCountFunc) {
274
307
  this.sides = sideCountFunc(this);
275
308
  }
276
309
  this.spawning = false;
277
310
  this.shadowColor = (0, ColorUtils_js_1.rangeColorToRgb)(this.options.shadow.color);
278
- for (const updater of container.particles.updaters) {
311
+ for (const updater of particles.updaters) {
279
312
  updater.init(this);
280
313
  }
281
- for (const mover of container.particles.movers) {
314
+ for (const mover of particles.movers) {
282
315
  mover.init && mover.init(this);
283
316
  }
284
- if (drawer && drawer.particleInit) {
285
- drawer.particleInit(container, this);
317
+ if (effectDrawer && effectDrawer.particleInit) {
318
+ effectDrawer.particleInit(container, this);
319
+ }
320
+ if (shapeDrawer && shapeDrawer.particleInit) {
321
+ shapeDrawer.particleInit(container, this);
286
322
  }
287
323
  for (const [, plugin] of container.plugins) {
288
324
  plugin.particleCreated && plugin.particleCreated(this);
@@ -10,16 +10,29 @@ const Rectangle_js_1 = require("./Utils/Rectangle.js");
10
10
  const Constants_js_1 = require("./Utils/Constants.js");
11
11
  const qTreeCapacity = 4;
12
12
  const qTreeRectangle = (canvasSize) => {
13
- return new Rectangle_js_1.Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, (canvasSize.width * 3) / 2, (canvasSize.height * 3) / 2);
13
+ const { height, width } = canvasSize, posOffset = -0.25, sizeFactor = 1.5;
14
+ return new Rectangle_js_1.Rectangle(posOffset * width, posOffset * height, sizeFactor * width, sizeFactor * height);
14
15
  };
15
16
  class Particles {
16
17
  constructor(engine, container) {
17
18
  this._applyDensity = (options, manualCount, group) => {
19
+ const numberOptions = options.number;
18
20
  if (!options.number.density?.enable) {
21
+ if (group === undefined) {
22
+ this._limit = numberOptions.limit.value;
23
+ }
24
+ else {
25
+ this._groupLimits.set(group, numberOptions.limit.value);
26
+ }
19
27
  return;
20
28
  }
21
- const numberOptions = options.number, densityFactor = this._initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount, particlesCount = Math.min(this.count, this.filter((t) => t.group === group).length);
22
- this.limit = numberOptions.limit * densityFactor;
29
+ const densityFactor = this._initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit.value > 0 ? numberOptions.limit.value : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount, particlesCount = Math.min(this.count, this.filter((t) => t.group === group).length);
30
+ if (group === undefined) {
31
+ this._limit = numberOptions.limit.value * densityFactor;
32
+ }
33
+ else {
34
+ this._groupLimits.set(group, numberOptions.limit.value * densityFactor);
35
+ }
23
36
  if (particlesCount < particlesNumber) {
24
37
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
25
38
  }
@@ -37,7 +50,7 @@ class Particles {
37
50
  };
38
51
  this._pushParticle = (position, overrideOptions, group, initializer) => {
39
52
  try {
40
- let particle = this.pool.pop();
53
+ let particle = this._pool.pop();
41
54
  if (particle) {
42
55
  particle.init(this._nextId, position, overrideOptions, group);
43
56
  }
@@ -76,7 +89,7 @@ class Particles {
76
89
  const zIdx = this._zArray.indexOf(particle);
77
90
  this._array.splice(index, 1);
78
91
  this._zArray.splice(zIdx, 1);
79
- this.pool.push(particle);
92
+ this._pool.push(particle);
80
93
  this._engine.dispatchEvent("particleRemoved", {
81
94
  container: this._container,
82
95
  data: {
@@ -90,10 +103,11 @@ class Particles {
90
103
  this._nextId = 0;
91
104
  this._array = [];
92
105
  this._zArray = [];
93
- this.pool = [];
94
- this.limit = 0;
95
- this.needsSort = false;
96
- this.lastZIndex = 0;
106
+ this._pool = [];
107
+ this._limit = 0;
108
+ this._groupLimits = new Map();
109
+ this._needsSort = false;
110
+ this._lastZIndex = 0;
97
111
  this._interactionManager = new InteractionManager_js_1.InteractionManager(engine, container);
98
112
  const canvasSize = container.canvas.size;
99
113
  this.quadTree = new QuadTree_js_1.QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
@@ -110,17 +124,21 @@ class Particles {
110
124
  }
111
125
  }
112
126
  addParticle(position, overrideOptions, group, initializer) {
113
- this.pushing = true;
114
- const container = this._container, options = container.actualOptions, limit = options.particles.number.limit;
127
+ const limitOptions = this._container.actualOptions.particles.number.limit, limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit, currentCount = this.count;
115
128
  if (limit > 0) {
116
- const countToRemove = this.count + 1 - limit;
117
- if (countToRemove > 0) {
118
- this.removeQuantity(countToRemove);
129
+ if (limitOptions.mode === "delete") {
130
+ const countToRemove = currentCount + 1 - limit;
131
+ if (countToRemove > 0) {
132
+ this.removeQuantity(countToRemove);
133
+ }
134
+ }
135
+ else if (limitOptions.mode === "wait") {
136
+ if (currentCount >= limit) {
137
+ return;
138
+ }
119
139
  }
120
140
  }
121
- const res = this._pushParticle(position, overrideOptions, group, initializer);
122
- this.pushing = false;
123
- return res;
141
+ return this._pushParticle(position, overrideOptions, group, initializer);
124
142
  }
125
143
  clear() {
126
144
  this._array = [];
@@ -157,8 +175,8 @@ class Particles {
157
175
  }
158
176
  init() {
159
177
  const container = this._container, options = container.actualOptions;
160
- this.lastZIndex = 0;
161
- this.needsSort = false;
178
+ this._lastZIndex = 0;
179
+ this._needsSort = false;
162
180
  let handled = false;
163
181
  this.updaters = this._engine.getUpdaters(container, true);
164
182
  this._interactionManager.init();
@@ -220,6 +238,13 @@ class Particles {
220
238
  }
221
239
  this._applyDensity(options.particles, options.manualParticles.length);
222
240
  }
241
+ setLastZIndex(zIndex) {
242
+ this._lastZIndex = zIndex;
243
+ this._needsSort = this._needsSort || this._lastZIndex < zIndex;
244
+ }
245
+ setResizeFactor(factor) {
246
+ this._resizeFactor = factor;
247
+ }
223
248
  async update(delta) {
224
249
  const container = this._container, particlesToDelete = new Set();
225
250
  this.quadTree = new QuadTree_js_1.QuadTree(qTreeRectangle(container.canvas.size), qTreeCapacity);
@@ -227,10 +252,10 @@ class Particles {
227
252
  pathGenerator.update();
228
253
  }
229
254
  for (const [, plugin] of container.plugins) {
230
- plugin.update && plugin.update(delta);
255
+ plugin.update && (await plugin.update(delta));
231
256
  }
257
+ const resizeFactor = this._resizeFactor;
232
258
  for (const particle of this._array) {
233
- const resizeFactor = container.canvas.resizeFactor;
234
259
  if (resizeFactor && !particle.ignoresResizeRatio) {
235
260
  particle.position.x *= resizeFactor.width;
236
261
  particle.position.y *= resizeFactor.height;
@@ -258,7 +283,7 @@ class Particles {
258
283
  const checkDelete = (p) => !particlesToDelete.has(p);
259
284
  this._array = this.filter(checkDelete);
260
285
  this._zArray = this._zArray.filter(checkDelete);
261
- this.pool.push(...particlesToDelete);
286
+ this._pool.push(...particlesToDelete);
262
287
  }
263
288
  await this._interactionManager.externalInteract(delta);
264
289
  for (const particle of this._array) {
@@ -269,12 +294,12 @@ class Particles {
269
294
  await this._interactionManager.particlesInteract(particle, delta);
270
295
  }
271
296
  }
272
- delete container.canvas.resizeFactor;
273
- if (this.needsSort) {
297
+ delete this._resizeFactor;
298
+ if (this._needsSort) {
274
299
  const zArray = this._zArray;
275
300
  zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
276
- this.lastZIndex = zArray[zArray.length - 1].position.z;
277
- this.needsSort = false;
301
+ this._lastZIndex = zArray[zArray.length - 1].position.z;
302
+ this._needsSort = false;
278
303
  }
279
304
  }
280
305
  }
@@ -20,13 +20,11 @@ class Retina {
20
20
  canvas.size.height = element.offsetHeight * ratio;
21
21
  }
22
22
  const particles = options.particles, moveOptions = particles.move;
23
- this.attractDistance = (0, NumberUtils_js_1.getRangeValue)(moveOptions.attract.distance) * ratio;
24
23
  this.maxSpeed = (0, NumberUtils_js_1.getRangeValue)(moveOptions.gravity.maxSpeed) * ratio;
25
24
  this.sizeAnimationSpeed = (0, NumberUtils_js_1.getRangeValue)(particles.size.animation.speed) * ratio;
26
25
  }
27
26
  initParticle(particle) {
28
27
  const options = particle.options, ratio = this.pixelRatio, moveOptions = options.move, moveDistance = moveOptions.distance, props = particle.retina;
29
- props.attractDistance = (0, NumberUtils_js_1.getRangeValue)(moveOptions.attract.distance) * ratio;
30
28
  props.moveDrift = (0, NumberUtils_js_1.getRangeValue)(moveOptions.drift) * ratio;
31
29
  props.moveSpeed = (0, NumberUtils_js_1.getRangeValue)(moveOptions.speed) * ratio;
32
30
  props.sizeAnimationSpeed = (0, NumberUtils_js_1.getRangeValue)(options.size.animation.speed) * ratio;
@@ -11,7 +11,7 @@ class QuadTree {
11
11
  this._subdivide = () => {
12
12
  const { x, y } = this.rectangle.position, { width, height } = this.rectangle.size, { capacity } = this;
13
13
  for (let i = 0; i < 4; i++) {
14
- this._subs.push(new QuadTree(new Rectangle_js_1.Rectangle(x + (width / 2) * (i % 2), y + (height / 2) * (Math.round(i / 2) - (i % 2)), width / 2, height / 2), capacity));
14
+ this._subs.push(new QuadTree(new Rectangle_js_1.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));
15
15
  }
16
16
  this._divided = true;
17
17
  };
@@ -17,8 +17,7 @@ class BackgroundMask {
17
17
  this.composite = data.composite;
18
18
  }
19
19
  if (data.cover !== undefined) {
20
- const cover = data.cover;
21
- const color = ((0, Utils_js_1.isString)(data.cover) ? { color: data.cover } : data.cover);
20
+ const cover = data.cover, color = ((0, Utils_js_1.isString)(data.cover) ? { color: data.cover } : data.cover);
22
21
  this.cover.load(cover.color !== undefined ? cover : { color: color });
23
22
  }
24
23
  if (data.enable !== undefined) {
@@ -1,42 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ColorAnimation = void 0;
4
+ const AnimationOptions_js_1 = require("./AnimationOptions.js");
4
5
  const NumberUtils_js_1 = require("../../Utils/NumberUtils.js");
5
- class ColorAnimation {
6
+ class ColorAnimation extends AnimationOptions_js_1.AnimationOptions {
6
7
  constructor() {
7
- this.count = 0;
8
- this.enable = false;
8
+ super();
9
9
  this.offset = 0;
10
- this.speed = 1;
11
- this.delay = 0;
12
- this.decay = 0;
13
10
  this.sync = true;
14
11
  }
15
12
  load(data) {
13
+ super.load(data);
16
14
  if (!data) {
17
15
  return;
18
16
  }
19
- if (data.count !== undefined) {
20
- this.count = (0, NumberUtils_js_1.setRangeValue)(data.count);
21
- }
22
- if (data.enable !== undefined) {
23
- this.enable = data.enable;
24
- }
25
17
  if (data.offset !== undefined) {
26
18
  this.offset = (0, NumberUtils_js_1.setRangeValue)(data.offset);
27
19
  }
28
- if (data.speed !== undefined) {
29
- this.speed = (0, NumberUtils_js_1.setRangeValue)(data.speed);
30
- }
31
- if (data.decay !== undefined) {
32
- this.decay = (0, NumberUtils_js_1.setRangeValue)(data.decay);
33
- }
34
- if (data.delay !== undefined) {
35
- this.delay = (0, NumberUtils_js_1.setRangeValue)(data.delay);
36
- }
37
- if (data.sync !== undefined) {
38
- this.sync = data.sync;
39
- }
40
20
  }
41
21
  }
42
22
  exports.ColorAnimation = ColorAnimation;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Events = void 0;
4
- const Utils_js_1 = require("../../../../Utils/Utils.js");
5
4
  const ClickEvent_js_1 = require("./ClickEvent.js");
6
5
  const DivEvent_js_1 = require("./DivEvent.js");
7
6
  const HoverEvent_js_1 = require("./HoverEvent.js");
8
7
  const ResizeEvent_js_1 = require("./ResizeEvent.js");
8
+ const Utils_js_1 = require("../../../../Utils/Utils.js");
9
9
  class Events {
10
10
  constructor() {
11
11
  this.onClick = new ClickEvent_js_1.ClickEvent();
@@ -27,12 +27,7 @@ class Events {
27
27
  });
28
28
  }
29
29
  this.onHover.load(data.onHover);
30
- if ((0, Utils_js_1.isBoolean)(data.resize)) {
31
- this.resize.enable = data.resize;
32
- }
33
- else {
34
- this.resize.load(data.resize);
35
- }
30
+ this.resize.load(data.resize);
36
31
  }
37
32
  }
38
33
  exports.Events = Events;