@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
@@ -24,13 +24,13 @@ export class RgbColorManager {
24
24
  if (!input.startsWith(this.stringPrefix)) {
25
25
  return;
26
26
  }
27
- const regex = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([\d.%]+)\s*)?\)/i, result = regex.exec(input);
27
+ const regex = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([\d.%]+)\s*)?\)/i, result = regex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
28
28
  return result
29
29
  ? {
30
- a: result.length > 4 ? parseAlpha(result[5]) : 1,
31
- b: parseInt(result[3], 10),
32
- g: parseInt(result[2], 10),
33
- r: parseInt(result[1], 10),
30
+ a: result.length > minLength ? parseAlpha(result[5]) : defaultAlpha,
31
+ b: parseInt(result[3], radix),
32
+ g: parseInt(result[2], radix),
33
+ r: parseInt(result[1], radix),
34
34
  }
35
35
  : undefined;
36
36
  }
@@ -1,4 +1,5 @@
1
- import { collisionVelocity, getDistances, getRandom, getRangeMax, getRangeMin, getRangeValue, randomInRange, } from "./NumberUtils.js";
1
+ import { clamp, collisionVelocity, getDistances, getRandom, getRangeMax, getRangeMin, getRangeValue, randomInRange, } from "./NumberUtils.js";
2
+ import { halfRandom, millisecondsToSeconds, percentDenominator } from "../Core/Utils/Constants.js";
2
3
  import { Vector } from "../Core/Utils/Vector.js";
3
4
  const _logger = {
4
5
  debug: console.debug,
@@ -20,15 +21,15 @@ export function getLogger() {
20
21
  return _logger;
21
22
  }
22
23
  function rectSideBounce(data) {
23
- const res = { bounced: false }, { pSide, pOtherSide, rectSide, rectOtherSide, velocity, factor } = data;
24
+ const res = { bounced: false }, { pSide, pOtherSide, rectSide, rectOtherSide, velocity, factor } = data, half = 0.5, minVelocity = 0;
24
25
  if (pOtherSide.min < rectOtherSide.min ||
25
26
  pOtherSide.min > rectOtherSide.max ||
26
27
  pOtherSide.max < rectOtherSide.min ||
27
28
  pOtherSide.max > rectOtherSide.max) {
28
29
  return res;
29
30
  }
30
- if ((pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) * 0.5 && velocity > 0) ||
31
- (pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) * 0.5 && velocity < 0)) {
31
+ if ((pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) * half && velocity > minVelocity) ||
32
+ (pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) * half && velocity < minVelocity)) {
32
33
  res.velocity = velocity * -factor;
33
34
  res.bounced = true;
34
35
  }
@@ -65,7 +66,8 @@ export function safeMutationObserver(callback) {
65
66
  return new MutationObserver(callback);
66
67
  }
67
68
  export function isInArray(value, array) {
68
- return value === array || (isArray(array) && array.indexOf(value) > -1);
69
+ const invalidIndex = -1;
70
+ return value === array || (isArray(array) && array.indexOf(value) > invalidIndex);
69
71
  }
70
72
  export async function loadFont(font, weight) {
71
73
  try {
@@ -81,7 +83,8 @@ export function itemFromArray(array, index, useIndex = true) {
81
83
  return array[index !== undefined && useIndex ? index % array.length : arrayRandomIndex(array)];
82
84
  }
83
85
  export function isPointInside(point, size, offset, radius, direction) {
84
- return areBoundsInside(calculateBounds(point, radius ?? 0), size, offset, direction);
86
+ const minRadius = 0;
87
+ return areBoundsInside(calculateBounds(point, radius ?? minRadius), size, offset, direction);
85
88
  }
86
89
  export function areBoundsInside(bounds, size, offset, direction) {
87
90
  let inside = true;
@@ -171,8 +174,8 @@ export function circleBounceDataFromParticle(p) {
171
174
  };
172
175
  }
173
176
  export function circleBounce(p1, p2) {
174
- const { x: xVelocityDiff, y: yVelocityDiff } = p1.velocity.sub(p2.velocity), [pos1, pos2] = [p1.position, p2.position], { dx: xDist, dy: yDist } = getDistances(pos2, pos1);
175
- if (xVelocityDiff * xDist + yVelocityDiff * yDist < 0) {
177
+ const { x: xVelocityDiff, y: yVelocityDiff } = p1.velocity.sub(p2.velocity), [pos1, pos2] = [p1.position, p2.position], { dx: xDist, dy: yDist } = getDistances(pos2, pos1), minimumDistance = 0;
178
+ if (xVelocityDiff * xDist + yVelocityDiff * yDist < minimumDistance) {
176
179
  return;
177
180
  }
178
181
  const angle = -Math.atan2(yDist, xDist), m1 = p1.mass, m2 = p2.mass, u1 = p1.velocity.rotate(angle), u2 = p2.velocity.rotate(angle), v1 = collisionVelocity(u1, u2, m1, m2), v2 = collisionVelocity(u2, u1, m1, m2), vFinal1 = v1.rotate(-angle), vFinal2 = v2.rotate(-angle);
@@ -240,17 +243,22 @@ export function rectBounce(particle, divBounds) {
240
243
  }
241
244
  }
242
245
  export function executeOnSingleOrMultiple(obj, callback) {
243
- return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, 0);
246
+ const defaultIndex = 0;
247
+ return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, defaultIndex);
244
248
  }
245
249
  export function itemFromSingleOrMultiple(obj, index, useIndex) {
246
250
  return isArray(obj) ? itemFromArray(obj, index, useIndex) : obj;
247
251
  }
248
252
  export function findItemFromSingleOrMultiple(obj, callback) {
249
- return isArray(obj) ? obj.find((t, index) => callback(t, index)) : callback(obj, 0) ? obj : undefined;
253
+ if (isArray(obj)) {
254
+ return obj.find((t, index) => callback(t, index));
255
+ }
256
+ const defaultIndex = 0;
257
+ return callback(obj, defaultIndex) ? obj : undefined;
250
258
  }
251
259
  export function initParticleNumericAnimationValue(options, pxRatio) {
252
260
  const valueRange = options.value, animationOptions = options.animation, res = {
253
- delayTime: getRangeValue(animationOptions.delay) * 1000,
261
+ delayTime: getRangeValue(animationOptions.delay) * millisecondsToSeconds,
254
262
  enable: animationOptions.enable,
255
263
  value: getRangeValue(options.value) * pxRatio,
256
264
  max: getRangeMax(valueRange) * pxRatio,
@@ -258,9 +266,9 @@ export function initParticleNumericAnimationValue(options, pxRatio) {
258
266
  loops: 0,
259
267
  maxLoops: getRangeValue(animationOptions.count),
260
268
  time: 0,
261
- };
269
+ }, decayOffset = 1;
262
270
  if (animationOptions.enable) {
263
- res.decay = 1 - getRangeValue(animationOptions.decay);
271
+ res.decay = decayOffset - getRangeValue(animationOptions.decay);
264
272
  switch (animationOptions.mode) {
265
273
  case "increase":
266
274
  res.status = "increasing";
@@ -269,7 +277,7 @@ export function initParticleNumericAnimationValue(options, pxRatio) {
269
277
  res.status = "decreasing";
270
278
  break;
271
279
  case "random":
272
- res.status = getRandom() >= 0.5 ? "increasing" : "decreasing";
280
+ res.status = getRandom() >= halfRandom ? "increasing" : "decreasing";
273
281
  break;
274
282
  }
275
283
  const autoStatus = animationOptions.mode === "auto";
@@ -290,7 +298,7 @@ export function initParticleNumericAnimationValue(options, pxRatio) {
290
298
  default:
291
299
  res.value = randomInRange(res);
292
300
  if (autoStatus) {
293
- res.status = getRandom() >= 0.5 ? "increasing" : "decreasing";
301
+ res.status = getRandom() >= halfRandom ? "increasing" : "decreasing";
294
302
  }
295
303
  break;
296
304
  }
@@ -307,14 +315,14 @@ function getPositionOrSize(positionOrSize, canvasSize) {
307
315
  const isPosition = "x" in positionOrSize;
308
316
  if (isPosition) {
309
317
  return {
310
- x: (positionOrSize.x / 100) * canvasSize.width,
311
- y: (positionOrSize.y / 100) * canvasSize.height,
318
+ x: (positionOrSize.x / percentDenominator) * canvasSize.width,
319
+ y: (positionOrSize.y / percentDenominator) * canvasSize.height,
312
320
  };
313
321
  }
314
322
  else {
315
323
  return {
316
- width: (positionOrSize.width / 100) * canvasSize.width,
317
- height: (positionOrSize.height / 100) * canvasSize.height,
324
+ width: (positionOrSize.width / percentDenominator) * canvasSize.width,
325
+ height: (positionOrSize.height / percentDenominator) * canvasSize.height,
318
326
  };
319
327
  }
320
328
  }
@@ -342,3 +350,78 @@ export function isObject(arg) {
342
350
  export function isArray(arg) {
343
351
  return Array.isArray(arg);
344
352
  }
353
+ function checkDestroy(particle, destroyType, value, minValue, maxValue) {
354
+ switch (destroyType) {
355
+ case "max":
356
+ if (value >= maxValue) {
357
+ particle.destroy();
358
+ }
359
+ break;
360
+ case "min":
361
+ if (value <= minValue) {
362
+ particle.destroy();
363
+ }
364
+ break;
365
+ }
366
+ }
367
+ export function updateAnimation(particle, data, changeDirection, destroyType, delta) {
368
+ const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minDecay = 1;
369
+ if (particle.destroyed ||
370
+ !data ||
371
+ !data.enable ||
372
+ ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
373
+ return;
374
+ }
375
+ const velocity = (data.velocity ?? minVelocity) * delta.factor, minValue = data.min, maxValue = data.max, decay = data.decay ?? minDecay;
376
+ if (!data.time) {
377
+ data.time = 0;
378
+ }
379
+ if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
380
+ data.time += delta.value;
381
+ }
382
+ if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
383
+ return;
384
+ }
385
+ switch (data.status) {
386
+ case "increasing":
387
+ if (data.value >= maxValue) {
388
+ if (changeDirection) {
389
+ data.status = "decreasing";
390
+ }
391
+ else {
392
+ data.value -= maxValue;
393
+ }
394
+ if (!data.loops) {
395
+ data.loops = minLoops;
396
+ }
397
+ data.loops++;
398
+ }
399
+ else {
400
+ data.value += velocity;
401
+ }
402
+ break;
403
+ case "decreasing":
404
+ if (data.value <= minValue) {
405
+ if (changeDirection) {
406
+ data.status = "increasing";
407
+ }
408
+ else {
409
+ data.value += maxValue;
410
+ }
411
+ if (!data.loops) {
412
+ data.loops = minLoops;
413
+ }
414
+ data.loops++;
415
+ }
416
+ else {
417
+ data.value -= velocity;
418
+ }
419
+ }
420
+ if (data.velocity && decay !== identity) {
421
+ data.velocity *= decay;
422
+ }
423
+ checkDestroy(particle, destroyType, data.value, minValue, maxValue);
424
+ if (!particle.destroyed) {
425
+ data.value = clamp(data.value, minValue, maxValue);
426
+ }
427
+ }
@@ -6,9 +6,29 @@ const Utils_js_1 = require("../Utils/Utils.js");
6
6
  const ColorUtils_js_1 = require("../Utils/ColorUtils.js");
7
7
  const Constants_js_1 = require("./Utils/Constants.js");
8
8
  function setTransformValue(factor, newFactor, key) {
9
- const newValue = newFactor[key];
9
+ const newValue = newFactor[key], defaultValue = 1;
10
10
  if (newValue !== undefined) {
11
- factor[key] = (factor[key] ?? 1) * newValue;
11
+ factor[key] = (factor[key] ?? defaultValue) * newValue;
12
+ }
13
+ }
14
+ function setStyle(canvas, style, important = false) {
15
+ if (!style) {
16
+ return;
17
+ }
18
+ const element = canvas;
19
+ if (!element) {
20
+ return;
21
+ }
22
+ const elementStyle = element.style;
23
+ if (!elementStyle) {
24
+ return;
25
+ }
26
+ for (const key in style) {
27
+ const value = style[key];
28
+ if (!value) {
29
+ continue;
30
+ }
31
+ elementStyle.setProperty(key, value, important ? "important" : "");
12
32
  }
13
33
  }
14
34
  class Canvas {
@@ -16,7 +36,7 @@ class Canvas {
16
36
  this.container = container;
17
37
  this._applyPostDrawUpdaters = (particle) => {
18
38
  for (const updater of this._postDrawUpdaters) {
19
- updater.afterDraw && updater.afterDraw(particle);
39
+ updater.afterDraw?.(particle);
20
40
  }
21
41
  };
22
42
  this._applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
@@ -36,12 +56,12 @@ class Canvas {
36
56
  setTransformValue(transform, updaterTransform, key);
37
57
  }
38
58
  }
39
- updater.beforeDraw && updater.beforeDraw(particle);
59
+ updater.beforeDraw?.(particle);
40
60
  }
41
61
  };
42
62
  this._applyResizePlugins = () => {
43
63
  for (const plugin of this._resizePlugins) {
44
- plugin.resize && plugin.resize();
64
+ plugin.resize?.();
45
65
  }
46
66
  };
47
67
  this._getPluginParticleColors = (particle) => {
@@ -59,14 +79,36 @@ class Canvas {
59
79
  }
60
80
  return [fColor, sColor];
61
81
  };
62
- this._initCover = () => {
63
- const options = this.container.actualOptions, cover = options.backgroundMask.cover, color = cover.color, coverRgb = (0, ColorUtils_js_1.rangeColorToRgb)(color);
64
- if (coverRgb) {
65
- const coverColor = {
66
- ...coverRgb,
67
- a: cover.opacity,
68
- };
69
- this._coverColorStyle = (0, ColorUtils_js_1.getStyleFromRgb)(coverColor, coverColor.a);
82
+ this._initCover = async () => {
83
+ const options = this.container.actualOptions, cover = options.backgroundMask.cover, color = cover.color;
84
+ if (color) {
85
+ const coverRgb = (0, ColorUtils_js_1.rangeColorToRgb)(color);
86
+ if (coverRgb) {
87
+ const coverColor = {
88
+ ...coverRgb,
89
+ a: cover.opacity,
90
+ };
91
+ this._coverColorStyle = (0, ColorUtils_js_1.getStyleFromRgb)(coverColor, coverColor.a);
92
+ }
93
+ }
94
+ else {
95
+ await new Promise((resolve, reject) => {
96
+ if (!cover.image) {
97
+ return;
98
+ }
99
+ const img = document.createElement("img");
100
+ img.addEventListener("load", () => {
101
+ this._coverImage = {
102
+ image: img,
103
+ opacity: cover.opacity,
104
+ };
105
+ resolve();
106
+ });
107
+ img.addEventListener("error", (evt) => {
108
+ reject(evt.error);
109
+ });
110
+ img.src = cover.image;
111
+ });
70
112
  }
71
113
  };
72
114
  this._initStyle = () => {
@@ -97,17 +139,17 @@ class Canvas {
97
139
  if (!trail.enable) {
98
140
  return;
99
141
  }
142
+ const factorNumerator = 1, opacity = factorNumerator / trail.length;
100
143
  if (trailFill.color) {
101
144
  const fillColor = (0, ColorUtils_js_1.rangeColorToRgb)(trailFill.color);
102
145
  if (!fillColor) {
103
146
  return;
104
147
  }
105
- const trail = options.particles.move.trail;
106
148
  this._trailFill = {
107
149
  color: {
108
150
  ...fillColor,
109
151
  },
110
- opacity: 1 / trail.length,
152
+ opacity,
111
153
  };
112
154
  }
113
155
  else {
@@ -119,7 +161,7 @@ class Canvas {
119
161
  img.addEventListener("load", () => {
120
162
  this._trailFill = {
121
163
  image: img,
122
- opacity: 1 / trail.length,
164
+ opacity,
123
165
  };
124
166
  resolve();
125
167
  });
@@ -151,13 +193,7 @@ class Canvas {
151
193
  if (!(element && originalStyle)) {
152
194
  return;
153
195
  }
154
- const style = element.style;
155
- style.position = originalStyle.position;
156
- style.zIndex = originalStyle.zIndex;
157
- style.top = originalStyle.top;
158
- style.left = originalStyle.left;
159
- style.width = originalStyle.width;
160
- style.height = originalStyle.height;
196
+ setStyle(element, originalStyle);
161
197
  };
162
198
  this._safeMutationObserver = (callback) => {
163
199
  if (!this._mutationObserver) {
@@ -170,13 +206,15 @@ class Canvas {
170
206
  if (!element) {
171
207
  return;
172
208
  }
173
- const priority = "important", style = element.style;
174
- style.setProperty("position", "fixed", priority);
175
- style.setProperty("z-index", this.container.actualOptions.fullScreen.zIndex.toString(10), priority);
176
- style.setProperty("top", "0", priority);
177
- style.setProperty("left", "0", priority);
178
- style.setProperty("width", "100%", priority);
179
- style.setProperty("height", "100%", priority);
209
+ const radix = 10;
210
+ setStyle(element, {
211
+ position: "fixed",
212
+ zIndex: this.container.actualOptions.fullScreen.zIndex.toString(radix),
213
+ top: "0",
214
+ left: "0",
215
+ width: "100%",
216
+ height: "100%",
217
+ }, true);
180
218
  };
181
219
  this.size = {
182
220
  height: 0,
@@ -193,11 +231,11 @@ class Canvas {
193
231
  return this.container.actualOptions.fullScreen.enable;
194
232
  }
195
233
  clear() {
196
- const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = this._trailFill;
234
+ const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = this._trailFill, minimumLength = 0;
197
235
  if (options.backgroundMask.enable) {
198
236
  this.paint();
199
237
  }
200
- else if (trail.enable && trail.length > 0 && trailFill) {
238
+ else if (trail.enable && trail.length > minimumLength && trailFill) {
201
239
  if (trailFill.color) {
202
240
  this._paintBase((0, ColorUtils_js_1.getStyleFromRgb)(trailFill.color, trailFill.opacity));
203
241
  }
@@ -215,7 +253,7 @@ class Canvas {
215
253
  this.stop();
216
254
  if (this._generated) {
217
255
  const element = this.element;
218
- element && element.remove();
256
+ element?.remove();
219
257
  }
220
258
  else {
221
259
  this._resetOriginalStyle();
@@ -232,12 +270,19 @@ class Canvas {
232
270
  }
233
271
  return cb(ctx);
234
272
  }
235
- drawParticle(particle, delta) {
273
+ drawAsync(cb) {
274
+ const ctx = this._context;
275
+ if (!ctx) {
276
+ return Promise.resolve(undefined);
277
+ }
278
+ return cb(ctx);
279
+ }
280
+ async drawParticle(particle, delta) {
236
281
  if (particle.spawning || particle.destroyed) {
237
282
  return;
238
283
  }
239
- const radius = particle.getRadius();
240
- if (radius <= 0) {
284
+ const radius = particle.getRadius(), minimumSize = 0;
285
+ if (radius <= minimumSize) {
241
286
  return;
242
287
  }
243
288
  const pfColor = particle.getFillColor(), psColor = particle.getStrokeColor() ?? pfColor;
@@ -251,13 +296,13 @@ class Canvas {
251
296
  if (!fColor && !sColor) {
252
297
  return;
253
298
  }
254
- this.draw((ctx) => {
255
- const container = this.container, options = container.actualOptions, zIndexOptions = particle.options.zIndex, zOpacityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.opacityRate, opacity = particle.bubble.opacity ?? particle.opacity?.value ?? 1, strokeOpacity = particle.strokeOpacity ?? opacity, zOpacity = opacity * zOpacityFactor, zStrokeOpacity = strokeOpacity * zOpacityFactor, transform = {}, colorStyles = {
299
+ await this.drawAsync(async (ctx) => {
300
+ const container = this.container, options = container.actualOptions, zIndexOptions = particle.options.zIndex, zIndexFactorOffset = 1, zIndexFactor = zIndexFactorOffset - particle.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, defaultOpacity = 1, opacity = particle.bubble.opacity ?? particle.opacity?.value ?? defaultOpacity, strokeOpacity = particle.strokeOpacity ?? opacity, zOpacity = opacity * zOpacityFactor, zStrokeOpacity = strokeOpacity * zOpacityFactor, transform = {}, colorStyles = {
256
301
  fill: fColor ? (0, ColorUtils_js_1.getStyleFromHsl)(fColor, zOpacity) : undefined,
257
302
  };
258
303
  colorStyles.stroke = sColor ? (0, ColorUtils_js_1.getStyleFromHsl)(sColor, zStrokeOpacity) : colorStyles.fill;
259
304
  this._applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform);
260
- (0, CanvasUtils_js_1.drawParticle)({
305
+ await (0, CanvasUtils_js_1.drawParticle)({
261
306
  container,
262
307
  context: ctx,
263
308
  particle,
@@ -265,7 +310,7 @@ class Canvas {
265
310
  colorStyles,
266
311
  backgroundMask: options.backgroundMask.enable,
267
312
  composite: options.backgroundMask.composite,
268
- radius: radius * (1 - particle.zIndexFactor) ** zIndexOptions.sizeRate,
313
+ radius: radius * zIndexFactor ** zIndexOptions.sizeRate,
269
314
  opacity: zOpacity,
270
315
  shadow: particle.options.shadow,
271
316
  transform,
@@ -273,11 +318,11 @@ class Canvas {
273
318
  this._applyPostDrawUpdaters(particle);
274
319
  });
275
320
  }
276
- drawParticlePlugin(plugin, particle, delta) {
277
- this.draw((ctx) => (0, CanvasUtils_js_1.drawParticlePlugin)(ctx, plugin, particle, delta));
321
+ async drawParticlePlugin(plugin, particle, delta) {
322
+ await this.drawAsync((ctx) => (0, CanvasUtils_js_1.drawParticlePlugin)(ctx, plugin, particle, delta));
278
323
  }
279
- drawPlugin(plugin, delta) {
280
- this.draw((ctx) => (0, CanvasUtils_js_1.drawPlugin)(ctx, plugin, delta));
324
+ async drawPlugin(plugin, delta) {
325
+ await this.drawAsync((ctx) => (0, CanvasUtils_js_1.drawPlugin)(ctx, plugin, delta));
281
326
  }
282
327
  async init() {
283
328
  this._safeMutationObserver((obs) => obs.disconnect());
@@ -290,7 +335,7 @@ class Canvas {
290
335
  });
291
336
  this.resize();
292
337
  this._initStyle();
293
- this._initCover();
338
+ await this._initCover();
294
339
  try {
295
340
  await this._initTrail();
296
341
  }
@@ -335,7 +380,7 @@ class Canvas {
335
380
  if (plugin.resize) {
336
381
  this._resizePlugins.push(plugin);
337
382
  }
338
- if (plugin.particleFillColor || plugin.particleStrokeColor) {
383
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
339
384
  this._colorPlugins.push(plugin);
340
385
  }
341
386
  }
@@ -347,7 +392,7 @@ class Canvas {
347
392
  if (updater.afterDraw) {
348
393
  this._postDrawUpdaters.push(updater);
349
394
  }
350
- if (updater.getColorStyles || updater.getTransformValues || updater.beforeDraw) {
395
+ if (updater.getColorStyles ?? updater.getTransformValues ?? updater.beforeDraw) {
351
396
  this._preDrawUpdaters.push(updater);
352
397
  }
353
398
  }
@@ -380,7 +425,15 @@ class Canvas {
380
425
  this.draw((ctx) => {
381
426
  if (options.backgroundMask.enable && options.backgroundMask.cover) {
382
427
  (0, CanvasUtils_js_1.clear)(ctx, this.size);
383
- this._paintBase(this._coverColorStyle);
428
+ if (this._coverImage) {
429
+ this._paintImage(this._coverImage.image, this._coverImage.opacity);
430
+ }
431
+ else if (this._coverColorStyle) {
432
+ this._paintBase(this._coverColorStyle);
433
+ }
434
+ else {
435
+ this._paintBase();
436
+ }
384
437
  }
385
438
  else {
386
439
  this._paintBase();
@@ -422,7 +475,7 @@ class Canvas {
422
475
  return;
423
476
  }
424
477
  const container = this.container, needsRefresh = container.updateActualOptions();
425
- container.particles.setDensity();
478
+ await container.particles.setDensity();
426
479
  this._applyResizePlugins();
427
480
  if (needsRefresh) {
428
481
  await container.refresh();