@tsparticles/engine 3.0.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/373.min.js +2 -0
  2. package/373.min.js.LICENSE.txt +1 -0
  3. package/438.min.js +2 -0
  4. package/438.min.js.LICENSE.txt +1 -0
  5. package/README.md +337 -216
  6. package/browser/Core/Canvas.js +102 -49
  7. package/browser/Core/Container.js +53 -41
  8. package/browser/Core/Engine.js +47 -32
  9. package/browser/Core/Particle.js +46 -48
  10. package/browser/Core/Particles.js +70 -57
  11. package/browser/Core/Retina.js +5 -4
  12. package/browser/Core/Utils/Circle.js +4 -3
  13. package/browser/Core/Utils/Constants.js +3 -0
  14. package/browser/Core/Utils/EventListeners.js +19 -16
  15. package/browser/Core/Utils/ExternalInteractorBase.js +1 -1
  16. package/browser/Core/Utils/InteractionManager.js +17 -8
  17. package/browser/Core/Utils/ParticlesInteractorBase.js +1 -1
  18. package/browser/Core/Utils/QuadTree.js +5 -3
  19. package/browser/Core/Utils/Vector.js +7 -2
  20. package/browser/Core/Utils/Vector3d.js +14 -9
  21. package/browser/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  22. package/browser/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  23. package/browser/Options/Classes/ManualParticle.js +3 -2
  24. package/browser/Options/Classes/Options.js +3 -0
  25. package/browser/Utils/CanvasUtils.js +50 -40
  26. package/browser/Utils/ColorUtils.js +124 -45
  27. package/browser/Utils/EventDispatcher.js +6 -5
  28. package/browser/Utils/HslColorManager.js +5 -5
  29. package/browser/Utils/NumberUtils.js +35 -23
  30. package/browser/Utils/RgbColorManager.js +5 -5
  31. package/browser/Utils/Utils.js +102 -19
  32. package/cjs/Core/Canvas.js +102 -49
  33. package/cjs/Core/Container.js +53 -41
  34. package/cjs/Core/Engine.js +70 -32
  35. package/cjs/Core/Particle.js +45 -47
  36. package/cjs/Core/Particles.js +93 -57
  37. package/cjs/Core/Retina.js +5 -4
  38. package/cjs/Core/Utils/Circle.js +4 -3
  39. package/cjs/Core/Utils/Constants.js +4 -1
  40. package/cjs/Core/Utils/EventListeners.js +18 -15
  41. package/cjs/Core/Utils/ExternalInteractorBase.js +1 -1
  42. package/cjs/Core/Utils/InteractionManager.js +17 -8
  43. package/cjs/Core/Utils/ParticlesInteractorBase.js +1 -1
  44. package/cjs/Core/Utils/QuadTree.js +5 -3
  45. package/cjs/Core/Utils/Vector.js +7 -2
  46. package/cjs/Core/Utils/Vector3d.js +14 -9
  47. package/cjs/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  48. package/cjs/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  49. package/cjs/Options/Classes/ManualParticle.js +3 -2
  50. package/cjs/Options/Classes/Options.js +3 -0
  51. package/cjs/Utils/CanvasUtils.js +50 -40
  52. package/cjs/Utils/ColorUtils.js +126 -45
  53. package/cjs/Utils/EventDispatcher.js +6 -5
  54. package/cjs/Utils/HslColorManager.js +5 -5
  55. package/cjs/Utils/NumberUtils.js +37 -24
  56. package/cjs/Utils/RgbColorManager.js +5 -5
  57. package/cjs/Utils/Utils.js +103 -19
  58. package/dist_browser_Core_Container_js.js +92 -0
  59. package/dist_browser_Core_Particle_js.js +32 -0
  60. package/esm/Core/Canvas.js +102 -49
  61. package/esm/Core/Container.js +53 -41
  62. package/esm/Core/Engine.js +47 -32
  63. package/esm/Core/Particle.js +46 -48
  64. package/esm/Core/Particles.js +70 -57
  65. package/esm/Core/Retina.js +5 -4
  66. package/esm/Core/Utils/Circle.js +4 -3
  67. package/esm/Core/Utils/Constants.js +3 -0
  68. package/esm/Core/Utils/EventListeners.js +19 -16
  69. package/esm/Core/Utils/ExternalInteractorBase.js +1 -1
  70. package/esm/Core/Utils/InteractionManager.js +17 -8
  71. package/esm/Core/Utils/ParticlesInteractorBase.js +1 -1
  72. package/esm/Core/Utils/QuadTree.js +5 -3
  73. package/esm/Core/Utils/Vector.js +7 -2
  74. package/esm/Core/Utils/Vector3d.js +14 -9
  75. package/esm/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  76. package/esm/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  77. package/esm/Options/Classes/ManualParticle.js +3 -2
  78. package/esm/Options/Classes/Options.js +3 -0
  79. package/esm/Utils/CanvasUtils.js +50 -40
  80. package/esm/Utils/ColorUtils.js +124 -45
  81. package/esm/Utils/EventDispatcher.js +6 -5
  82. package/esm/Utils/HslColorManager.js +5 -5
  83. package/esm/Utils/NumberUtils.js +35 -23
  84. package/esm/Utils/RgbColorManager.js +5 -5
  85. package/esm/Utils/Utils.js +102 -19
  86. package/package.json +1 -1
  87. package/report.html +3 -3
  88. package/tsparticles.engine.js +894 -5461
  89. package/tsparticles.engine.min.js +1 -1
  90. package/tsparticles.engine.min.js.LICENSE.txt +1 -1
  91. package/types/Core/Canvas.d.ts +5 -3
  92. package/types/Core/Container.d.ts +1 -1
  93. package/types/Core/Engine.d.ts +13 -8
  94. package/types/Core/Interfaces/IContainerPlugin.d.ts +3 -3
  95. package/types/Core/Interfaces/IEffectDrawer.d.ts +3 -3
  96. package/types/Core/Interfaces/IMovePathGenerator.d.ts +2 -2
  97. package/types/Core/Interfaces/IParticleHslAnimation.d.ts +4 -4
  98. package/types/Core/Interfaces/IParticleMover.d.ts +2 -2
  99. package/types/Core/Interfaces/IParticleUpdater.d.ts +2 -2
  100. package/types/Core/Interfaces/IParticleValueAnimation.d.ts +4 -0
  101. package/types/Core/Interfaces/IPlugin.d.ts +1 -1
  102. package/types/Core/Interfaces/IShapeDrawData.d.ts +2 -2
  103. package/types/Core/Interfaces/IShapeDrawer.d.ts +4 -4
  104. package/types/Core/Particle.d.ts +3 -3
  105. package/types/Core/Particles.d.ts +12 -8
  106. package/types/Core/Utils/Constants.d.ts +3 -0
  107. package/types/Core/Utils/ExternalInteractorBase.d.ts +1 -1
  108. package/types/Core/Utils/InteractionManager.d.ts +3 -3
  109. package/types/Core/Utils/ParticlesInteractorBase.d.ts +1 -1
  110. package/types/Core/Utils/Point.d.ts +1 -1
  111. package/types/Enums/Modes/OutMode.d.ts +0 -3
  112. package/types/Options/Classes/BackgroundMask/BackgroundMaskCover.d.ts +2 -1
  113. package/types/Options/Classes/Options.d.ts +1 -0
  114. package/types/Options/Classes/Particles/Move/Move.d.ts +1 -2
  115. package/types/Options/Classes/Particles/Move/OutModes.d.ts +5 -6
  116. package/types/Options/Interfaces/BackgroundMask/IBackgroundMask.d.ts +2 -1
  117. package/types/Options/Interfaces/BackgroundMask/IBackgroundMaskCover.d.ts +2 -1
  118. package/types/Options/Interfaces/IOptions.d.ts +1 -0
  119. package/types/Options/Interfaces/Interactivity/Modes/IModes.d.ts +1 -3
  120. package/types/Options/Interfaces/Particles/Move/IMove.d.ts +2 -2
  121. package/types/Options/Interfaces/Particles/Move/IOutModes.d.ts +6 -6
  122. package/types/Types/CustomEventArgs.d.ts +2 -2
  123. package/types/Types/ExportResult.d.ts +2 -2
  124. package/types/Types/ParticlesGroups.d.ts +1 -3
  125. package/types/Types/PathOptions.d.ts +1 -3
  126. package/types/Types/ShapeData.d.ts +1 -3
  127. package/types/Utils/CanvasUtils.d.ts +9 -8
  128. package/types/Utils/ColorUtils.d.ts +5 -0
  129. package/types/Utils/NumberUtils.d.ts +2 -2
  130. package/types/Utils/Utils.d.ts +9 -6
  131. package/umd/Core/Canvas.js +102 -49
  132. package/umd/Core/Container.js +54 -42
  133. package/umd/Core/Engine.js +72 -33
  134. package/umd/Core/Particle.js +46 -48
  135. package/umd/Core/Particles.js +95 -58
  136. package/umd/Core/Retina.js +5 -4
  137. package/umd/Core/Utils/Circle.js +4 -3
  138. package/umd/Core/Utils/Constants.js +4 -1
  139. package/umd/Core/Utils/EventListeners.js +18 -15
  140. package/umd/Core/Utils/ExternalInteractorBase.js +1 -1
  141. package/umd/Core/Utils/InteractionManager.js +17 -8
  142. package/umd/Core/Utils/ParticlesInteractorBase.js +1 -1
  143. package/umd/Core/Utils/QuadTree.js +5 -3
  144. package/umd/Core/Utils/Vector.js +7 -2
  145. package/umd/Core/Utils/Vector3d.js +14 -9
  146. package/umd/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  147. package/umd/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  148. package/umd/Options/Classes/ManualParticle.js +3 -2
  149. package/umd/Options/Classes/Options.js +3 -0
  150. package/umd/Utils/CanvasUtils.js +50 -40
  151. package/umd/Utils/ColorUtils.js +127 -46
  152. package/umd/Utils/EventDispatcher.js +6 -5
  153. package/umd/Utils/HslColorManager.js +5 -5
  154. package/umd/Utils/NumberUtils.js +38 -25
  155. package/umd/Utils/RgbColorManager.js +5 -5
  156. package/umd/Utils/Utils.js +104 -20
@@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Particle = void 0;
4
4
  const NumberUtils_js_1 = require("../Utils/NumberUtils.js");
5
5
  const Utils_js_1 = require("../Utils/Utils.js");
6
+ const Constants_js_1 = require("./Utils/Constants.js");
6
7
  const ColorUtils_js_1 = require("../Utils/ColorUtils.js");
7
8
  const Interactivity_js_1 = require("../Options/Classes/Interactivity/Interactivity.js");
8
9
  const Vector_js_1 = require("./Utils/Vector.js");
9
10
  const Vector3d_js_1 = require("./Utils/Vector3d.js");
10
11
  const CanvasUtils_js_1 = require("../Utils/CanvasUtils.js");
11
- const Constants_js_1 = require("./Utils/Constants.js");
12
12
  const OptionsUtils_js_1 = require("../Utils/OptionsUtils.js");
13
+ const defaultRetryCount = 0, double = 2, half = 0.5, squareExp = 2;
13
14
  function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
14
15
  const effectData = effectOptions.options[effect];
15
16
  if (!effectData) {
@@ -34,7 +35,7 @@ function fixOutMode(data) {
34
35
  if (!(0, Utils_js_1.isInArray)(data.outMode, data.checkModes)) {
35
36
  return;
36
37
  }
37
- const diameter = data.radius * 2;
38
+ const diameter = data.radius * double;
38
39
  if (data.coord > data.maxCoord - diameter) {
39
40
  data.setCb(-data.radius);
40
41
  }
@@ -43,9 +44,9 @@ function fixOutMode(data) {
43
44
  }
44
45
  }
45
46
  class Particle {
46
- constructor(engine, id, container, position, overrideOptions, group) {
47
+ constructor(engine, container) {
47
48
  this.container = container;
48
- this._calcPosition = (container, position, zIndex, tryCount = 0) => {
49
+ this._calcPosition = (container, position, zIndex, tryCount = defaultRetryCount) => {
49
50
  for (const [, plugin] of container.plugins) {
50
51
  const pluginPos = plugin.particlePosition !== undefined ? plugin.particlePosition(position, this) : undefined;
51
52
  if (pluginPos) {
@@ -58,7 +59,7 @@ class Particle {
58
59
  }), pos = Vector3d_js_1.Vector3d.create(exactPosition.x, exactPosition.y, zIndex), radius = this.getRadius(), outModes = this.options.move.outModes, fixHorizontal = (outMode) => {
59
60
  fixOutMode({
60
61
  outMode,
61
- checkModes: ["bounce", "bounce-horizontal"],
62
+ checkModes: ["bounce"],
62
63
  coord: pos.x,
63
64
  maxCoord: container.canvas.size.width,
64
65
  setCb: (value) => (pos.x += value),
@@ -67,7 +68,7 @@ class Particle {
67
68
  }, fixVertical = (outMode) => {
68
69
  fixOutMode({
69
70
  outMode,
70
- checkModes: ["bounce", "bounce-vertical"],
71
+ checkModes: ["bounce"],
71
72
  coord: pos.y,
72
73
  maxCoord: container.canvas.size.height,
73
74
  setCb: (value) => (pos.y += value),
@@ -79,7 +80,8 @@ class Particle {
79
80
  fixVertical(outModes.top ?? outModes.default);
80
81
  fixVertical(outModes.bottom ?? outModes.default);
81
82
  if (this._checkOverlap(pos, tryCount)) {
82
- return this._calcPosition(container, undefined, zIndex, tryCount + 1);
83
+ const increment = 1;
84
+ return this._calcPosition(container, undefined, zIndex, tryCount + increment);
83
85
  }
84
86
  return pos;
85
87
  };
@@ -88,9 +90,9 @@ class Particle {
88
90
  if (moveOptions.direction === "inside" || moveOptions.direction === "outside") {
89
91
  return res;
90
92
  }
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 = {
92
- left: radOffset - rad * 0.5,
93
- right: radOffset + rad * 0.5,
93
+ const rad = (0, NumberUtils_js_1.degToRad)((0, NumberUtils_js_1.getRangeValue)(moveOptions.angle.value)), radOffset = (0, NumberUtils_js_1.degToRad)((0, NumberUtils_js_1.getRangeValue)(moveOptions.angle.offset)), range = {
94
+ left: radOffset - rad * half,
95
+ right: radOffset + rad * half,
94
96
  };
95
97
  if (!moveOptions.straight) {
96
98
  res.angle += (0, NumberUtils_js_1.randomInRange)((0, NumberUtils_js_1.setRangeValue)(range.left, range.right));
@@ -100,7 +102,7 @@ class Particle {
100
102
  }
101
103
  return res;
102
104
  };
103
- this._checkOverlap = (pos, tryCount = 0) => {
105
+ this._checkOverlap = (pos, tryCount = defaultRetryCount) => {
104
106
  const collisionsOptions = this.options.collisions, radius = this.getRadius();
105
107
  if (!collisionsOptions.enable) {
106
108
  return false;
@@ -109,8 +111,8 @@ class Particle {
109
111
  if (overlapOptions.enable) {
110
112
  return false;
111
113
  }
112
- const retries = overlapOptions.retries;
113
- if (retries >= 0 && tryCount > retries) {
114
+ const retries = overlapOptions.retries, minRetries = 0;
115
+ if (retries >= minRetries && tryCount > retries) {
114
116
  throw new Error(`${Constants_js_1.errorPrefix} particle is overlapping and can't be placed`);
115
117
  }
116
118
  return !!this.container.particles.find((particle) => (0, NumberUtils_js_1.getDistance)(pos, particle.position) < radius + particle.getRadius());
@@ -119,7 +121,7 @@ class Particle {
119
121
  if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
120
122
  return color;
121
123
  }
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;
124
+ const rollFactor = 1, none = 0, backFactor = this.roll.horizontal && this.roll.vertical ? double * rollFactor : rollFactor, backSum = this.roll.horizontal ? Math.PI * half : none, rolled = Math.floor(((this.roll.angle ?? none) + backSum) / (Math.PI / backFactor)) % double;
123
125
  if (!rolled) {
124
126
  return color;
125
127
  }
@@ -132,13 +134,13 @@ class Particle {
132
134
  return color;
133
135
  };
134
136
  this._initPosition = (position) => {
135
- const container = this.container, zIndexValue = (0, NumberUtils_js_1.getRangeValue)(this.options.zIndex.value);
136
- this.position = this._calcPosition(container, position, (0, NumberUtils_js_1.clamp)(zIndexValue, 0, container.zLayers));
137
+ const container = this.container, zIndexValue = (0, NumberUtils_js_1.getRangeValue)(this.options.zIndex.value), minZ = 0;
138
+ this.position = this._calcPosition(container, position, (0, NumberUtils_js_1.clamp)(zIndexValue, minZ, container.zLayers));
137
139
  this.initialPosition = this.position.copy();
138
- const canvasSize = container.canvas.size;
140
+ const canvasSize = container.canvas.size, defaultRadius = 0;
139
141
  this.moveCenter = {
140
142
  ...(0, Utils_js_1.getPosition)(this.options.move.center, canvasSize),
141
- radius: this.options.move.center.radius ?? 0,
143
+ radius: this.options.move.center.radius ?? defaultRadius,
142
144
  mode: this.options.move.center.mode ?? "percent",
143
145
  };
144
146
  this.direction = (0, NumberUtils_js_1.getParticleDirectionAngle)(this.options.move.direction, this.position, this.moveCenter);
@@ -153,7 +155,6 @@ class Particle {
153
155
  this.offset = Vector_js_1.Vector.origin;
154
156
  };
155
157
  this._engine = engine;
156
- this.init(id, position, overrideOptions, group);
157
158
  }
158
159
  destroy(override) {
159
160
  if (this.unbreakable || this.destroyed) {
@@ -163,14 +164,14 @@ class Particle {
163
164
  this.bubble.inRange = false;
164
165
  this.slow.inRange = false;
165
166
  const container = this.container, pathGenerator = this.pathGenerator, shapeDrawer = container.shapeDrawers.get(this.shape);
166
- shapeDrawer && shapeDrawer.particleDestroy && shapeDrawer.particleDestroy(this);
167
+ shapeDrawer?.particleDestroy?.(this);
167
168
  for (const [, plugin] of container.plugins) {
168
- plugin.particleDestroyed && plugin.particleDestroyed(this, override);
169
+ plugin.particleDestroyed?.(this, override);
169
170
  }
170
171
  for (const updater of container.particles.updaters) {
171
- updater.particleDestroyed && updater.particleDestroyed(this, override);
172
+ updater.particleDestroyed?.(this, override);
172
173
  }
173
- pathGenerator && pathGenerator.reset(this);
174
+ pathGenerator?.reset(this);
174
175
  this._engine.dispatchEvent("particleDestroyed", {
175
176
  container: this.container,
176
177
  data: {
@@ -178,18 +179,18 @@ class Particle {
178
179
  },
179
180
  });
180
181
  }
181
- draw(delta) {
182
+ async draw(delta) {
182
183
  const container = this.container, canvas = container.canvas;
183
184
  for (const [, plugin] of container.plugins) {
184
- canvas.drawParticlePlugin(plugin, this, delta);
185
+ await canvas.drawParticlePlugin(plugin, this, delta);
185
186
  }
186
- canvas.drawParticle(this, delta);
187
+ await canvas.drawParticle(this, delta);
187
188
  }
188
189
  getFillColor() {
189
190
  return this._getRollColor(this.bubble.color ?? (0, ColorUtils_js_1.getHslFromAnimation)(this.color));
190
191
  }
191
192
  getMass() {
192
- return this.getRadius() ** 2 * Math.PI * 0.5;
193
+ return this.getRadius() ** squareExp * Math.PI * half;
193
194
  }
194
195
  getPosition() {
195
196
  return {
@@ -204,7 +205,7 @@ class Particle {
204
205
  getStrokeColor() {
205
206
  return this._getRollColor(this.bubble.color ?? (0, ColorUtils_js_1.getHslFromAnimation)(this.strokeColor));
206
207
  }
207
- init(id, position, overrideOptions, group) {
208
+ async init(id, position, overrideOptions, group) {
208
209
  const container = this.container, engine = this._engine;
209
210
  this.id = id;
210
211
  this.group = group;
@@ -228,14 +229,14 @@ class Particle {
228
229
  this.shape = (0, Utils_js_1.itemFromSingleOrMultiple)(shapeType, this.id, reduceDuplicates);
229
230
  const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
230
231
  if (overrideOptions) {
231
- if (overrideOptions.effect && overrideOptions.effect.type) {
232
+ if (overrideOptions.effect?.type) {
232
233
  const overrideEffectType = overrideOptions.effect.type, effect = (0, Utils_js_1.itemFromSingleOrMultiple)(overrideEffectType, this.id, reduceDuplicates);
233
234
  if (effect) {
234
235
  this.effect = effect;
235
236
  effectOptions.load(overrideOptions.effect);
236
237
  }
237
238
  }
238
- if (overrideOptions.shape && overrideOptions.shape.type) {
239
+ if (overrideOptions.shape?.type) {
239
240
  const overrideShapeType = overrideOptions.shape.type, shape = (0, Utils_js_1.itemFromSingleOrMultiple)(overrideShapeType, this.id, reduceDuplicates);
240
241
  if (shape) {
241
242
  this.shape = shape;
@@ -264,11 +265,11 @@ class Particle {
264
265
  this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
265
266
  this.options = particlesOptions;
266
267
  const pathOptions = this.options.move.path;
267
- this.pathDelay = (0, NumberUtils_js_1.getRangeValue)(pathOptions.delay.value) * 1000;
268
+ this.pathDelay = (0, NumberUtils_js_1.getRangeValue)(pathOptions.delay.value) * Constants_js_1.millisecondsToSeconds;
268
269
  if (pathOptions.generator) {
269
270
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
270
271
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
271
- this.pathGenerator.init(container);
272
+ await this.pathGenerator.init(container);
272
273
  }
273
274
  }
274
275
  container.retina.initParticle(this);
@@ -283,7 +284,8 @@ class Particle {
283
284
  this._initPosition(position);
284
285
  this.initialVelocity = this._calculateVelocity();
285
286
  this.velocity = this.initialVelocity.copy();
286
- this.moveDecay = 1 - (0, NumberUtils_js_1.getRangeValue)(this.options.move.decay);
287
+ const decayOffset = 1;
288
+ this.moveDecay = decayOffset - (0, NumberUtils_js_1.getRangeValue)(this.options.move.decay);
287
289
  const particles = container.particles;
288
290
  particles.setLastZIndex(this.position.z);
289
291
  this.zIndexFactor = this.position.z / container.zLayers;
@@ -295,8 +297,8 @@ class Particle {
295
297
  container.effectDrawers.set(this.effect, effectDrawer);
296
298
  }
297
299
  }
298
- if (effectDrawer && effectDrawer.loadEffect) {
299
- effectDrawer.loadEffect(this);
300
+ if (effectDrawer?.loadEffect) {
301
+ await effectDrawer.loadEffect(this);
300
302
  }
301
303
  let shapeDrawer = container.shapeDrawers.get(this.shape);
302
304
  if (!shapeDrawer) {
@@ -305,8 +307,8 @@ class Particle {
305
307
  container.shapeDrawers.set(this.shape, shapeDrawer);
306
308
  }
307
309
  }
308
- if (shapeDrawer && shapeDrawer.loadShape) {
309
- shapeDrawer.loadShape(this);
310
+ if (shapeDrawer?.loadShape) {
311
+ await shapeDrawer.loadShape(this);
310
312
  }
311
313
  const sideCountFunc = shapeDrawer?.getSidesCount;
312
314
  if (sideCountFunc) {
@@ -315,19 +317,15 @@ class Particle {
315
317
  this.spawning = false;
316
318
  this.shadowColor = (0, ColorUtils_js_1.rangeColorToRgb)(this.options.shadow.color);
317
319
  for (const updater of particles.updaters) {
318
- updater.init(this);
320
+ await updater.init(this);
319
321
  }
320
322
  for (const mover of particles.movers) {
321
- mover.init && mover.init(this);
322
- }
323
- if (effectDrawer && effectDrawer.particleInit) {
324
- effectDrawer.particleInit(container, this);
325
- }
326
- if (shapeDrawer && shapeDrawer.particleInit) {
327
- shapeDrawer.particleInit(container, this);
323
+ await mover.init?.(this);
328
324
  }
325
+ await effectDrawer?.particleInit?.(container, this);
326
+ await shapeDrawer?.particleInit?.(container, this);
329
327
  for (const [, plugin] of container.plugins) {
330
- plugin.particleCreated && plugin.particleCreated(this);
328
+ plugin.particleCreated?.(this);
331
329
  }
332
330
  }
333
331
  isInsideCanvas() {
@@ -342,7 +340,7 @@ class Particle {
342
340
  }
343
341
  reset() {
344
342
  for (const updater of this.container.particles.updaters) {
345
- updater.reset && updater.reset(this);
343
+ updater.reset?.(this);
346
344
  }
347
345
  }
348
346
  }
@@ -1,14 +1,36 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.Particles = void 0;
4
27
  const Utils_js_1 = require("../Utils/Utils.js");
5
28
  const InteractionManager_js_1 = require("./Utils/InteractionManager.js");
6
- const Particle_js_1 = require("./Particle.js");
7
29
  const Point_js_1 = require("./Utils/Point.js");
8
30
  const QuadTree_js_1 = require("./Utils/QuadTree.js");
9
31
  const Rectangle_js_1 = require("./Utils/Rectangle.js");
10
32
  const Constants_js_1 = require("./Utils/Constants.js");
11
- const qTreeCapacity = 4;
33
+ const qTreeCapacity = 4, squareExp = 2, defaultRemoveQuantity = 1;
12
34
  const qTreeRectangle = (canvasSize) => {
13
35
  const { height, width } = canvasSize, posOffset = -0.25, sizeFactor = 1.5;
14
36
  return new Rectangle_js_1.Rectangle(posOffset * width, posOffset * height, sizeFactor * width, sizeFactor * height);
@@ -20,7 +42,7 @@ class Particles {
20
42
  this._pool.push(particle);
21
43
  }
22
44
  };
23
- this._applyDensity = (options, manualCount, group) => {
45
+ this._applyDensity = async (options, manualCount, group) => {
24
46
  const numberOptions = options.number;
25
47
  if (!options.number.density?.enable) {
26
48
  if (group === undefined) {
@@ -31,7 +53,7 @@ class Particles {
31
53
  }
32
54
  return;
33
55
  }
34
- 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);
56
+ const densityFactor = this._initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, minLimit = 0, optParticlesLimit = numberOptions.limit.value > minLimit ? numberOptions.limit.value : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount, particlesCount = Math.min(this.count, this.filter((t) => t.group === group).length);
35
57
  if (group === undefined) {
36
58
  this._limit = numberOptions.limit.value * densityFactor;
37
59
  }
@@ -39,29 +61,28 @@ class Particles {
39
61
  this._groupLimits.set(group, numberOptions.limit.value * densityFactor);
40
62
  }
41
63
  if (particlesCount < particlesNumber) {
42
- this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
64
+ await this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
43
65
  }
44
66
  else if (particlesCount > particlesNumber) {
45
67
  this.removeQuantity(particlesCount - particlesNumber, group);
46
68
  }
47
69
  };
48
70
  this._initDensityFactor = (densityOptions) => {
49
- const container = this._container;
71
+ const container = this._container, defaultFactor = 1;
50
72
  if (!container.canvas.element || !densityOptions.enable) {
51
- return 1;
73
+ return defaultFactor;
52
74
  }
53
75
  const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
54
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** 2);
76
+ return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
55
77
  };
56
- this._pushParticle = (position, overrideOptions, group, initializer) => {
78
+ this._pushParticle = async (position, overrideOptions, group, initializer) => {
57
79
  try {
58
80
  let particle = this._pool.pop();
59
- if (particle) {
60
- particle.init(this._nextId, position, overrideOptions, group);
61
- }
62
- else {
63
- particle = new Particle_js_1.Particle(this._engine, this._nextId, this._container, position, overrideOptions, group);
81
+ if (!particle) {
82
+ const { Particle } = await Promise.resolve().then(() => __importStar(require("./Particle.js")));
83
+ particle = new Particle(this._engine, this._container);
64
84
  }
85
+ await particle.init(this._nextId, position, overrideOptions, group);
65
86
  let canAdd = true;
66
87
  if (initializer) {
67
88
  canAdd = initializer(particle);
@@ -82,7 +103,6 @@ class Particles {
82
103
  }
83
104
  catch (e) {
84
105
  (0, Utils_js_1.getLogger)().warning(`${Constants_js_1.errorPrefix} adding particle: ${e}`);
85
- return;
86
106
  }
87
107
  };
88
108
  this._removeParticle = (index, group, override) => {
@@ -90,9 +110,9 @@ class Particles {
90
110
  if (!particle || particle.group !== group) {
91
111
  return false;
92
112
  }
93
- const zIdx = this._zArray.indexOf(particle);
94
- this._array.splice(index, 1);
95
- this._zArray.splice(zIdx, 1);
113
+ const zIdx = this._zArray.indexOf(particle), deleteCount = 1;
114
+ this._array.splice(index, deleteCount);
115
+ this._zArray.splice(zIdx, deleteCount);
96
116
  particle.destroy(override);
97
117
  this._engine.dispatchEvent("particleRemoved", {
98
118
  container: this._container,
@@ -114,26 +134,27 @@ class Particles {
114
134
  this._needsSort = false;
115
135
  this._lastZIndex = 0;
116
136
  this._interactionManager = new InteractionManager_js_1.InteractionManager(engine, container);
137
+ this._pluginsInitialized = false;
117
138
  const canvasSize = container.canvas.size;
118
139
  this.quadTree = new QuadTree_js_1.QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
119
- this.movers = this._engine.getMovers(container, true);
120
- this.updaters = this._engine.getUpdaters(container, true);
140
+ this.movers = [];
141
+ this.updaters = [];
121
142
  }
122
143
  get count() {
123
144
  return this._array.length;
124
145
  }
125
- addManualParticles() {
146
+ async addManualParticles() {
126
147
  const container = this._container, options = container.actualOptions;
127
148
  for (const particle of options.manualParticles) {
128
- this.addParticle(particle.position ? (0, Utils_js_1.getPosition)(particle.position, container.canvas.size) : undefined, particle.options);
149
+ await this.addParticle(particle.position ? (0, Utils_js_1.getPosition)(particle.position, container.canvas.size) : undefined, particle.options);
129
150
  }
130
151
  }
131
- addParticle(position, overrideOptions, group, initializer) {
132
- const limitOptions = this._container.actualOptions.particles.number.limit, limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit, currentCount = this.count;
133
- if (limit > 0) {
152
+ async addParticle(position, overrideOptions, group, initializer) {
153
+ const limitOptions = this._container.actualOptions.particles.number.limit, limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit, currentCount = this.count, minLimit = 0;
154
+ if (limit > minLimit) {
134
155
  if (limitOptions.mode === "delete") {
135
- const countToRemove = currentCount + 1 - limit;
136
- if (countToRemove > 0) {
156
+ const countOffset = 1, minCount = 0, countToRemove = currentCount + countOffset - limit;
157
+ if (countToRemove > minCount) {
137
158
  this.removeQuantity(countToRemove);
138
159
  }
139
160
  }
@@ -143,11 +164,12 @@ class Particles {
143
164
  }
144
165
  }
145
166
  }
146
- return this._pushParticle(position, overrideOptions, group, initializer);
167
+ return await this._pushParticle(position, overrideOptions, group, initializer);
147
168
  }
148
169
  clear() {
149
170
  this._array = [];
150
171
  this._zArray = [];
172
+ this._pluginsInitialized = false;
151
173
  }
152
174
  destroy() {
153
175
  this._array = [];
@@ -160,10 +182,10 @@ class Particles {
160
182
  canvas.clear();
161
183
  await this.update(delta);
162
184
  for (const [, plugin] of container.plugins) {
163
- canvas.drawPlugin(plugin, delta);
185
+ await canvas.drawPlugin(plugin, delta);
164
186
  }
165
187
  for (const p of this._zArray) {
166
- p.draw(delta);
188
+ await p.draw(delta);
167
189
  }
168
190
  }
169
191
  filter(condition) {
@@ -178,13 +200,12 @@ class Particles {
178
200
  handleClickMode(mode) {
179
201
  this._interactionManager.handleClickMode(mode);
180
202
  }
181
- init() {
203
+ async init() {
182
204
  const container = this._container, options = container.actualOptions;
183
205
  this._lastZIndex = 0;
184
206
  this._needsSort = false;
207
+ await this.initPlugins();
185
208
  let handled = false;
186
- this.updaters = this._engine.getUpdaters(container, true);
187
- this._interactionManager.init();
188
209
  for (const [, plugin] of container.plugins) {
189
210
  if (plugin.particlesInitialization !== undefined) {
190
211
  handled = plugin.particlesInitialization();
@@ -193,55 +214,67 @@ class Particles {
193
214
  break;
194
215
  }
195
216
  }
196
- this._interactionManager.init();
197
- for (const [, pathGenerator] of container.pathGenerators) {
198
- pathGenerator.init(container);
199
- }
200
- this.addManualParticles();
217
+ await this.addManualParticles();
201
218
  if (!handled) {
202
219
  const particlesOptions = options.particles, groups = particlesOptions.groups;
203
220
  for (const group in groups) {
204
221
  const groupOptions = groups[group];
205
222
  for (let i = this.count, j = 0; j < groupOptions.number?.value && i < particlesOptions.number.value; i++, j++) {
206
- this.addParticle(undefined, groupOptions, group);
223
+ await this.addParticle(undefined, groupOptions, group);
207
224
  }
208
225
  }
209
226
  for (let i = this.count; i < particlesOptions.number.value; i++) {
210
- this.addParticle();
227
+ await this.addParticle();
211
228
  }
212
229
  }
213
230
  }
214
- push(nb, mouse, overrideOptions, group) {
231
+ async initPlugins() {
232
+ if (this._pluginsInitialized) {
233
+ return;
234
+ }
235
+ const container = this._container;
236
+ this.movers = await this._engine.getMovers(container, true);
237
+ this.updaters = await this._engine.getUpdaters(container, true);
238
+ await this._interactionManager.init();
239
+ for (const [, pathGenerator] of container.pathGenerators) {
240
+ await pathGenerator.init(container);
241
+ }
242
+ }
243
+ async push(nb, mouse, overrideOptions, group) {
215
244
  for (let i = 0; i < nb; i++) {
216
- this.addParticle(mouse?.position, overrideOptions, group);
245
+ await this.addParticle(mouse?.position, overrideOptions, group);
217
246
  }
218
247
  }
219
248
  async redraw() {
220
249
  this.clear();
221
- this.init();
250
+ await this.init();
222
251
  await this.draw({ value: 0, factor: 0 });
223
252
  }
224
253
  remove(particle, group, override) {
225
254
  this.removeAt(this._array.indexOf(particle), undefined, group, override);
226
255
  }
227
- removeAt(index, quantity = 1, group, override) {
228
- if (index < 0 || index > this.count) {
256
+ removeAt(index, quantity = defaultRemoveQuantity, group, override) {
257
+ const minIndex = 0;
258
+ if (index < minIndex || index > this.count) {
229
259
  return;
230
260
  }
231
261
  let deleted = 0;
232
262
  for (let i = index; deleted < quantity && i < this.count; i++) {
233
- this._removeParticle(i--, group, override) && deleted++;
263
+ if (this._removeParticle(i--, group, override)) {
264
+ deleted++;
265
+ }
234
266
  }
235
267
  }
236
268
  removeQuantity(quantity, group) {
237
- this.removeAt(0, quantity, group);
269
+ const defaultIndex = 0;
270
+ this.removeAt(defaultIndex, quantity, group);
238
271
  }
239
- setDensity() {
240
- const options = this._container.actualOptions, groups = options.particles.groups;
272
+ async setDensity() {
273
+ const options = this._container.actualOptions, groups = options.particles.groups, manualCount = 0;
241
274
  for (const group in groups) {
242
- this._applyDensity(groups[group], 0, group);
275
+ await this._applyDensity(groups[group], manualCount, group);
243
276
  }
244
- this._applyDensity(options.particles, options.manualParticles.length);
277
+ await this._applyDensity(options.particles, options.manualParticles.length);
245
278
  }
246
279
  setLastZIndex(zIndex) {
247
280
  this._lastZIndex = zIndex;
@@ -257,7 +290,7 @@ class Particles {
257
290
  pathGenerator.update();
258
291
  }
259
292
  for (const [, plugin] of container.plugins) {
260
- plugin.update && (await plugin.update(delta));
293
+ await plugin.update?.(delta);
261
294
  }
262
295
  const resizeFactor = this._resizeFactor;
263
296
  for (const particle of this._array) {
@@ -268,15 +301,17 @@ class Particles {
268
301
  particle.initialPosition.y *= resizeFactor.height;
269
302
  }
270
303
  particle.ignoresResizeRatio = false;
271
- await this._interactionManager.reset(particle);
304
+ this._interactionManager.reset(particle);
272
305
  for (const [, plugin] of this._container.plugins) {
273
306
  if (particle.destroyed) {
274
307
  break;
275
308
  }
276
- plugin.particleUpdate && plugin.particleUpdate(particle, delta);
309
+ plugin.particleUpdate?.(particle, delta);
277
310
  }
278
311
  for (const mover of this.movers) {
279
- mover.isEnabled(particle) && mover.move(particle, delta);
312
+ if (mover.isEnabled(particle)) {
313
+ await mover.move(particle, delta);
314
+ }
280
315
  }
281
316
  if (particle.destroyed) {
282
317
  particlesToDelete.add(particle);
@@ -301,7 +336,7 @@ class Particles {
301
336
  await this._interactionManager.externalInteract(delta);
302
337
  for (const particle of this._array) {
303
338
  for (const updater of this.updaters) {
304
- updater.update(particle, delta);
339
+ await updater.update(particle, delta);
305
340
  }
306
341
  if (!particle.destroyed && !particle.spawning) {
307
342
  await this._interactionManager.particlesInteract(particle, delta);
@@ -311,7 +346,8 @@ class Particles {
311
346
  if (this._needsSort) {
312
347
  const zArray = this._zArray;
313
348
  zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
314
- this._lastZIndex = zArray[zArray.length - 1].position.z;
349
+ const lengthOffset = 1;
350
+ this._lastZIndex = zArray[zArray.length - lengthOffset].position.z;
315
351
  this._needsSort = false;
316
352
  }
317
353
  }
@@ -3,16 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Retina = void 0;
4
4
  const NumberUtils_js_1 = require("../Utils/NumberUtils.js");
5
5
  const Utils_js_1 = require("../Utils/Utils.js");
6
+ const defaultRatio = 1, defaultReduceFactor = 1;
6
7
  class Retina {
7
8
  constructor(container) {
8
9
  this.container = container;
9
- this.pixelRatio = 1;
10
- this.reduceFactor = 1;
10
+ this.pixelRatio = defaultRatio;
11
+ this.reduceFactor = defaultReduceFactor;
11
12
  }
12
13
  init() {
13
14
  const container = this.container, options = container.actualOptions;
14
- this.pixelRatio = !options.detectRetina || (0, Utils_js_1.isSsr)() ? 1 : window.devicePixelRatio;
15
- this.reduceFactor = 1;
15
+ this.pixelRatio = !options.detectRetina || (0, Utils_js_1.isSsr)() ? defaultRatio : window.devicePixelRatio;
16
+ this.reduceFactor = defaultReduceFactor;
16
17
  const ratio = this.pixelRatio, canvas = container.canvas;
17
18
  if (canvas.element) {
18
19
  const element = canvas.element;
@@ -4,6 +4,7 @@ exports.Circle = void 0;
4
4
  const Range_js_1 = require("./Range.js");
5
5
  const Rectangle_js_1 = require("./Rectangle.js");
6
6
  const NumberUtils_js_1 = require("../../Utils/NumberUtils.js");
7
+ const squareExp = 2;
7
8
  class Circle extends Range_js_1.Range {
8
9
  constructor(x, y, radius) {
9
10
  super(x, y);
@@ -15,12 +16,12 @@ class Circle extends Range_js_1.Range {
15
16
  intersects(range) {
16
17
  const pos1 = this.position, pos2 = range.position, distPos = { x: Math.abs(pos2.x - pos1.x), y: Math.abs(pos2.y - pos1.y) }, r = this.radius;
17
18
  if (range instanceof Circle) {
18
- const rSum = r + range.radius, dist = Math.sqrt(distPos.x ** 2 + distPos.y ** 2);
19
+ const rSum = r + range.radius, dist = Math.sqrt(distPos.x ** squareExp + distPos.y ** squareExp);
19
20
  return rSum > dist;
20
21
  }
21
22
  else if (range instanceof Rectangle_js_1.Rectangle) {
22
- const { width, height } = range.size, edges = Math.pow(distPos.x - width, 2) + Math.pow(distPos.y - height, 2);
23
- return (edges <= r ** 2 ||
23
+ const { width, height } = range.size, edges = Math.pow(distPos.x - width, squareExp) + Math.pow(distPos.y - height, squareExp);
24
+ return (edges <= r ** squareExp ||
24
25
  (distPos.x <= r + width && distPos.y <= r + height) ||
25
26
  distPos.x <= width ||
26
27
  distPos.y <= height);