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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) 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 +75 -40
  5. package/browser/Core/Particles.js +51 -26
  6. package/browser/Core/Retina.js +0 -2
  7. package/browser/Core/Utils/QuadTree.js +1 -1
  8. package/browser/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  9. package/browser/Options/Classes/ColorAnimation.js +4 -24
  10. package/browser/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  11. package/browser/Options/Classes/Particles/Effect/Effect.js +32 -0
  12. package/browser/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  13. package/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js +17 -0
  14. package/browser/Options/Classes/Particles/Opacity/Opacity.js +2 -3
  15. package/browser/Options/Classes/Particles/ParticlesOptions.js +3 -0
  16. package/browser/Options/Classes/Particles/Size/Size.js +2 -3
  17. package/browser/Options/Classes/ValueWithRandom.js +1 -10
  18. package/browser/Utils/CanvasUtils.js +23 -18
  19. package/browser/Utils/ColorUtils.js +24 -38
  20. package/browser/Utils/NumberUtils.js +7 -16
  21. package/browser/Utils/Utils.js +7 -7
  22. package/browser/export-types.js +4 -0
  23. package/browser/exports.js +2 -3
  24. package/cjs/Core/Canvas.js +2 -2
  25. package/cjs/Core/Container.js +36 -19
  26. package/cjs/Core/Engine.js +18 -5
  27. package/cjs/Core/Particle.js +74 -39
  28. package/cjs/Core/Particles.js +51 -26
  29. package/cjs/Core/Retina.js +0 -2
  30. package/cjs/Core/Utils/QuadTree.js +1 -1
  31. package/cjs/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  32. package/cjs/Options/Classes/ColorAnimation.js +4 -24
  33. package/cjs/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  34. package/cjs/Options/Classes/Particles/Effect/Effect.js +36 -0
  35. package/cjs/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  36. package/cjs/Options/Classes/Particles/Number/ParticlesNumberLimit.js +21 -0
  37. package/cjs/Options/Classes/Particles/Opacity/Opacity.js +1 -2
  38. package/cjs/Options/Classes/Particles/ParticlesOptions.js +3 -0
  39. package/cjs/Options/Classes/Particles/Size/Size.js +2 -3
  40. package/cjs/Options/Classes/ValueWithRandom.js +1 -10
  41. package/cjs/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js +2 -0
  42. package/cjs/Utils/CanvasUtils.js +26 -21
  43. package/cjs/Utils/ColorUtils.js +24 -38
  44. package/cjs/Utils/NumberUtils.js +8 -18
  45. package/cjs/Utils/Utils.js +6 -6
  46. package/cjs/export-types.js +4 -0
  47. package/cjs/exports.js +2 -3
  48. package/esm/Core/Canvas.js +2 -2
  49. package/esm/Core/Container.js +36 -19
  50. package/esm/Core/Engine.js +18 -5
  51. package/esm/Core/Particle.js +75 -40
  52. package/esm/Core/Particles.js +51 -26
  53. package/esm/Core/Retina.js +0 -2
  54. package/esm/Core/Utils/QuadTree.js +1 -1
  55. package/esm/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  56. package/esm/Options/Classes/ColorAnimation.js +4 -24
  57. package/esm/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  58. package/esm/Options/Classes/Particles/Effect/Effect.js +32 -0
  59. package/esm/Options/Classes/Particles/Number/ParticlesNumber.js +3 -5
  60. package/esm/Options/Classes/Particles/Number/ParticlesNumberLimit.js +17 -0
  61. package/esm/Options/Classes/Particles/Opacity/Opacity.js +2 -3
  62. package/esm/Options/Classes/Particles/ParticlesOptions.js +3 -0
  63. package/esm/Options/Classes/Particles/Size/Size.js +2 -3
  64. package/esm/Options/Classes/ValueWithRandom.js +1 -10
  65. package/esm/Options/Interfaces/Particles/Effect/IEffect.js +1 -0
  66. package/esm/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js +1 -0
  67. package/esm/Utils/CanvasUtils.js +23 -18
  68. package/esm/Utils/ColorUtils.js +24 -38
  69. package/esm/Utils/NumberUtils.js +7 -16
  70. package/esm/Utils/Utils.js +7 -7
  71. package/esm/export-types.js +4 -0
  72. package/esm/exports.js +2 -3
  73. package/package.json +1 -1
  74. package/report.html +4 -22
  75. package/tsparticles.engine.js +387 -283
  76. package/tsparticles.engine.min.js +1 -1
  77. package/tsparticles.engine.min.js.LICENSE.txt +1 -1
  78. package/types/Core/Canvas.d.ts +0 -1
  79. package/types/Core/Container.d.ts +8 -7
  80. package/types/Core/Engine.d.ts +7 -2
  81. package/types/Core/Interfaces/IContainerPlugin.d.ts +2 -3
  82. package/types/Core/Interfaces/IEffectDrawer.d.ts +10 -0
  83. package/types/Core/Interfaces/IExternalInteractor.d.ts +3 -4
  84. package/types/Core/Interfaces/IInteractor.d.ts +3 -3
  85. package/types/Core/Interfaces/IParticleRetinaProps.d.ts +0 -1
  86. package/types/Core/Interfaces/IParticlesInteractor.d.ts +3 -3
  87. package/types/Core/Interfaces/IShapeDrawData.d.ts +10 -0
  88. package/types/Core/Interfaces/IShapeDrawer.d.ts +2 -10
  89. package/types/Core/Particle.d.ts +6 -2
  90. package/types/Core/Particles.d.ts +10 -7
  91. package/types/Core/Retina.d.ts +0 -1
  92. package/types/Core/Utils/ExternalInteractorBase.d.ts +4 -4
  93. package/types/Core/Utils/InteractionManager.d.ts +1 -2
  94. package/types/Core/Utils/ParticlesInteractorBase.d.ts +5 -5
  95. package/types/Enums/Modes/LimitMode.d.ts +4 -0
  96. package/types/Enums/Types/EasingType.d.ts +3 -0
  97. package/types/Options/Classes/BackgroundMask/BackgroundMask.d.ts +1 -1
  98. package/types/Options/Classes/ColorAnimation.d.ts +2 -7
  99. package/types/Options/Classes/Interactivity/Events/ClickEvent.d.ts +1 -2
  100. package/types/Options/Classes/Interactivity/Events/DivEvent.d.ts +1 -2
  101. package/types/Options/Classes/Interactivity/Events/Events.d.ts +3 -3
  102. package/types/Options/Classes/Interactivity/Events/HoverEvent.d.ts +2 -3
  103. package/types/Options/Classes/Interactivity/Interactivity.d.ts +2 -2
  104. package/types/Options/Classes/Options.d.ts +6 -6
  105. package/types/Options/Classes/Particles/Bounce/ParticlesBounce.d.ts +2 -2
  106. package/types/Options/Classes/Particles/Collisions/Collisions.d.ts +3 -3
  107. package/types/Options/Classes/Particles/Effect/Effect.d.ts +13 -0
  108. package/types/Options/Classes/Particles/Move/Move.d.ts +8 -8
  109. package/types/Options/Classes/Particles/Move/MoveTrail.d.ts +1 -1
  110. package/types/Options/Classes/Particles/Number/ParticlesNumber.d.ts +3 -2
  111. package/types/Options/Classes/Particles/Number/ParticlesNumberLimit.d.ts +10 -0
  112. package/types/Options/Classes/Particles/Opacity/Opacity.d.ts +3 -3
  113. package/types/Options/Classes/Particles/ParticlesOptions.d.ts +12 -10
  114. package/types/Options/Classes/Particles/Size/Size.d.ts +3 -3
  115. package/types/Options/Classes/Theme/Theme.d.ts +1 -1
  116. package/types/Options/Classes/ValueWithRandom.d.ts +2 -4
  117. package/types/Options/Interfaces/IValueWithRandom.d.ts +0 -2
  118. package/types/Options/Interfaces/Interactivity/Events/IClickEvent.d.ts +1 -2
  119. package/types/Options/Interfaces/Interactivity/Events/IDivEvent.d.ts +1 -2
  120. package/types/Options/Interfaces/Interactivity/Events/IHoverEvent.d.ts +1 -2
  121. package/types/Options/Interfaces/Particles/Effect/IEffect.d.ts +8 -0
  122. package/types/Options/Interfaces/Particles/IParticlesOptions.d.ts +2 -0
  123. package/types/Options/Interfaces/Particles/Number/IParticlesNumber.d.ts +2 -1
  124. package/types/Options/Interfaces/Particles/Number/IParticlesNumberLimit.d.ts +5 -0
  125. package/types/Utils/CanvasUtils.d.ts +2 -2
  126. package/types/Utils/NumberUtils.d.ts +0 -2
  127. package/types/Utils/Utils.d.ts +2 -3
  128. package/types/export-types.d.ts +5 -0
  129. package/types/exports.d.ts +2 -3
  130. package/umd/Core/Canvas.js +2 -2
  131. package/umd/Core/Container.js +36 -19
  132. package/umd/Core/Engine.js +18 -5
  133. package/umd/Core/Particle.js +74 -39
  134. package/umd/Core/Particles.js +51 -26
  135. package/umd/Core/Retina.js +0 -2
  136. package/umd/Core/Utils/QuadTree.js +1 -1
  137. package/umd/Options/Classes/BackgroundMask/BackgroundMask.js +1 -2
  138. package/umd/Options/Classes/ColorAnimation.js +5 -25
  139. package/umd/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js +0 -1
  140. package/umd/Options/Classes/Particles/Effect/Effect.js +46 -0
  141. package/umd/Options/Classes/Particles/Number/ParticlesNumber.js +4 -6
  142. package/umd/Options/Classes/{Random.js → Particles/Number/ParticlesNumberLimit.js} +9 -9
  143. package/umd/Options/Classes/Particles/Opacity/Opacity.js +1 -2
  144. package/umd/Options/Classes/Particles/ParticlesOptions.js +4 -1
  145. package/umd/Options/Classes/Particles/Size/Size.js +3 -4
  146. package/umd/Options/Classes/ValueWithRandom.js +2 -11
  147. package/umd/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js +12 -0
  148. package/umd/Utils/CanvasUtils.js +26 -21
  149. package/umd/Utils/ColorUtils.js +24 -38
  150. package/umd/Utils/NumberUtils.js +9 -19
  151. package/umd/Utils/Utils.js +6 -6
  152. package/umd/export-types.js +5 -1
  153. package/umd/exports.js +3 -4
  154. package/browser/Options/Classes/Random.js +0 -17
  155. package/cjs/Options/Classes/Random.js +0 -21
  156. package/esm/Options/Classes/Random.js +0 -17
  157. package/types/Enums/Modes/ClickMode.d.ts +0 -9
  158. package/types/Enums/Modes/DivMode.d.ts +0 -5
  159. package/types/Enums/Modes/HoverMode.d.ts +0 -11
  160. package/types/Options/Classes/Random.d.ts +0 -9
  161. package/types/Options/Interfaces/IRandom.d.ts +0 -4
  162. /package/browser/{Enums/Modes/ClickMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  163. /package/browser/{Enums/Modes/DivMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  164. /package/browser/Enums/Modes/{HoverMode.js → LimitMode.js} +0 -0
  165. /package/browser/Options/Interfaces/{IRandom.js → Particles/Effect/IEffect.js} +0 -0
  166. /package/{esm/Enums/Modes/ClickMode.js → browser/Options/Interfaces/Particles/Number/IParticlesNumberLimit.js} +0 -0
  167. /package/cjs/{Enums/Modes/ClickMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  168. /package/cjs/{Enums/Modes/DivMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  169. /package/cjs/Enums/Modes/{HoverMode.js → LimitMode.js} +0 -0
  170. /package/cjs/Options/Interfaces/{IRandom.js → Particles/Effect/IEffect.js} +0 -0
  171. /package/esm/{Enums/Modes/DivMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  172. /package/esm/{Enums/Modes/HoverMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  173. /package/esm/{Options/Interfaces/IRandom.js → Enums/Modes/LimitMode.js} +0 -0
  174. /package/umd/{Enums/Modes/ClickMode.js → Core/Interfaces/IEffectDrawer.js} +0 -0
  175. /package/umd/{Enums/Modes/DivMode.js → Core/Interfaces/IShapeDrawData.js} +0 -0
  176. /package/umd/Enums/Modes/{HoverMode.js → LimitMode.js} +0 -0
  177. /package/umd/Options/Interfaces/{IRandom.js → Particles/Effect/IEffect.js} +0 -0
@@ -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.4";
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
  }
@@ -154,18 +164,12 @@ class Particle {
154
164
  this.slow.inRange = false;
155
165
  const container = this.container, pathGenerator = this.pathGenerator;
156
166
  for (const [, plugin] of container.plugins) {
157
- if (plugin.particleDestroyed) {
158
- plugin.particleDestroyed(this, override);
159
- }
167
+ plugin.particleDestroyed && plugin.particleDestroyed(this, override);
160
168
  }
161
169
  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);
170
+ updater.particleDestroyed && updater.particleDestroyed(this, override);
168
171
  }
172
+ pathGenerator && pathGenerator.reset(this);
169
173
  }
170
174
  draw(delta) {
171
175
  const container = this.container, canvas = container.canvas;
@@ -178,7 +182,7 @@ class Particle {
178
182
  return this._getRollColor(this.bubble.color ?? (0, ColorUtils_js_1.getHslFromAnimation)(this.color));
179
183
  }
180
184
  getMass() {
181
- return (this.getRadius() ** 2 * Math.PI) / 2;
185
+ return this.getRadius() ** 2 * Math.PI * 0.5;
182
186
  }
183
187
  getPosition() {
184
188
  return {
@@ -197,9 +201,11 @@ class Particle {
197
201
  const container = this.container, engine = this._engine;
198
202
  this.id = id;
199
203
  this.group = group;
200
- this.fill = true;
204
+ this.effectClose = true;
205
+ this.effectFill = true;
206
+ this.shapeClose = true;
207
+ this.shapeFill = true;
201
208
  this.pathRotation = false;
202
- this.close = true;
203
209
  this.lastPathTime = 0;
204
210
  this.destroyed = false;
205
211
  this.unbreakable = false;
@@ -210,18 +216,33 @@ class Particle {
210
216
  };
211
217
  this.outType = "normal";
212
218
  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;
219
+ 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;
220
+ this.effect = (0, Utils_js_1.itemFromSingleOrMultiple)(effectType, this.id, reduceDuplicates);
214
221
  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);
222
+ const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
223
+ if (overrideOptions) {
224
+ if (overrideOptions.effect && overrideOptions.effect.type) {
225
+ const overrideEffectType = overrideOptions.effect.type, effect = (0, Utils_js_1.itemFromSingleOrMultiple)(overrideEffectType, this.id, reduceDuplicates);
226
+ if (effect) {
227
+ this.effect = effect;
228
+ effectOptions.load(overrideOptions.effect);
229
+ }
230
+ }
231
+ if (overrideOptions.shape && overrideOptions.shape.type) {
232
+ const overrideShapeType = overrideOptions.shape.type, shape = (0, Utils_js_1.itemFromSingleOrMultiple)(overrideShapeType, this.id, reduceDuplicates);
233
+ if (shape) {
234
+ this.shape = shape;
235
+ shapeOptions.load(overrideOptions.shape);
236
+ }
221
237
  }
222
238
  }
239
+ this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
223
240
  this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
224
241
  particlesOptions.load(overrideOptions);
242
+ const effectData = this.effectData;
243
+ if (effectData) {
244
+ particlesOptions.load(effectData.particles);
245
+ }
225
246
  const shapeData = this.shapeData;
226
247
  if (shapeData) {
227
248
  particlesOptions.load(shapeData.particles);
@@ -230,11 +251,13 @@ class Particle {
230
251
  interactivity.load(container.actualOptions.interactivity);
231
252
  interactivity.load(particlesOptions.interactivity);
232
253
  this.interactivity = interactivity;
233
- this.fill = shapeData?.fill ?? particlesOptions.shape.fill;
234
- this.close = shapeData?.close ?? particlesOptions.shape.close;
254
+ this.effectFill = effectData?.fill ?? particlesOptions.effect.fill;
255
+ this.effectClose = effectData?.close ?? particlesOptions.effect.close;
256
+ this.shapeFill = shapeData?.fill ?? particlesOptions.shape.fill;
257
+ this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
235
258
  this.options = particlesOptions;
236
259
  const pathOptions = this.options.move.path;
237
- this.pathDelay = (0, NumberUtils_js_1.getValue)(pathOptions.delay) * 1000;
260
+ this.pathDelay = (0, NumberUtils_js_1.getRangeValue)(pathOptions.delay.value) * 1000;
238
261
  if (pathOptions.generator) {
239
262
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
240
263
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
@@ -255,34 +278,46 @@ class Particle {
255
278
  this.velocity = this.initialVelocity.copy();
256
279
  this.moveDecay = 1 - (0, NumberUtils_js_1.getRangeValue)(this.options.move.decay);
257
280
  const particles = container.particles;
258
- particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
259
- particles.lastZIndex = this.position.z;
281
+ particles.setLastZIndex(this.position.z);
260
282
  this.zIndexFactor = this.position.z / container.zLayers;
261
283
  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);
284
+ let effectDrawer = container.effectDrawers.get(this.effect);
285
+ if (!effectDrawer) {
286
+ effectDrawer = this._engine.getEffectDrawer(this.effect);
287
+ if (effectDrawer) {
288
+ container.effectDrawers.set(this.effect, effectDrawer);
289
+ }
290
+ }
291
+ if (effectDrawer && effectDrawer.loadEffect) {
292
+ effectDrawer.loadEffect(this);
293
+ }
294
+ let shapeDrawer = container.shapeDrawers.get(this.shape);
295
+ if (!shapeDrawer) {
296
+ shapeDrawer = this._engine.getShapeDrawer(this.shape);
297
+ if (shapeDrawer) {
298
+ container.shapeDrawers.set(this.shape, shapeDrawer);
267
299
  }
268
300
  }
269
- if (drawer && drawer.loadShape) {
270
- drawer.loadShape(this);
301
+ if (shapeDrawer && shapeDrawer.loadShape) {
302
+ shapeDrawer.loadShape(this);
271
303
  }
272
- const sideCountFunc = drawer?.getSidesCount;
304
+ const sideCountFunc = shapeDrawer?.getSidesCount;
273
305
  if (sideCountFunc) {
274
306
  this.sides = sideCountFunc(this);
275
307
  }
276
308
  this.spawning = false;
277
309
  this.shadowColor = (0, ColorUtils_js_1.rangeColorToRgb)(this.options.shadow.color);
278
- for (const updater of container.particles.updaters) {
310
+ for (const updater of particles.updaters) {
279
311
  updater.init(this);
280
312
  }
281
- for (const mover of container.particles.movers) {
313
+ for (const mover of particles.movers) {
282
314
  mover.init && mover.init(this);
283
315
  }
284
- if (drawer && drawer.particleInit) {
285
- drawer.particleInit(container, this);
316
+ if (effectDrawer && effectDrawer.particleInit) {
317
+ effectDrawer.particleInit(container, this);
318
+ }
319
+ if (shapeDrawer && shapeDrawer.particleInit) {
320
+ shapeDrawer.particleInit(container, this);
286
321
  }
287
322
  for (const [, plugin] of container.plugins) {
288
323
  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;
@@ -5,7 +5,6 @@ const ValueWithRandom_js_1 = require("../../ValueWithRandom.js");
5
5
  class ParticlesBounceFactor extends ValueWithRandom_js_1.ValueWithRandom {
6
6
  constructor() {
7
7
  super();
8
- this.random.minimumValue = 0.1;
9
8
  this.value = 1;
10
9
  }
11
10
  }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Effect = void 0;
4
+ const Utils_js_1 = require("../../../../Utils/Utils.js");
5
+ class Effect {
6
+ constructor() {
7
+ this.close = true;
8
+ this.fill = true;
9
+ this.options = {};
10
+ this.type = [];
11
+ }
12
+ load(data) {
13
+ if (!data) {
14
+ return;
15
+ }
16
+ const options = data.options;
17
+ if (options !== undefined) {
18
+ for (const effect in options) {
19
+ const item = options[effect];
20
+ if (item) {
21
+ this.options[effect] = (0, Utils_js_1.deepExtend)(this.options[effect] ?? {}, item);
22
+ }
23
+ }
24
+ }
25
+ if (data.close !== undefined) {
26
+ this.close = data.close;
27
+ }
28
+ if (data.fill !== undefined) {
29
+ this.fill = data.fill;
30
+ }
31
+ if (data.type !== undefined) {
32
+ this.type = data.type;
33
+ }
34
+ }
35
+ }
36
+ exports.Effect = Effect;
@@ -2,10 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ParticlesNumber = void 0;
4
4
  const ParticlesDensity_js_1 = require("./ParticlesDensity.js");
5
+ const ParticlesNumberLimit_js_1 = require("./ParticlesNumberLimit.js");
5
6
  class ParticlesNumber {
6
7
  constructor() {
7
8
  this.density = new ParticlesDensity_js_1.ParticlesDensity();
8
- this.limit = 0;
9
+ this.limit = new ParticlesNumberLimit_js_1.ParticlesNumberLimit();
9
10
  this.value = 0;
10
11
  }
11
12
  load(data) {
@@ -13,10 +14,7 @@ class ParticlesNumber {
13
14
  return;
14
15
  }
15
16
  this.density.load(data.density);
16
- const limit = data.limit;
17
- if (limit !== undefined) {
18
- this.limit = limit;
19
- }
17
+ this.limit.load(data.limit);
20
18
  if (data.value !== undefined) {
21
19
  this.value = data.value;
22
20
  }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParticlesNumberLimit = void 0;
4
+ class ParticlesNumberLimit {
5
+ constructor() {
6
+ this.mode = "delete";
7
+ this.value = 0;
8
+ }
9
+ load(data) {
10
+ if (!data) {
11
+ return;
12
+ }
13
+ if (data.mode !== undefined) {
14
+ this.mode = data.mode;
15
+ }
16
+ if (data.value !== undefined) {
17
+ this.value = data.value;
18
+ }
19
+ }
20
+ }
21
+ exports.ParticlesNumberLimit = ParticlesNumberLimit;
@@ -3,11 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Opacity = void 0;
4
4
  const OpacityAnimation_js_1 = require("./OpacityAnimation.js");
5
5
  const ValueWithRandom_js_1 = require("../../ValueWithRandom.js");
6
- class Opacity extends ValueWithRandom_js_1.ValueWithRandom {
6
+ class Opacity extends ValueWithRandom_js_1.RangedAnimationValueWithRandom {
7
7
  constructor() {
8
8
  super();
9
9
  this.animation = new OpacityAnimation_js_1.OpacityAnimation();
10
- this.random.minimumValue = 0.1;
11
10
  this.value = 1;
12
11
  }
13
12
  load(data) {
@@ -4,6 +4,7 @@ exports.ParticlesOptions = void 0;
4
4
  const Utils_js_1 = require("../../../Utils/Utils.js");
5
5
  const AnimatableColor_js_1 = require("../AnimatableColor.js");
6
6
  const Collisions_js_1 = require("./Collisions/Collisions.js");
7
+ const Effect_js_1 = require("./Effect/Effect.js");
7
8
  const Move_js_1 = require("./Move/Move.js");
8
9
  const Opacity_js_1 = require("./Opacity/Opacity.js");
9
10
  const ParticlesBounce_js_1 = require("./Bounce/ParticlesBounce.js");
@@ -21,6 +22,7 @@ class ParticlesOptions {
21
22
  this.collisions = new Collisions_js_1.Collisions();
22
23
  this.color = new AnimatableColor_js_1.AnimatableColor();
23
24
  this.color.value = "#fff";
25
+ this.effect = new Effect_js_1.Effect();
24
26
  this.groups = {};
25
27
  this.move = new Move_js_1.Move();
26
28
  this.number = new ParticlesNumber_js_1.ParticlesNumber();
@@ -38,6 +40,7 @@ class ParticlesOptions {
38
40
  }
39
41
  this.bounce.load(data.bounce);
40
42
  this.color.load(AnimatableColor_js_1.AnimatableColor.create(this.color, data.color));
43
+ this.effect.load(data.effect);
41
44
  if (data.groups !== undefined) {
42
45
  for (const group in data.groups) {
43
46
  const item = data.groups[group];
@@ -1,13 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Size = void 0;
4
- const SizeAnimation_js_1 = require("./SizeAnimation.js");
5
4
  const ValueWithRandom_js_1 = require("../../ValueWithRandom.js");
6
- class Size extends ValueWithRandom_js_1.ValueWithRandom {
5
+ const SizeAnimation_js_1 = require("./SizeAnimation.js");
6
+ class Size extends ValueWithRandom_js_1.RangedAnimationValueWithRandom {
7
7
  constructor() {
8
8
  super();
9
9
  this.animation = new SizeAnimation_js_1.SizeAnimation();
10
- this.random.minimumValue = 1;
11
10
  this.value = 3;
12
11
  }
13
12
  load(data) {