tsparticles 3.0.0-beta.2 → 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.
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v3.0.0-beta.2
7
+ * v3.0.0-beta.4
8
8
  */
9
9
  (function webpackUniversalModuleDefinition(root, factory) {
10
10
  if(typeof exports === 'object' && typeof module === 'object')
@@ -97,6 +97,7 @@ __webpack_require__.d(__webpack_exports__, {
97
97
  ParticlesDensity: () => (/* reexport */ ParticlesDensity),
98
98
  ParticlesInteractorBase: () => (/* reexport */ ParticlesInteractorBase),
99
99
  ParticlesNumber: () => (/* reexport */ ParticlesNumber),
100
+ ParticlesNumberLimit: () => (/* reexport */ ParticlesNumberLimit),
100
101
  ParticlesOptions: () => (/* reexport */ ParticlesOptions),
101
102
  Point: () => (/* reexport */ Point),
102
103
  Range: () => (/* reexport */ Range),
@@ -140,13 +141,13 @@ __webpack_require__.d(__webpack_exports__, {
140
141
  deepExtend: () => (/* reexport */ deepExtend),
141
142
  divMode: () => (/* reexport */ divMode),
142
143
  divModeExecute: () => (/* reexport */ divModeExecute),
144
+ drawEffect: () => (/* reexport */ drawEffect),
143
145
  drawLine: () => (/* reexport */ drawLine),
144
146
  drawParticle: () => (/* reexport */ drawParticle),
145
147
  drawParticlePlugin: () => (/* reexport */ drawParticlePlugin),
146
148
  drawPlugin: () => (/* reexport */ drawPlugin),
147
149
  drawShape: () => (/* reexport */ drawShape),
148
- drawShapeAfterEffect: () => (/* reexport */ drawShapeAfterEffect),
149
- drawTriangle: () => (/* reexport */ drawTriangle),
150
+ drawShapeAfterDraw: () => (/* reexport */ drawShapeAfterDraw),
150
151
  errorPrefix: () => (/* reexport */ errorPrefix),
151
152
  executeOnSingleOrMultiple: () => (/* reexport */ executeOnSingleOrMultiple),
152
153
  findItemFromSingleOrMultiple: () => (/* reexport */ findItemFromSingleOrMultiple),
@@ -170,7 +171,6 @@ __webpack_require__.d(__webpack_exports__, {
170
171
  getSize: () => (/* reexport */ getSize),
171
172
  getStyleFromHsl: () => (/* reexport */ getStyleFromHsl),
172
173
  getStyleFromRgb: () => (/* reexport */ getStyleFromRgb),
173
- getValue: () => (/* reexport */ getValue),
174
174
  hasMatchMedia: () => (/* reexport */ hasMatchMedia),
175
175
  hslToRgb: () => (/* reexport */ hslToRgb),
176
176
  hslaToRgba: () => (/* reexport */ hslaToRgba),
@@ -207,6 +207,7 @@ __webpack_require__.d(__webpack_exports__, {
207
207
  rectBounce: () => (/* reexport */ rectBounce),
208
208
  resizeEvent: () => (/* reexport */ resizeEvent),
209
209
  rgbToHsl: () => (/* reexport */ rgbToHsl),
210
+ safeIntersectionObserver: () => (/* reexport */ safeIntersectionObserver),
210
211
  safeMatchMedia: () => (/* reexport */ safeMatchMedia),
211
212
  safeMutationObserver: () => (/* reexport */ safeMutationObserver),
212
213
  setLogger: () => (/* reexport */ setLogger),
@@ -410,17 +411,6 @@ function setRangeValue(source, value) {
410
411
  max: Math.max(max, value)
411
412
  } : setRangeValue(min, max);
412
413
  }
413
- function getValue(options) {
414
- const random = options.random,
415
- {
416
- enable,
417
- minimumValue
418
- } = isBoolean(random) ? {
419
- enable: random,
420
- minimumValue: 0
421
- } : random;
422
- return enable ? getRangeValue(setRangeValue(options.value, minimumValue)) : getRangeValue(options.value);
423
- }
424
414
  function getDistances(pointA, pointB) {
425
415
  const dx = pointA.x - pointB.x,
426
416
  dy = pointA.y - pointB.y;
@@ -439,21 +429,21 @@ function getParticleDirectionAngle(direction, position, center) {
439
429
  }
440
430
  switch (direction) {
441
431
  case "top":
442
- return -Math.PI / 2;
432
+ return -Math.PI * 0.5;
443
433
  case "top-right":
444
- return -Math.PI / 4;
434
+ return -Math.PI * 0.25;
445
435
  case "right":
446
436
  return 0;
447
437
  case "bottom-right":
448
- return Math.PI / 4;
438
+ return Math.PI * 0.25;
449
439
  case "bottom":
450
- return Math.PI / 2;
440
+ return Math.PI * 0.5;
451
441
  case "bottom-left":
452
- return 3 * Math.PI / 4;
442
+ return Math.PI * 0.75;
453
443
  case "left":
454
444
  return Math.PI;
455
445
  case "top-left":
456
- return -3 * Math.PI / 4;
446
+ return -Math.PI * 0.75;
457
447
  case "inside":
458
448
  return Math.atan2(center.y - position.y, center.x - position.x);
459
449
  case "outside":
@@ -549,7 +539,7 @@ function rectSideBounce(data) {
549
539
  if (pOtherSide.min < rectOtherSide.min || pOtherSide.min > rectOtherSide.max || pOtherSide.max < rectOtherSide.min || pOtherSide.max > rectOtherSide.max) {
550
540
  return res;
551
541
  }
552
- if (pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) / 2 && velocity > 0 || pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) / 2 && velocity < 0) {
542
+ if (pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) * 0.5 && velocity > 0 || pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) * 0.5 && velocity < 0) {
553
543
  res.velocity = velocity * -factor;
554
544
  res.bounced = true;
555
545
  }
@@ -573,6 +563,12 @@ function safeMatchMedia(query) {
573
563
  }
574
564
  return matchMedia(query);
575
565
  }
566
+ function safeIntersectionObserver(callback) {
567
+ if (isSsr() || typeof IntersectionObserver === "undefined") {
568
+ return;
569
+ }
570
+ return new IntersectionObserver(callback);
571
+ }
576
572
  function safeMutationObserver(callback) {
577
573
  if (isSsr() || typeof MutationObserver === "undefined") {
578
574
  return;
@@ -679,7 +675,7 @@ function circleBounceDataFromParticle(p) {
679
675
  radius: p.getRadius(),
680
676
  mass: p.getMass(),
681
677
  velocity: p.velocity,
682
- factor: Vector.create(getValue(p.options.bounce.horizontal), getValue(p.options.bounce.vertical))
678
+ factor: Vector.create(getRangeValue(p.options.bounce.horizontal.value), getRangeValue(p.options.bounce.vertical.value))
683
679
  };
684
680
  }
685
681
  function circleBounce(p1, p2) {
@@ -713,6 +709,7 @@ function rectBounce(particle, divBounds) {
713
709
  const pPos = particle.getPosition(),
714
710
  size = particle.getRadius(),
715
711
  bounds = calculateBounds(pPos, size),
712
+ bounceOptions = particle.options.bounce,
716
713
  resH = rectSideBounce({
717
714
  pSide: {
718
715
  min: bounds.left,
@@ -731,7 +728,7 @@ function rectBounce(particle, divBounds) {
731
728
  max: divBounds.bottom
732
729
  },
733
730
  velocity: particle.velocity.x,
734
- factor: getValue(particle.options.bounce.horizontal)
731
+ factor: getRangeValue(bounceOptions.horizontal.value)
735
732
  });
736
733
  if (resH.bounced) {
737
734
  if (resH.velocity !== undefined) {
@@ -759,7 +756,7 @@ function rectBounce(particle, divBounds) {
759
756
  max: divBounds.right
760
757
  },
761
758
  velocity: particle.velocity.y,
762
- factor: getValue(particle.options.bounce.vertical)
759
+ factor: getRangeValue(bounceOptions.vertical.value)
763
760
  });
764
761
  if (resV.bounced) {
765
762
  if (resV.velocity !== undefined) {
@@ -886,24 +883,6 @@ const randomColorValue = "random",
886
883
  function addColorManager(manager) {
887
884
  colorManagers.set(manager.key, manager);
888
885
  }
889
- function hue2rgb(p, q, t) {
890
- if (t < 0) {
891
- t += 1;
892
- }
893
- if (t > 1) {
894
- t -= 1;
895
- }
896
- if (t < 1 / 6) {
897
- return p + (q - p) * 6 * t;
898
- }
899
- if (t < 1 / 2) {
900
- return q;
901
- }
902
- if (t < 2 / 3) {
903
- return p + (q - p) * (2 / 3 - t) * 6;
904
- }
905
- return p;
906
- }
907
886
  function stringToRgba(input) {
908
887
  for (const [, manager] of colorManagers) {
909
888
  if (input.startsWith(manager.stringPrefix)) {
@@ -983,7 +962,7 @@ function rgbToHsl(color) {
983
962
  min = Math.min(r1, g1, b1),
984
963
  res = {
985
964
  h: 0,
986
- l: (max + min) / 2,
965
+ l: (max + min) * 0.5,
987
966
  s: 0
988
967
  };
989
968
  if (max !== min) {
@@ -1008,29 +987,48 @@ function stringToRgb(input) {
1008
987
  return stringToRgba(input);
1009
988
  }
1010
989
  function hslToRgb(hsl) {
1011
- const result = {
1012
- b: 0,
1013
- g: 0,
1014
- r: 0
1015
- },
1016
- hslPercent = {
1017
- h: hsl.h / 360,
1018
- l: hsl.l / 100,
1019
- s: hsl.s / 100
990
+ const h = (hsl.h % 360 + 360) % 360,
991
+ s = Math.max(0, Math.min(100, hsl.s)),
992
+ l = Math.max(0, Math.min(100, hsl.l)),
993
+ hNormalized = h / 360,
994
+ sNormalized = s / 100,
995
+ lNormalized = l / 100;
996
+ if (s === 0) {
997
+ const grayscaleValue = Math.round(lNormalized * 255);
998
+ return {
999
+ r: grayscaleValue,
1000
+ g: grayscaleValue,
1001
+ b: grayscaleValue
1020
1002
  };
1021
- if (!hslPercent.s) {
1022
- result.r = result.g = result.b = hslPercent.l;
1023
- } else {
1024
- const q = hslPercent.l < 0.5 ? hslPercent.l * (1 + hslPercent.s) : hslPercent.l + hslPercent.s - hslPercent.l * hslPercent.s,
1025
- p = 2 * hslPercent.l - q;
1026
- result.r = hue2rgb(p, q, hslPercent.h + 1 / 3);
1027
- result.g = hue2rgb(p, q, hslPercent.h);
1028
- result.b = hue2rgb(p, q, hslPercent.h - 1 / 3);
1029
1003
  }
1030
- result.r = Math.floor(result.r * 255);
1031
- result.g = Math.floor(result.g * 255);
1032
- result.b = Math.floor(result.b * 255);
1033
- return result;
1004
+ const channel = (temp1, temp2, temp3) => {
1005
+ if (temp3 < 0) {
1006
+ temp3 += 1;
1007
+ }
1008
+ if (temp3 > 1) {
1009
+ temp3 -= 1;
1010
+ }
1011
+ if (temp3 * 6 < 1) {
1012
+ return temp1 + (temp2 - temp1) * 6 * temp3;
1013
+ }
1014
+ if (temp3 * 2 < 1) {
1015
+ return temp2;
1016
+ }
1017
+ if (temp3 * 3 < 2) {
1018
+ return temp1 + (temp2 - temp1) * (2 / 3 - temp3) * 6;
1019
+ }
1020
+ return temp1;
1021
+ },
1022
+ temp1 = lNormalized < 0.5 ? lNormalized * (1 + sNormalized) : lNormalized + sNormalized - lNormalized * sNormalized,
1023
+ temp2 = 2 * lNormalized - temp1,
1024
+ red = Math.min(255, 255 * channel(temp2, temp1, hNormalized + 1 / 3)),
1025
+ green = Math.min(255, 255 * channel(temp2, temp1, hNormalized)),
1026
+ blue = Math.min(255, 255 * channel(temp2, temp1, hNormalized - 1 / 3));
1027
+ return {
1028
+ r: Math.round(red),
1029
+ g: Math.round(green),
1030
+ b: Math.round(blue)
1031
+ };
1034
1032
  }
1035
1033
  function hslaToRgba(hsla) {
1036
1034
  const rgbResult = hslToRgb(hsla);
@@ -1164,13 +1162,6 @@ function drawLine(context, begin, end) {
1164
1162
  context.lineTo(end.x, end.y);
1165
1163
  context.closePath();
1166
1164
  }
1167
- function drawTriangle(context, p1, p2, p3) {
1168
- context.beginPath();
1169
- context.moveTo(p1.x, p1.y);
1170
- context.lineTo(p2.x, p2.y);
1171
- context.lineTo(p3.x, p3.y);
1172
- context.closePath();
1173
- }
1174
1165
  function paintBase(context, dimension, baseColor) {
1175
1166
  context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1176
1167
  context.fillRect(0, 0, dimension.width, dimension.height);
@@ -1213,7 +1204,6 @@ function drawParticle(data) {
1213
1204
  d: rotateData.cos * (transform.d ?? 1)
1214
1205
  };
1215
1206
  context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1216
- context.beginPath();
1217
1207
  if (backgroundMask) {
1218
1208
  context.globalCompositeOperation = composite;
1219
1209
  }
@@ -1232,39 +1222,104 @@ function drawParticle(data) {
1232
1222
  if (colorStyles.stroke) {
1233
1223
  context.strokeStyle = colorStyles.stroke;
1234
1224
  }
1235
- drawShape(container, context, particle, radius, opacity, delta);
1225
+ const drawData = {
1226
+ container,
1227
+ context,
1228
+ particle,
1229
+ radius,
1230
+ opacity,
1231
+ delta
1232
+ };
1233
+ context.beginPath();
1234
+ drawShape(drawData);
1235
+ if (particle.shapeClose) {
1236
+ context.closePath();
1237
+ }
1236
1238
  if (strokeWidth > 0) {
1237
1239
  context.stroke();
1238
1240
  }
1239
- if (particle.close) {
1240
- context.closePath();
1241
- }
1242
- if (particle.fill) {
1241
+ if (particle.shapeFill) {
1243
1242
  context.fill();
1244
1243
  }
1245
- drawShapeAfterEffect(container, context, particle, radius, opacity, delta);
1244
+ drawShapeAfterDraw(drawData);
1245
+ drawEffect(drawData);
1246
1246
  context.globalCompositeOperation = "source-over";
1247
1247
  context.setTransform(1, 0, 0, 1, 0, 0);
1248
1248
  }
1249
- function drawShape(container, context, particle, radius, opacity, delta) {
1249
+ function drawEffect(data) {
1250
+ const {
1251
+ container,
1252
+ context,
1253
+ particle,
1254
+ radius,
1255
+ opacity,
1256
+ delta
1257
+ } = data;
1258
+ if (!particle.effect) {
1259
+ return;
1260
+ }
1261
+ const drawer = container.effectDrawers.get(particle.effect);
1262
+ if (!drawer) {
1263
+ return;
1264
+ }
1265
+ drawer.draw({
1266
+ context,
1267
+ particle,
1268
+ radius,
1269
+ opacity,
1270
+ delta,
1271
+ pixelRatio: container.retina.pixelRatio
1272
+ });
1273
+ }
1274
+ function drawShape(data) {
1275
+ const {
1276
+ container,
1277
+ context,
1278
+ particle,
1279
+ radius,
1280
+ opacity,
1281
+ delta
1282
+ } = data;
1250
1283
  if (!particle.shape) {
1251
1284
  return;
1252
1285
  }
1253
- const drawer = container.drawers.get(particle.shape);
1286
+ const drawer = container.shapeDrawers.get(particle.shape);
1254
1287
  if (!drawer) {
1255
1288
  return;
1256
1289
  }
1257
- drawer.draw(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1290
+ drawer.draw({
1291
+ context,
1292
+ particle,
1293
+ radius,
1294
+ opacity,
1295
+ delta,
1296
+ pixelRatio: container.retina.pixelRatio
1297
+ });
1258
1298
  }
1259
- function drawShapeAfterEffect(container, context, particle, radius, opacity, delta) {
1299
+ function drawShapeAfterDraw(data) {
1300
+ const {
1301
+ container,
1302
+ context,
1303
+ particle,
1304
+ radius,
1305
+ opacity,
1306
+ delta
1307
+ } = data;
1260
1308
  if (!particle.shape) {
1261
1309
  return;
1262
1310
  }
1263
- const drawer = container.drawers.get(particle.shape);
1264
- if (!drawer || !drawer.afterEffect) {
1311
+ const drawer = container.shapeDrawers.get(particle.shape);
1312
+ if (!drawer || !drawer.afterDraw) {
1265
1313
  return;
1266
1314
  }
1267
- drawer.afterEffect(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1315
+ drawer.afterDraw({
1316
+ context,
1317
+ particle,
1318
+ radius,
1319
+ opacity,
1320
+ delta,
1321
+ pixelRatio: container.retina.pixelRatio
1322
+ });
1268
1323
  }
1269
1324
  function drawPlugin(context, plugin, delta) {
1270
1325
  if (!plugin.draw) {
@@ -1711,10 +1766,10 @@ class Canvas {
1711
1766
  this.element.width = size.width = this.element.offsetWidth * pxRatio;
1712
1767
  this.element.height = size.height = this.element.offsetHeight * pxRatio;
1713
1768
  if (this.container.started) {
1714
- this.resizeFactor = {
1769
+ container.particles.setResizeFactor({
1715
1770
  width: size.width / oldSize.width,
1716
1771
  height: size.height / oldSize.height
1717
- };
1772
+ });
1718
1773
  }
1719
1774
  return true;
1720
1775
  }
@@ -2184,10 +2239,10 @@ class BackgroundMask {
2184
2239
  this.composite = data.composite;
2185
2240
  }
2186
2241
  if (data.cover !== undefined) {
2187
- const cover = data.cover;
2188
- const color = isString(data.cover) ? {
2189
- color: data.cover
2190
- } : data.cover;
2242
+ const cover = data.cover,
2243
+ color = isString(data.cover) ? {
2244
+ color: data.cover
2245
+ } : data.cover;
2191
2246
  this.cover.load(cover.color !== undefined ? cover : {
2192
2247
  color: color
2193
2248
  });
@@ -2489,17 +2544,16 @@ class Theme {
2489
2544
  }
2490
2545
  }
2491
2546
  }
2492
- ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/ColorAnimation.js
2547
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/AnimationOptions.js
2493
2548
 
2494
- class ColorAnimation {
2549
+ class AnimationOptions {
2495
2550
  constructor() {
2496
2551
  this.count = 0;
2497
2552
  this.enable = false;
2498
- this.offset = 0;
2499
2553
  this.speed = 1;
2500
- this.delay = 0;
2501
2554
  this.decay = 0;
2502
- this.sync = true;
2555
+ this.delay = 0;
2556
+ this.sync = false;
2503
2557
  }
2504
2558
  load(data) {
2505
2559
  if (!data) {
@@ -2511,9 +2565,6 @@ class ColorAnimation {
2511
2565
  if (data.enable !== undefined) {
2512
2566
  this.enable = data.enable;
2513
2567
  }
2514
- if (data.offset !== undefined) {
2515
- this.offset = setRangeValue(data.offset);
2516
- }
2517
2568
  if (data.speed !== undefined) {
2518
2569
  this.speed = setRangeValue(data.speed);
2519
2570
  }
@@ -2528,6 +2579,44 @@ class ColorAnimation {
2528
2579
  }
2529
2580
  }
2530
2581
  }
2582
+ class RangedAnimationOptions extends AnimationOptions {
2583
+ constructor() {
2584
+ super();
2585
+ this.mode = "auto";
2586
+ this.startValue = "random";
2587
+ }
2588
+ load(data) {
2589
+ super.load(data);
2590
+ if (!data) {
2591
+ return;
2592
+ }
2593
+ if (data.mode !== undefined) {
2594
+ this.mode = data.mode;
2595
+ }
2596
+ if (data.startValue !== undefined) {
2597
+ this.startValue = data.startValue;
2598
+ }
2599
+ }
2600
+ }
2601
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/ColorAnimation.js
2602
+
2603
+
2604
+ class ColorAnimation extends AnimationOptions {
2605
+ constructor() {
2606
+ super();
2607
+ this.offset = 0;
2608
+ this.sync = true;
2609
+ }
2610
+ load(data) {
2611
+ super.load(data);
2612
+ if (!data) {
2613
+ return;
2614
+ }
2615
+ if (data.offset !== undefined) {
2616
+ this.offset = setRangeValue(data.offset);
2617
+ }
2618
+ }
2619
+ }
2531
2620
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/HslAnimation.js
2532
2621
 
2533
2622
  class HslAnimation {
@@ -2615,99 +2704,19 @@ class CollisionsOverlap {
2615
2704
  }
2616
2705
  }
2617
2706
  }
2618
- ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/AnimationOptions.js
2619
-
2620
- class AnimationOptions {
2621
- constructor() {
2622
- this.count = 0;
2623
- this.enable = false;
2624
- this.speed = 1;
2625
- this.decay = 0;
2626
- this.delay = 0;
2627
- this.sync = false;
2628
- }
2629
- load(data) {
2630
- if (!data) {
2631
- return;
2632
- }
2633
- if (data.count !== undefined) {
2634
- this.count = setRangeValue(data.count);
2635
- }
2636
- if (data.enable !== undefined) {
2637
- this.enable = data.enable;
2638
- }
2639
- if (data.speed !== undefined) {
2640
- this.speed = setRangeValue(data.speed);
2641
- }
2642
- if (data.decay !== undefined) {
2643
- this.decay = setRangeValue(data.decay);
2644
- }
2645
- if (data.delay !== undefined) {
2646
- this.delay = setRangeValue(data.delay);
2647
- }
2648
- if (data.sync !== undefined) {
2649
- this.sync = data.sync;
2650
- }
2651
- }
2652
- }
2653
- class RangedAnimationOptions extends AnimationOptions {
2654
- constructor() {
2655
- super();
2656
- this.mode = "auto";
2657
- this.startValue = "random";
2658
- }
2659
- load(data) {
2660
- super.load(data);
2661
- if (!data) {
2662
- return;
2663
- }
2664
- if (data.mode !== undefined) {
2665
- this.mode = data.mode;
2666
- }
2667
- if (data.startValue !== undefined) {
2668
- this.startValue = data.startValue;
2669
- }
2670
- }
2671
- }
2672
- ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Random.js
2673
- class Random {
2674
- constructor() {
2675
- this.enable = false;
2676
- this.minimumValue = 0;
2677
- }
2678
- load(data) {
2679
- if (!data) {
2680
- return;
2681
- }
2682
- if (data.enable !== undefined) {
2683
- this.enable = data.enable;
2684
- }
2685
- if (data.minimumValue !== undefined) {
2686
- this.minimumValue = data.minimumValue;
2687
- }
2688
- }
2689
- }
2690
2707
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/ValueWithRandom.js
2691
2708
 
2692
2709
 
2693
-
2694
-
2695
2710
  class ValueWithRandom {
2696
2711
  constructor() {
2697
- this.random = new Random();
2698
2712
  this.value = 0;
2699
2713
  }
2700
2714
  load(data) {
2701
2715
  if (!data) {
2702
2716
  return;
2703
2717
  }
2704
- if (isBoolean(data.random)) {
2705
- this.random.enable = data.random;
2706
- } else {
2707
- this.random.load(data.random);
2708
- }
2709
2718
  if (data.value !== undefined) {
2710
- this.value = setRangeValue(data.value, this.random.enable ? this.random.minimumValue : undefined);
2719
+ this.value = setRangeValue(data.value);
2711
2720
  }
2712
2721
  }
2713
2722
  }
@@ -2741,7 +2750,6 @@ class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
2741
2750
  class ParticlesBounceFactor extends ValueWithRandom {
2742
2751
  constructor() {
2743
2752
  super();
2744
- this.random.minimumValue = 0.1;
2745
2753
  this.value = 1;
2746
2754
  }
2747
2755
  }
@@ -2792,6 +2800,39 @@ class Collisions {
2792
2800
  this.overlap.load(data.overlap);
2793
2801
  }
2794
2802
  }
2803
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Effect/Effect.js
2804
+
2805
+ class Effect {
2806
+ constructor() {
2807
+ this.close = true;
2808
+ this.fill = true;
2809
+ this.options = {};
2810
+ this.type = [];
2811
+ }
2812
+ load(data) {
2813
+ if (!data) {
2814
+ return;
2815
+ }
2816
+ const options = data.options;
2817
+ if (options !== undefined) {
2818
+ for (const effect in options) {
2819
+ const item = options[effect];
2820
+ if (item) {
2821
+ this.options[effect] = deepExtend(this.options[effect] ?? {}, item);
2822
+ }
2823
+ }
2824
+ }
2825
+ if (data.close !== undefined) {
2826
+ this.close = data.close;
2827
+ }
2828
+ if (data.fill !== undefined) {
2829
+ this.fill = data.fill;
2830
+ }
2831
+ if (data.type !== undefined) {
2832
+ this.type = data.type;
2833
+ }
2834
+ }
2835
+ }
2795
2836
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Move/MoveAngle.js
2796
2837
 
2797
2838
  class MoveAngle {
@@ -3120,11 +3161,10 @@ class OpacityAnimation extends RangedAnimationOptions {
3120
3161
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Opacity/Opacity.js
3121
3162
 
3122
3163
 
3123
- class Opacity extends ValueWithRandom {
3164
+ class Opacity extends RangedAnimationValueWithRandom {
3124
3165
  constructor() {
3125
3166
  super();
3126
3167
  this.animation = new OpacityAnimation();
3127
- this.random.minimumValue = 0.1;
3128
3168
  this.value = 1;
3129
3169
  }
3130
3170
  load(data) {
@@ -3162,12 +3202,31 @@ class ParticlesDensity {
3162
3202
  }
3163
3203
  }
3164
3204
  }
3205
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js
3206
+ class ParticlesNumberLimit {
3207
+ constructor() {
3208
+ this.mode = "delete";
3209
+ this.value = 0;
3210
+ }
3211
+ load(data) {
3212
+ if (!data) {
3213
+ return;
3214
+ }
3215
+ if (data.mode !== undefined) {
3216
+ this.mode = data.mode;
3217
+ }
3218
+ if (data.value !== undefined) {
3219
+ this.value = data.value;
3220
+ }
3221
+ }
3222
+ }
3165
3223
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Number/ParticlesNumber.js
3166
3224
 
3225
+
3167
3226
  class ParticlesNumber {
3168
3227
  constructor() {
3169
3228
  this.density = new ParticlesDensity();
3170
- this.limit = 0;
3229
+ this.limit = new ParticlesNumberLimit();
3171
3230
  this.value = 0;
3172
3231
  }
3173
3232
  load(data) {
@@ -3175,10 +3234,7 @@ class ParticlesNumber {
3175
3234
  return;
3176
3235
  }
3177
3236
  this.density.load(data.density);
3178
- const limit = data.limit;
3179
- if (limit !== undefined) {
3180
- this.limit = limit;
3181
- }
3237
+ this.limit.load(data.limit);
3182
3238
  if (data.value !== undefined) {
3183
3239
  this.value = data.value;
3184
3240
  }
@@ -3273,11 +3329,10 @@ class SizeAnimation extends RangedAnimationOptions {
3273
3329
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Size/Size.js
3274
3330
 
3275
3331
 
3276
- class Size extends ValueWithRandom {
3332
+ class Size extends RangedAnimationValueWithRandom {
3277
3333
  constructor() {
3278
3334
  super();
3279
3335
  this.animation = new SizeAnimation();
3280
- this.random.minimumValue = 1;
3281
3336
  this.value = 3;
3282
3337
  }
3283
3338
  load(data) {
@@ -3351,6 +3406,7 @@ class ZIndex extends ValueWithRandom {
3351
3406
 
3352
3407
 
3353
3408
 
3409
+
3354
3410
  class ParticlesOptions {
3355
3411
  constructor(engine, container) {
3356
3412
  this._engine = engine;
@@ -3359,6 +3415,7 @@ class ParticlesOptions {
3359
3415
  this.collisions = new Collisions();
3360
3416
  this.color = new AnimatableColor();
3361
3417
  this.color.value = "#fff";
3418
+ this.effect = new Effect();
3362
3419
  this.groups = {};
3363
3420
  this.move = new Move();
3364
3421
  this.number = new ParticlesNumber();
@@ -3376,6 +3433,7 @@ class ParticlesOptions {
3376
3433
  }
3377
3434
  this.bounce.load(data.bounce);
3378
3435
  this.color.load(AnimatableColor.create(this.color, data.color));
3436
+ this.effect.load(data.effect);
3379
3437
  if (data.groups !== undefined) {
3380
3438
  for (const group in data.groups) {
3381
3439
  const item = data.groups[group];
@@ -3648,7 +3706,27 @@ class InteractionManager {
3648
3706
 
3649
3707
 
3650
3708
 
3651
- const fixOutMode = data => {
3709
+ function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
3710
+ const effectData = effectOptions.options[effect];
3711
+ if (!effectData) {
3712
+ return;
3713
+ }
3714
+ return deepExtend({
3715
+ close: effectOptions.close,
3716
+ fill: effectOptions.fill
3717
+ }, itemFromSingleOrMultiple(effectData, id, reduceDuplicates));
3718
+ }
3719
+ function loadShapeData(shape, shapeOptions, id, reduceDuplicates) {
3720
+ const shapeData = shapeOptions.options[shape];
3721
+ if (!shapeData) {
3722
+ return;
3723
+ }
3724
+ return deepExtend({
3725
+ close: shapeOptions.close,
3726
+ fill: shapeOptions.fill
3727
+ }, itemFromSingleOrMultiple(shapeData, id, reduceDuplicates));
3728
+ }
3729
+ function fixOutMode(data) {
3652
3730
  if (!isInArray(data.outMode, data.checkModes)) {
3653
3731
  return;
3654
3732
  }
@@ -3658,7 +3736,7 @@ const fixOutMode = data => {
3658
3736
  } else if (data.coord < diameter) {
3659
3737
  data.setCb(data.radius);
3660
3738
  }
3661
- };
3739
+ }
3662
3740
  class Particle {
3663
3741
  constructor(engine, id, container, position, overrideOptions, group) {
3664
3742
  this.container = container;
@@ -3716,8 +3794,8 @@ class Particle {
3716
3794
  const rad = Math.PI / 180 * getRangeValue(moveOptions.angle.value),
3717
3795
  radOffset = Math.PI / 180 * getRangeValue(moveOptions.angle.offset),
3718
3796
  range = {
3719
- left: radOffset - rad / 2,
3720
- right: radOffset + rad / 2
3797
+ left: radOffset - rad * 0.5,
3798
+ right: radOffset + rad * 0.5
3721
3799
  };
3722
3800
  if (!moveOptions.straight) {
3723
3801
  res.angle += randomInRange(setRangeValue(range.left, range.right));
@@ -3748,7 +3826,7 @@ class Particle {
3748
3826
  return color;
3749
3827
  }
3750
3828
  const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1,
3751
- backSum = this.roll.horizontal ? Math.PI / 2 : 0,
3829
+ backSum = this.roll.horizontal ? Math.PI * 0.5 : 0,
3752
3830
  rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
3753
3831
  if (!rolled) {
3754
3832
  return color;
@@ -3783,16 +3861,6 @@ class Particle {
3783
3861
  }
3784
3862
  this.offset = Vector.origin;
3785
3863
  };
3786
- this._loadShapeData = (shapeOptions, reduceDuplicates) => {
3787
- const shapeData = shapeOptions.options[this.shape];
3788
- if (!shapeData) {
3789
- return;
3790
- }
3791
- return deepExtend({
3792
- close: shapeOptions.close,
3793
- fill: shapeOptions.fill
3794
- }, itemFromSingleOrMultiple(shapeData, this.id, reduceDuplicates));
3795
- };
3796
3864
  this._engine = engine;
3797
3865
  this.init(id, position, overrideOptions, group);
3798
3866
  }
@@ -3806,18 +3874,12 @@ class Particle {
3806
3874
  const container = this.container,
3807
3875
  pathGenerator = this.pathGenerator;
3808
3876
  for (const [, plugin] of container.plugins) {
3809
- if (plugin.particleDestroyed) {
3810
- plugin.particleDestroyed(this, override);
3811
- }
3877
+ plugin.particleDestroyed && plugin.particleDestroyed(this, override);
3812
3878
  }
3813
3879
  for (const updater of container.particles.updaters) {
3814
- if (updater.particleDestroyed) {
3815
- updater.particleDestroyed(this, override);
3816
- }
3817
- }
3818
- if (pathGenerator) {
3819
- pathGenerator.reset(this);
3880
+ updater.particleDestroyed && updater.particleDestroyed(this, override);
3820
3881
  }
3882
+ pathGenerator && pathGenerator.reset(this);
3821
3883
  }
3822
3884
  draw(delta) {
3823
3885
  const container = this.container,
@@ -3831,7 +3893,7 @@ class Particle {
3831
3893
  return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.color));
3832
3894
  }
3833
3895
  getMass() {
3834
- return this.getRadius() ** 2 * Math.PI / 2;
3896
+ return this.getRadius() ** 2 * Math.PI * 0.5;
3835
3897
  }
3836
3898
  getPosition() {
3837
3899
  return {
@@ -3851,9 +3913,11 @@ class Particle {
3851
3913
  engine = this._engine;
3852
3914
  this.id = id;
3853
3915
  this.group = group;
3854
- this.fill = true;
3916
+ this.effectClose = true;
3917
+ this.effectFill = true;
3918
+ this.shapeClose = true;
3919
+ this.shapeFill = true;
3855
3920
  this.pathRotation = false;
3856
- this.close = true;
3857
3921
  this.lastPathTime = 0;
3858
3922
  this.destroyed = false;
3859
3923
  this.unbreakable = false;
@@ -3867,22 +3931,40 @@ class Particle {
3867
3931
  const pxRatio = container.retina.pixelRatio,
3868
3932
  mainOptions = container.actualOptions,
3869
3933
  particlesOptions = loadParticlesOptions(this._engine, container, mainOptions.particles),
3934
+ effectType = particlesOptions.effect.type,
3870
3935
  shapeType = particlesOptions.shape.type,
3871
3936
  {
3872
3937
  reduceDuplicates
3873
3938
  } = particlesOptions;
3939
+ this.effect = itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
3874
3940
  this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
3875
- const shapeOptions = particlesOptions.shape;
3876
- if (overrideOptions && overrideOptions.shape && overrideOptions.shape.type) {
3877
- const overrideShapeType = overrideOptions.shape.type,
3878
- shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3879
- if (shape) {
3880
- this.shape = shape;
3881
- shapeOptions.load(overrideOptions.shape);
3941
+ const effectOptions = particlesOptions.effect,
3942
+ shapeOptions = particlesOptions.shape;
3943
+ if (overrideOptions) {
3944
+ if (overrideOptions.effect && overrideOptions.effect.type) {
3945
+ const overrideEffectType = overrideOptions.effect.type,
3946
+ effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
3947
+ if (effect) {
3948
+ this.effect = effect;
3949
+ effectOptions.load(overrideOptions.effect);
3950
+ }
3951
+ }
3952
+ if (overrideOptions.shape && overrideOptions.shape.type) {
3953
+ const overrideShapeType = overrideOptions.shape.type,
3954
+ shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3955
+ if (shape) {
3956
+ this.shape = shape;
3957
+ shapeOptions.load(overrideOptions.shape);
3958
+ }
3882
3959
  }
3883
3960
  }
3884
- this.shapeData = this._loadShapeData(shapeOptions, reduceDuplicates);
3961
+ this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
3962
+ this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
3885
3963
  particlesOptions.load(overrideOptions);
3964
+ const effectData = this.effectData;
3965
+ if (effectData) {
3966
+ particlesOptions.load(effectData.particles);
3967
+ }
3886
3968
  const shapeData = this.shapeData;
3887
3969
  if (shapeData) {
3888
3970
  particlesOptions.load(shapeData.particles);
@@ -3891,11 +3973,13 @@ class Particle {
3891
3973
  interactivity.load(container.actualOptions.interactivity);
3892
3974
  interactivity.load(particlesOptions.interactivity);
3893
3975
  this.interactivity = interactivity;
3894
- this.fill = shapeData?.fill ?? particlesOptions.shape.fill;
3895
- this.close = shapeData?.close ?? particlesOptions.shape.close;
3976
+ this.effectFill = effectData?.fill ?? particlesOptions.effect.fill;
3977
+ this.effectClose = effectData?.close ?? particlesOptions.effect.close;
3978
+ this.shapeFill = shapeData?.fill ?? particlesOptions.shape.fill;
3979
+ this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
3896
3980
  this.options = particlesOptions;
3897
3981
  const pathOptions = this.options.move.path;
3898
- this.pathDelay = getValue(pathOptions.delay) * 1000;
3982
+ this.pathDelay = getRangeValue(pathOptions.delay.value) * 1000;
3899
3983
  if (pathOptions.generator) {
3900
3984
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
3901
3985
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
@@ -3916,34 +4000,46 @@ class Particle {
3916
4000
  this.velocity = this.initialVelocity.copy();
3917
4001
  this.moveDecay = 1 - getRangeValue(this.options.move.decay);
3918
4002
  const particles = container.particles;
3919
- particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
3920
- particles.lastZIndex = this.position.z;
4003
+ particles.setLastZIndex(this.position.z);
3921
4004
  this.zIndexFactor = this.position.z / container.zLayers;
3922
4005
  this.sides = 24;
3923
- let drawer = container.drawers.get(this.shape);
3924
- if (!drawer) {
3925
- drawer = this._engine.getShapeDrawer(this.shape);
3926
- if (drawer) {
3927
- container.drawers.set(this.shape, drawer);
4006
+ let effectDrawer = container.effectDrawers.get(this.effect);
4007
+ if (!effectDrawer) {
4008
+ effectDrawer = this._engine.getEffectDrawer(this.effect);
4009
+ if (effectDrawer) {
4010
+ container.effectDrawers.set(this.effect, effectDrawer);
4011
+ }
4012
+ }
4013
+ if (effectDrawer && effectDrawer.loadEffect) {
4014
+ effectDrawer.loadEffect(this);
4015
+ }
4016
+ let shapeDrawer = container.shapeDrawers.get(this.shape);
4017
+ if (!shapeDrawer) {
4018
+ shapeDrawer = this._engine.getShapeDrawer(this.shape);
4019
+ if (shapeDrawer) {
4020
+ container.shapeDrawers.set(this.shape, shapeDrawer);
3928
4021
  }
3929
4022
  }
3930
- if (drawer && drawer.loadShape) {
3931
- drawer.loadShape(this);
4023
+ if (shapeDrawer && shapeDrawer.loadShape) {
4024
+ shapeDrawer.loadShape(this);
3932
4025
  }
3933
- const sideCountFunc = drawer?.getSidesCount;
4026
+ const sideCountFunc = shapeDrawer?.getSidesCount;
3934
4027
  if (sideCountFunc) {
3935
4028
  this.sides = sideCountFunc(this);
3936
4029
  }
3937
4030
  this.spawning = false;
3938
4031
  this.shadowColor = rangeColorToRgb(this.options.shadow.color);
3939
- for (const updater of container.particles.updaters) {
4032
+ for (const updater of particles.updaters) {
3940
4033
  updater.init(this);
3941
4034
  }
3942
- for (const mover of container.particles.movers) {
4035
+ for (const mover of particles.movers) {
3943
4036
  mover.init && mover.init(this);
3944
4037
  }
3945
- if (drawer && drawer.particleInit) {
3946
- drawer.particleInit(container, this);
4038
+ if (effectDrawer && effectDrawer.particleInit) {
4039
+ effectDrawer.particleInit(container, this);
4040
+ }
4041
+ if (shapeDrawer && shapeDrawer.particleInit) {
4042
+ shapeDrawer.particleInit(container, this);
3947
4043
  }
3948
4044
  for (const [, plugin] of container.plugins) {
3949
4045
  plugin.particleCreated && plugin.particleCreated(this);
@@ -4070,7 +4166,7 @@ class QuadTree {
4070
4166
  capacity
4071
4167
  } = this;
4072
4168
  for (let i = 0; i < 4; i++) {
4073
- this._subs.push(new QuadTree(new Rectangle(x + width / 2 * (i % 2), y + height / 2 * (Math.round(i / 2) - i % 2), width / 2, height / 2), capacity));
4169
+ this._subs.push(new QuadTree(new Rectangle(x + width * 0.5 * (i % 2), y + height * 0.5 * (Math.round(i * 0.5) - i % 2), width * 0.5, height * 0.5), capacity));
4074
4170
  }
4075
4171
  this._divided = true;
4076
4172
  };
@@ -4126,21 +4222,36 @@ class QuadTree {
4126
4222
 
4127
4223
  const qTreeCapacity = 4;
4128
4224
  const qTreeRectangle = canvasSize => {
4129
- return new Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, canvasSize.width * 3 / 2, canvasSize.height * 3 / 2);
4225
+ const {
4226
+ height,
4227
+ width
4228
+ } = canvasSize,
4229
+ posOffset = -0.25,
4230
+ sizeFactor = 1.5;
4231
+ return new Rectangle(posOffset * width, posOffset * height, sizeFactor * width, sizeFactor * height);
4130
4232
  };
4131
4233
  class Particles {
4132
4234
  constructor(engine, container) {
4133
4235
  this._applyDensity = (options, manualCount, group) => {
4236
+ const numberOptions = options.number;
4134
4237
  if (!options.number.density?.enable) {
4238
+ if (group === undefined) {
4239
+ this._limit = numberOptions.limit.value;
4240
+ } else {
4241
+ this._groupLimits.set(group, numberOptions.limit.value);
4242
+ }
4135
4243
  return;
4136
4244
  }
4137
- const numberOptions = options.number,
4138
- densityFactor = this._initDensityFactor(numberOptions.density),
4245
+ const densityFactor = this._initDensityFactor(numberOptions.density),
4139
4246
  optParticlesNumber = numberOptions.value,
4140
- optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber,
4247
+ optParticlesLimit = numberOptions.limit.value > 0 ? numberOptions.limit.value : optParticlesNumber,
4141
4248
  particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount,
4142
4249
  particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
4143
- this.limit = numberOptions.limit * densityFactor;
4250
+ if (group === undefined) {
4251
+ this._limit = numberOptions.limit.value * densityFactor;
4252
+ } else {
4253
+ this._groupLimits.set(group, numberOptions.limit.value * densityFactor);
4254
+ }
4144
4255
  if (particlesCount < particlesNumber) {
4145
4256
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
4146
4257
  } else if (particlesCount > particlesNumber) {
@@ -4158,7 +4269,7 @@ class Particles {
4158
4269
  };
4159
4270
  this._pushParticle = (position, overrideOptions, group, initializer) => {
4160
4271
  try {
4161
- let particle = this.pool.pop();
4272
+ let particle = this._pool.pop();
4162
4273
  if (particle) {
4163
4274
  particle.init(this._nextId, position, overrideOptions, group);
4164
4275
  } else {
@@ -4195,7 +4306,7 @@ class Particles {
4195
4306
  const zIdx = this._zArray.indexOf(particle);
4196
4307
  this._array.splice(index, 1);
4197
4308
  this._zArray.splice(zIdx, 1);
4198
- this.pool.push(particle);
4309
+ this._pool.push(particle);
4199
4310
  this._engine.dispatchEvent("particleRemoved", {
4200
4311
  container: this._container,
4201
4312
  data: {
@@ -4209,10 +4320,11 @@ class Particles {
4209
4320
  this._nextId = 0;
4210
4321
  this._array = [];
4211
4322
  this._zArray = [];
4212
- this.pool = [];
4213
- this.limit = 0;
4214
- this.needsSort = false;
4215
- this.lastZIndex = 0;
4323
+ this._pool = [];
4324
+ this._limit = 0;
4325
+ this._groupLimits = new Map();
4326
+ this._needsSort = false;
4327
+ this._lastZIndex = 0;
4216
4328
  this._interactionManager = new InteractionManager(engine, container);
4217
4329
  const canvasSize = container.canvas.size;
4218
4330
  this.quadTree = new QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
@@ -4230,19 +4342,22 @@ class Particles {
4230
4342
  }
4231
4343
  }
4232
4344
  addParticle(position, overrideOptions, group, initializer) {
4233
- this.pushing = true;
4234
- const container = this._container,
4235
- options = container.actualOptions,
4236
- limit = options.particles.number.limit;
4345
+ const limitOptions = this._container.actualOptions.particles.number.limit,
4346
+ limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit,
4347
+ currentCount = this.count;
4237
4348
  if (limit > 0) {
4238
- const countToRemove = this.count + 1 - limit;
4239
- if (countToRemove > 0) {
4240
- this.removeQuantity(countToRemove);
4349
+ if (limitOptions.mode === "delete") {
4350
+ const countToRemove = currentCount + 1 - limit;
4351
+ if (countToRemove > 0) {
4352
+ this.removeQuantity(countToRemove);
4353
+ }
4354
+ } else if (limitOptions.mode === "wait") {
4355
+ if (currentCount >= limit) {
4356
+ return;
4357
+ }
4241
4358
  }
4242
4359
  }
4243
- const res = this._pushParticle(position, overrideOptions, group, initializer);
4244
- this.pushing = false;
4245
- return res;
4360
+ return this._pushParticle(position, overrideOptions, group, initializer);
4246
4361
  }
4247
4362
  clear() {
4248
4363
  this._array = [];
@@ -4281,8 +4396,8 @@ class Particles {
4281
4396
  init() {
4282
4397
  const container = this._container,
4283
4398
  options = container.actualOptions;
4284
- this.lastZIndex = 0;
4285
- this.needsSort = false;
4399
+ this._lastZIndex = 0;
4400
+ this._needsSort = false;
4286
4401
  let handled = false;
4287
4402
  this.updaters = this._engine.getUpdaters(container, true);
4288
4403
  this._interactionManager.init();
@@ -4349,6 +4464,13 @@ class Particles {
4349
4464
  }
4350
4465
  this._applyDensity(options.particles, options.manualParticles.length);
4351
4466
  }
4467
+ setLastZIndex(zIndex) {
4468
+ this._lastZIndex = zIndex;
4469
+ this._needsSort = this._needsSort || this._lastZIndex < zIndex;
4470
+ }
4471
+ setResizeFactor(factor) {
4472
+ this._resizeFactor = factor;
4473
+ }
4352
4474
  async update(delta) {
4353
4475
  const container = this._container,
4354
4476
  particlesToDelete = new Set();
@@ -4357,10 +4479,10 @@ class Particles {
4357
4479
  pathGenerator.update();
4358
4480
  }
4359
4481
  for (const [, plugin] of container.plugins) {
4360
- plugin.update && plugin.update(delta);
4482
+ plugin.update && (await plugin.update(delta));
4361
4483
  }
4484
+ const resizeFactor = this._resizeFactor;
4362
4485
  for (const particle of this._array) {
4363
- const resizeFactor = container.canvas.resizeFactor;
4364
4486
  if (resizeFactor && !particle.ignoresResizeRatio) {
4365
4487
  particle.position.x *= resizeFactor.width;
4366
4488
  particle.position.y *= resizeFactor.height;
@@ -4388,7 +4510,7 @@ class Particles {
4388
4510
  const checkDelete = p => !particlesToDelete.has(p);
4389
4511
  this._array = this.filter(checkDelete);
4390
4512
  this._zArray = this._zArray.filter(checkDelete);
4391
- this.pool.push(...particlesToDelete);
4513
+ this._pool.push(...particlesToDelete);
4392
4514
  }
4393
4515
  await this._interactionManager.externalInteract(delta);
4394
4516
  for (const particle of this._array) {
@@ -4399,12 +4521,12 @@ class Particles {
4399
4521
  await this._interactionManager.particlesInteract(particle, delta);
4400
4522
  }
4401
4523
  }
4402
- delete container.canvas.resizeFactor;
4403
- if (this.needsSort) {
4524
+ delete this._resizeFactor;
4525
+ if (this._needsSort) {
4404
4526
  const zArray = this._zArray;
4405
4527
  zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
4406
- this.lastZIndex = zArray[zArray.length - 1].position.z;
4407
- this.needsSort = false;
4528
+ this._lastZIndex = zArray[zArray.length - 1].position.z;
4529
+ this._needsSort = false;
4408
4530
  }
4409
4531
  }
4410
4532
  }
@@ -4431,7 +4553,6 @@ class Retina {
4431
4553
  }
4432
4554
  const particles = options.particles,
4433
4555
  moveOptions = particles.move;
4434
- this.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4435
4556
  this.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
4436
4557
  this.sizeAnimationSpeed = getRangeValue(particles.size.animation.speed) * ratio;
4437
4558
  }
@@ -4441,7 +4562,6 @@ class Retina {
4441
4562
  moveOptions = options.move,
4442
4563
  moveDistance = moveOptions.distance,
4443
4564
  props = particle.retina;
4444
- props.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4445
4565
  props.moveDrift = getRangeValue(moveOptions.drift) * ratio;
4446
4566
  props.moveSpeed = getRangeValue(moveOptions.speed) * ratio;
4447
4567
  props.sizeAnimationSpeed = getRangeValue(options.size.animation.speed) * ratio;
@@ -4477,7 +4597,6 @@ function loadContainerOptions(engine, container, ...sourceOptionsArr) {
4477
4597
  }
4478
4598
  class Container {
4479
4599
  constructor(engine, id, sourceOptions) {
4480
- this.id = id;
4481
4600
  this._intersectionManager = entries => {
4482
4601
  if (!guardCheck(this) || !this.actualOptions.pauseOnOutsideViewport) {
4483
4602
  return;
@@ -4491,14 +4610,14 @@ class Container {
4491
4610
  };
4492
4611
  this._nextFrame = async timestamp => {
4493
4612
  try {
4494
- if (!this.smooth && this.lastFrameTime !== undefined && timestamp < this.lastFrameTime + 1000 / this.fpsLimit) {
4613
+ if (!this._smooth && this._lastFrameTime !== undefined && timestamp < this._lastFrameTime + 1000 / this.fpsLimit) {
4495
4614
  this.draw(false);
4496
4615
  return;
4497
4616
  }
4498
- this.lastFrameTime ??= timestamp;
4499
- const delta = initDelta(timestamp - this.lastFrameTime, this.fpsLimit, this.smooth);
4617
+ this._lastFrameTime ??= timestamp;
4618
+ const delta = initDelta(timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
4500
4619
  this.addLifeTime(delta.value);
4501
- this.lastFrameTime = timestamp;
4620
+ this._lastFrameTime = timestamp;
4502
4621
  if (delta.value > 1000) {
4503
4622
  this.draw(false);
4504
4623
  return;
@@ -4516,8 +4635,9 @@ class Container {
4516
4635
  }
4517
4636
  };
4518
4637
  this._engine = engine;
4638
+ this.id = Symbol(id);
4519
4639
  this.fpsLimit = 120;
4520
- this.smooth = false;
4640
+ this._smooth = false;
4521
4641
  this._delay = 0;
4522
4642
  this._duration = 0;
4523
4643
  this._lifeTime = 0;
@@ -4525,7 +4645,7 @@ class Container {
4525
4645
  this.started = false;
4526
4646
  this.destroyed = false;
4527
4647
  this._paused = true;
4528
- this.lastFrameTime = 0;
4648
+ this._lastFrameTime = 0;
4529
4649
  this.zLayers = 100;
4530
4650
  this.pageHidden = false;
4531
4651
  this._sourceOptions = sourceOptions;
@@ -4541,13 +4661,12 @@ class Container {
4541
4661
  }
4542
4662
  };
4543
4663
  this.plugins = new Map();
4544
- this.drawers = new Map();
4664
+ this.effectDrawers = new Map();
4665
+ this.shapeDrawers = new Map();
4545
4666
  this._options = loadContainerOptions(this._engine, this);
4546
4667
  this.actualOptions = loadContainerOptions(this._engine, this);
4547
4668
  this._eventListeners = new EventListeners(this);
4548
- if (typeof IntersectionObserver !== "undefined" && IntersectionObserver) {
4549
- this._intersectionObserver = new IntersectionObserver(entries => this._intersectionManager(entries));
4550
- }
4669
+ this._intersectionObserver = safeIntersectionObserver(entries => this._intersectionManager(entries));
4551
4670
  this._engine.dispatchEvent("containerBuilt", {
4552
4671
  container: this
4553
4672
  });
@@ -4661,11 +4780,17 @@ class Container {
4661
4780
  this.stop();
4662
4781
  this.particles.destroy();
4663
4782
  this.canvas.destroy();
4664
- for (const [, drawer] of this.drawers) {
4665
- drawer.destroy && drawer.destroy(this);
4783
+ for (const [, effectDrawer] of this.effectDrawers) {
4784
+ effectDrawer.destroy && effectDrawer.destroy(this);
4785
+ }
4786
+ for (const [, shapeDrawer] of this.shapeDrawers) {
4787
+ shapeDrawer.destroy && shapeDrawer.destroy(this);
4788
+ }
4789
+ for (const key of this.effectDrawers.keys()) {
4790
+ this.effectDrawers.delete(key);
4666
4791
  }
4667
- for (const key of this.drawers.keys()) {
4668
- this.drawers.delete(key);
4792
+ for (const key of this.shapeDrawers.keys()) {
4793
+ this.shapeDrawers.delete(key);
4669
4794
  }
4670
4795
  this._engine.clearPlugins(this);
4671
4796
  this.destroyed = true;
@@ -4685,7 +4810,7 @@ class Container {
4685
4810
  let refreshTime = force;
4686
4811
  this._drawAnimationFrame = requestAnimationFrame(async timestamp => {
4687
4812
  if (refreshTime) {
4688
- this.lastFrameTime = undefined;
4813
+ this._lastFrameTime = undefined;
4689
4814
  refreshTime = false;
4690
4815
  }
4691
4816
  await this._nextFrame(timestamp);
@@ -4720,11 +4845,18 @@ class Container {
4720
4845
  if (!guardCheck(this)) {
4721
4846
  return;
4722
4847
  }
4848
+ const effects = this._engine.getSupportedEffects();
4849
+ for (const type of effects) {
4850
+ const drawer = this._engine.getEffectDrawer(type);
4851
+ if (drawer) {
4852
+ this.effectDrawers.set(type, drawer);
4853
+ }
4854
+ }
4723
4855
  const shapes = this._engine.getSupportedShapes();
4724
4856
  for (const type of shapes) {
4725
4857
  const drawer = this._engine.getShapeDrawer(type);
4726
4858
  if (drawer) {
4727
- this.drawers.set(type, drawer);
4859
+ this.shapeDrawers.set(type, drawer);
4728
4860
  }
4729
4861
  }
4730
4862
  this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
@@ -4743,8 +4875,11 @@ class Container {
4743
4875
  this._delay = getRangeValue(this.actualOptions.delay) * 1000;
4744
4876
  this._lifeTime = 0;
4745
4877
  this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
4746
- this.smooth = this.actualOptions.smooth;
4747
- for (const [, drawer] of this.drawers) {
4878
+ this._smooth = this.actualOptions.smooth;
4879
+ for (const [, drawer] of this.effectDrawers) {
4880
+ drawer.init && (await drawer.init(this));
4881
+ }
4882
+ for (const [, drawer] of this.shapeDrawers) {
4748
4883
  drawer.init && (await drawer.init(this));
4749
4884
  }
4750
4885
  for (const [, plugin] of this.plugins) {
@@ -4885,10 +5020,10 @@ class Container {
4885
5020
  this.actualOptions.responsive = [];
4886
5021
  const newMaxWidth = this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
4887
5022
  this.actualOptions.setTheme(this._currentTheme);
4888
- if (this.responsiveMaxWidth === newMaxWidth) {
5023
+ if (this._responsiveMaxWidth === newMaxWidth) {
4889
5024
  return false;
4890
5025
  }
4891
- this.responsiveMaxWidth = newMaxWidth;
5026
+ this._responsiveMaxWidth = newMaxWidth;
4892
5027
  return true;
4893
5028
  }
4894
5029
  }
@@ -4979,7 +5114,8 @@ class Engine {
4979
5114
  this.movers = new Map();
4980
5115
  this.updaters = new Map();
4981
5116
  this.presets = new Map();
4982
- this.drawers = new Map();
5117
+ this.effectDrawers = new Map();
5118
+ this.shapeDrawers = new Map();
4983
5119
  this.pathGenerators = new Map();
4984
5120
  }
4985
5121
  get configs() {
@@ -4990,17 +5126,23 @@ class Engine {
4990
5126
  return res;
4991
5127
  }
4992
5128
  get version() {
4993
- return "3.0.0-beta.2";
5129
+ return "3.0.0-beta.4";
4994
5130
  }
4995
- addConfig(nameOrConfig, config) {
4996
- if (isString(nameOrConfig)) {
4997
- if (config) {
4998
- config.name = nameOrConfig;
4999
- this._configs.set(nameOrConfig, config);
5131
+ addConfig(config) {
5132
+ const name = config.name ?? "default";
5133
+ this._configs.set(name, config);
5134
+ this._eventDispatcher.dispatchEvent("configAdded", {
5135
+ data: {
5136
+ name,
5137
+ config
5000
5138
  }
5001
- } else {
5002
- this._configs.set(nameOrConfig.name ?? "default", nameOrConfig);
5003
- }
5139
+ });
5140
+ }
5141
+ async addEffect(effect, drawer, refresh = true) {
5142
+ executeOnSingleOrMultiple(effect, type => {
5143
+ !this.getEffectDrawer(type) && this.effectDrawers.set(type, drawer);
5144
+ });
5145
+ await this.refresh(refresh);
5004
5146
  }
5005
5147
  addEventListener(type, listener) {
5006
5148
  this._eventDispatcher.addEventListener(type, listener);
@@ -5029,44 +5171,11 @@ class Engine {
5029
5171
  (override || !this.getPreset(preset)) && this.presets.set(preset, options);
5030
5172
  await this.refresh(refresh);
5031
5173
  }
5032
- async addShape(shape, drawer, initOrRefresh, afterEffectOrRefresh, destroyOrRefresh, refresh = true) {
5033
- let customDrawer;
5034
- let realRefresh = refresh,
5035
- realInit,
5036
- realAfterEffect,
5037
- realDestroy;
5038
- if (isBoolean(initOrRefresh)) {
5039
- realRefresh = initOrRefresh;
5040
- realInit = undefined;
5041
- } else {
5042
- realInit = initOrRefresh;
5043
- }
5044
- if (isBoolean(afterEffectOrRefresh)) {
5045
- realRefresh = afterEffectOrRefresh;
5046
- realAfterEffect = undefined;
5047
- } else {
5048
- realAfterEffect = afterEffectOrRefresh;
5049
- }
5050
- if (isBoolean(destroyOrRefresh)) {
5051
- realRefresh = destroyOrRefresh;
5052
- realDestroy = undefined;
5053
- } else {
5054
- realDestroy = destroyOrRefresh;
5055
- }
5056
- if (isFunction(drawer)) {
5057
- customDrawer = {
5058
- afterEffect: realAfterEffect,
5059
- destroy: realDestroy,
5060
- draw: drawer,
5061
- init: realInit
5062
- };
5063
- } else {
5064
- customDrawer = drawer;
5065
- }
5174
+ async addShape(shape, drawer, refresh = true) {
5066
5175
  executeOnSingleOrMultiple(shape, type => {
5067
- !this.getShapeDrawer(type) && this.drawers.set(type, customDrawer);
5176
+ !this.getShapeDrawer(type) && this.shapeDrawers.set(type, drawer);
5068
5177
  });
5069
- await this.refresh(realRefresh);
5178
+ await this.refresh(refresh);
5070
5179
  }
5071
5180
  clearPlugins(container) {
5072
5181
  this.updaters.delete(container);
@@ -5095,6 +5204,9 @@ class Engine {
5095
5204
  }
5096
5205
  return res;
5097
5206
  }
5207
+ getEffectDrawer(type) {
5208
+ return this.effectDrawers.get(type);
5209
+ }
5098
5210
  getInteractors(container, force = false) {
5099
5211
  return getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
5100
5212
  }
@@ -5111,10 +5223,13 @@ class Engine {
5111
5223
  return this.presets.get(preset);
5112
5224
  }
5113
5225
  getShapeDrawer(type) {
5114
- return this.drawers.get(type);
5226
+ return this.shapeDrawers.get(type);
5227
+ }
5228
+ getSupportedEffects() {
5229
+ return this.effectDrawers.keys();
5115
5230
  }
5116
5231
  getSupportedShapes() {
5117
- return this.drawers.keys();
5232
+ return this.shapeDrawers.keys();
5118
5233
  }
5119
5234
  getUpdaters(container, force = false) {
5120
5235
  return getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
@@ -5144,7 +5259,7 @@ class Engine {
5144
5259
  }
5145
5260
  const currentOptions = itemFromSingleOrMultiple(options, index),
5146
5261
  dom = this.dom(),
5147
- oldIndex = dom.findIndex(v => v.id === id);
5262
+ oldIndex = dom.findIndex(v => v.id.description === id);
5148
5263
  if (oldIndex >= 0) {
5149
5264
  const old = this.domItem(oldIndex);
5150
5265
  if (old && !old.destroyed) {
@@ -5410,7 +5525,6 @@ class ParticlesInteractorBase {
5410
5525
 
5411
5526
 
5412
5527
 
5413
-
5414
5528
 
5415
5529
 
5416
5530
  ;// CONCATENATED MODULE: ../../engine/dist/browser/index.js
@@ -5886,7 +6000,7 @@ function addSplitParticle(engine, container, parent, splitParticlesOptions) {
5886
6000
  }
5887
6001
  const splitOptions = destroyOptions.split,
5888
6002
  options = loadParticlesOptions(engine, container, parent.options),
5889
- factor = getValue(splitOptions.factor),
6003
+ factor = getRangeValue(splitOptions.factor.value),
5890
6004
  parentColor = parent.getFillColor();
5891
6005
  if (splitOptions.color) {
5892
6006
  options.color.load(splitOptions.color);
@@ -5948,7 +6062,7 @@ function split(engine, container, particle) {
5948
6062
  if (splitOptions.count >= 0 && (particle.splitCount === undefined || particle.splitCount++ > splitOptions.count)) {
5949
6063
  return;
5950
6064
  }
5951
- const rate = getValue(splitOptions.rate),
6065
+ const rate = getRangeValue(splitOptions.rate.value),
5952
6066
  particlesSplitOptions = itemFromSingleOrMultiple(splitOptions.particles);
5953
6067
  for (let i = 0; i < rate; i++) {
5954
6068
  addSplitParticle(engine, container, particle, particlesSplitOptions);
@@ -6037,35 +6151,6 @@ class DestroyUpdater {
6037
6151
  async function loadDestroyUpdater(engine, refresh = true) {
6038
6152
  await engine.addParticleUpdater("destroy", container => new DestroyUpdater(engine, container), refresh);
6039
6153
  }
6040
- ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Shapes/Circle/CircleShape.js
6041
-
6042
- class CircleShape {
6043
- randomPosition(position, size, fill) {
6044
- const generateTheta = (x, y) => {
6045
- const u = getRandom() / 4.0,
6046
- theta = Math.atan(y / x * Math.tan(2 * Math.PI * u)),
6047
- v = getRandom();
6048
- if (v < 0.25) {
6049
- return theta;
6050
- } else if (v < 0.5) {
6051
- return Math.PI - theta;
6052
- } else if (v < 0.75) {
6053
- return Math.PI + theta;
6054
- } else {
6055
- return -theta;
6056
- }
6057
- },
6058
- radius = (x, y, theta) => x * y / Math.sqrt((y * Math.cos(theta)) ** 2 + (x * Math.sin(theta)) ** 2),
6059
- [a, b] = [size.width / 2, size.height / 2],
6060
- randomTheta = generateTheta(a, b),
6061
- maxRadius = radius(a, b, randomTheta),
6062
- randomRadius = fill ? maxRadius * Math.sqrt(getRandom()) : maxRadius;
6063
- return {
6064
- x: position.x + randomRadius * Math.cos(randomTheta),
6065
- y: position.y + randomRadius * Math.sin(randomTheta)
6066
- };
6067
- }
6068
- }
6069
6154
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterLife.js
6070
6155
 
6071
6156
  class EmitterLife {
@@ -6109,6 +6194,46 @@ class EmitterRate {
6109
6194
  }
6110
6195
  }
6111
6196
  }
6197
+ ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterShapeReplace.js
6198
+ class EmitterShapeReplace {
6199
+ constructor() {
6200
+ this.color = false;
6201
+ this.opacity = false;
6202
+ }
6203
+ load(data) {
6204
+ if (!data) {
6205
+ return;
6206
+ }
6207
+ if (data.color !== undefined) {
6208
+ this.color = data.color;
6209
+ }
6210
+ if (data.opacity !== undefined) {
6211
+ this.opacity = data.opacity;
6212
+ }
6213
+ }
6214
+ }
6215
+ ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterShape.js
6216
+
6217
+
6218
+ class EmitterShape {
6219
+ constructor() {
6220
+ this.options = {};
6221
+ this.replace = new EmitterShapeReplace();
6222
+ this.type = "square";
6223
+ }
6224
+ load(data) {
6225
+ if (!data) {
6226
+ return;
6227
+ }
6228
+ if (data.options !== undefined) {
6229
+ this.options = deepExtend({}, data.options ?? {});
6230
+ }
6231
+ this.replace.load(data.replace);
6232
+ if (data.type !== undefined) {
6233
+ this.type = data.type;
6234
+ }
6235
+ }
6236
+ }
6112
6237
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterSize.js
6113
6238
  class EmitterSize {
6114
6239
  constructor() {
@@ -6136,13 +6261,14 @@ class EmitterSize {
6136
6261
 
6137
6262
 
6138
6263
 
6264
+
6139
6265
  class Emitter {
6140
6266
  constructor() {
6141
6267
  this.autoPlay = true;
6142
6268
  this.fill = true;
6143
6269
  this.life = new EmitterLife();
6144
6270
  this.rate = new EmitterRate();
6145
- this.shape = "square";
6271
+ this.shape = new EmitterShape();
6146
6272
  this.startCount = 0;
6147
6273
  }
6148
6274
  load(data) {
@@ -6171,9 +6297,7 @@ class Emitter {
6171
6297
  return deepExtend({}, particles);
6172
6298
  });
6173
6299
  this.rate.load(data.rate);
6174
- if (data.shape !== undefined) {
6175
- this.shape = data.shape;
6176
- }
6300
+ this.shape.load(data.shape);
6177
6301
  if (data.position !== undefined) {
6178
6302
  this.position = {};
6179
6303
  if (data.position.x !== undefined) {
@@ -6198,59 +6322,31 @@ class Emitter {
6198
6322
 
6199
6323
 
6200
6324
 
6325
+ function setParticlesOptionsColor(particlesOptions, color) {
6326
+ if (particlesOptions.color) {
6327
+ particlesOptions.color.value = color;
6328
+ } else {
6329
+ particlesOptions.color = {
6330
+ value: color
6331
+ };
6332
+ }
6333
+ }
6201
6334
  class EmitterInstance {
6202
6335
  constructor(engine, emitters, container, options, position) {
6203
6336
  this.emitters = emitters;
6204
- this.container = container;
6205
- this._calcPosition = () => {
6206
- return calcPositionOrRandomFromSizeRanged({
6207
- size: this.container.canvas.size,
6208
- position: this.options.position
6209
- });
6210
- };
6211
- this._destroy = () => {
6212
- this.emitters.removeEmitter(this);
6213
- this._engine.dispatchEvent("emitterDestroyed", {
6214
- container: this.container,
6215
- data: {
6216
- emitter: this
6217
- }
6218
- });
6219
- };
6220
- this._emit = () => {
6221
- if (this._paused) {
6222
- return;
6223
- }
6224
- const quantity = getRangeValue(this.options.rate.quantity);
6225
- this._emitParticles(quantity);
6226
- };
6227
- this._emitParticles = quantity => {
6228
- const position = this.getPosition(),
6229
- size = this.getSize(),
6230
- singleParticlesOptions = itemFromSingleOrMultiple(this._particlesOptions);
6231
- for (let i = 0; i < quantity; i++) {
6232
- const particlesOptions = deepExtend({}, singleParticlesOptions);
6233
- if (this.spawnColor) {
6234
- const hslAnimation = this.options.spawnColor?.animation;
6235
- if (hslAnimation) {
6236
- this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, 360);
6237
- this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, 100);
6238
- this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, 100);
6239
- }
6240
- if (!particlesOptions.color) {
6241
- particlesOptions.color = {
6242
- value: this.spawnColor
6243
- };
6244
- } else {
6245
- particlesOptions.color.value = this.spawnColor;
6246
- }
6247
- }
6248
- if (!position) {
6249
- return;
6337
+ this.container = container;
6338
+ this._destroy = () => {
6339
+ this._mutationObserver?.disconnect();
6340
+ this._mutationObserver = undefined;
6341
+ this._resizeObserver?.disconnect();
6342
+ this._resizeObserver = undefined;
6343
+ this.emitters.removeEmitter(this);
6344
+ this._engine.dispatchEvent("emitterDestroyed", {
6345
+ container: this.container,
6346
+ data: {
6347
+ emitter: this
6250
6348
  }
6251
- const pPosition = this._shape?.randomPosition(position, size, this.fill) ?? position;
6252
- this.container.particles.addParticle(pPosition, particlesOptions);
6253
- }
6349
+ });
6254
6350
  };
6255
6351
  this._prepareToDie = () => {
6256
6352
  if (this._paused) {
@@ -6286,7 +6382,6 @@ class EmitterInstance {
6286
6382
  this._spawnDelay = getRangeValue(this.options.life.delay ?? 0) * 1000 / this.container.retina.reduceFactor;
6287
6383
  this.position = this._initialPosition ?? this._calcPosition();
6288
6384
  this.name = this.options.name;
6289
- this._shape = this._engine.emitterShapeManager?.getShape(this.options.shape);
6290
6385
  this.fill = this.options.fill;
6291
6386
  this._firstSpawn = !this.options.life.wait;
6292
6387
  this._startParticlesAdded = false;
@@ -6299,17 +6394,31 @@ class EmitterInstance {
6299
6394
  }
6300
6395
  this._paused = !this.options.autoPlay;
6301
6396
  this._particlesOptions = particlesOptions;
6302
- this.size = this.options.size ?? (() => {
6303
- const size = new EmitterSize();
6304
- size.load({
6305
- height: 0,
6306
- mode: "percent",
6307
- width: 0
6308
- });
6309
- return size;
6310
- })();
6397
+ this._size = this._calcSize();
6398
+ this.size = getSize(this._size, this.container.canvas.size);
6311
6399
  this._lifeCount = this.options.life.count ?? -1;
6312
6400
  this._immortal = this._lifeCount <= 0;
6401
+ if (this.options.domId) {
6402
+ const element = document.getElementById(this.options.domId);
6403
+ if (element) {
6404
+ this._mutationObserver = new MutationObserver(() => {
6405
+ this.resize();
6406
+ });
6407
+ this._resizeObserver = new ResizeObserver(() => {
6408
+ this.resize();
6409
+ });
6410
+ this._mutationObserver.observe(element, {
6411
+ attributes: true,
6412
+ attributeFilter: ["style", "width", "height"]
6413
+ });
6414
+ this._resizeObserver.observe(element);
6415
+ }
6416
+ }
6417
+ const shapeOptions = this.options.shape,
6418
+ shapeGenerator = this._engine.emitterShapeManager?.getShapeGenerator(shapeOptions.type);
6419
+ if (shapeGenerator) {
6420
+ this._shape = shapeGenerator.generate(this.position, this.size, this.fill, shapeOptions.options);
6421
+ }
6313
6422
  this._engine.dispatchEvent("emitterCreated", {
6314
6423
  container,
6315
6424
  data: {
@@ -6326,33 +6435,8 @@ class EmitterInstance {
6326
6435
  this._paused = false;
6327
6436
  this.play();
6328
6437
  }
6329
- getPosition() {
6330
- if (this.options.domId) {
6331
- const container = this.container,
6332
- element = document.getElementById(this.options.domId);
6333
- if (element) {
6334
- const elRect = element.getBoundingClientRect();
6335
- return {
6336
- x: (elRect.x + elRect.width / 2) * container.retina.pixelRatio,
6337
- y: (elRect.y + elRect.height / 2) * container.retina.pixelRatio
6338
- };
6339
- }
6340
- }
6341
- return this.position;
6342
- }
6343
- getSize() {
6344
- const container = this.container;
6345
- if (this.options.domId) {
6346
- const element = document.getElementById(this.options.domId);
6347
- if (element) {
6348
- const elRect = element.getBoundingClientRect();
6349
- return {
6350
- width: elRect.width * container.retina.pixelRatio,
6351
- height: elRect.height * container.retina.pixelRatio
6352
- };
6353
- }
6354
- }
6355
- return getSize(this.size, container.canvas.size);
6438
+ async init() {
6439
+ await this._shape?.init();
6356
6440
  }
6357
6441
  pause() {
6358
6442
  if (this._paused) {
@@ -6378,8 +6462,11 @@ class EmitterInstance {
6378
6462
  resize() {
6379
6463
  const initialPosition = this._initialPosition;
6380
6464
  this.position = initialPosition && isPointInside(initialPosition, this.container.canvas.size, Vector.origin) ? initialPosition : this._calcPosition();
6465
+ this._size = this._calcSize();
6466
+ this.size = getSize(this._size, this.container.canvas.size);
6467
+ this._shape?.resize(this.position, this.size);
6381
6468
  }
6382
- update(delta) {
6469
+ async update(delta) {
6383
6470
  if (this._paused) {
6384
6471
  return;
6385
6472
  }
@@ -6390,7 +6477,7 @@ class EmitterInstance {
6390
6477
  }
6391
6478
  if (!this._startParticlesAdded) {
6392
6479
  this._startParticlesAdded = true;
6393
- this._emitParticles(this.options.startCount);
6480
+ await this._emitParticles(this.options.startCount);
6394
6481
  }
6395
6482
  if (this._duration !== undefined) {
6396
6483
  this._currentDuration += delta.value;
@@ -6431,6 +6518,94 @@ class EmitterInstance {
6431
6518
  }
6432
6519
  }
6433
6520
  }
6521
+ _calcPosition() {
6522
+ if (this.options.domId) {
6523
+ const container = this.container,
6524
+ element = document.getElementById(this.options.domId);
6525
+ if (element) {
6526
+ const elRect = element.getBoundingClientRect();
6527
+ return {
6528
+ x: (elRect.x + elRect.width / 2) * container.retina.pixelRatio,
6529
+ y: (elRect.y + elRect.height / 2) * container.retina.pixelRatio
6530
+ };
6531
+ }
6532
+ }
6533
+ return calcPositionOrRandomFromSizeRanged({
6534
+ size: this.container.canvas.size,
6535
+ position: this.options.position
6536
+ });
6537
+ }
6538
+ _calcSize() {
6539
+ const container = this.container;
6540
+ if (this.options.domId) {
6541
+ const element = document.getElementById(this.options.domId);
6542
+ if (element) {
6543
+ const elRect = element.getBoundingClientRect();
6544
+ return {
6545
+ width: elRect.width * container.retina.pixelRatio,
6546
+ height: elRect.height * container.retina.pixelRatio,
6547
+ mode: "precise"
6548
+ };
6549
+ }
6550
+ }
6551
+ return this.options.size ?? (() => {
6552
+ const size = new EmitterSize();
6553
+ size.load({
6554
+ height: 0,
6555
+ mode: "percent",
6556
+ width: 0
6557
+ });
6558
+ return size;
6559
+ })();
6560
+ }
6561
+ async _emit() {
6562
+ if (this._paused) {
6563
+ return;
6564
+ }
6565
+ const quantity = getRangeValue(this.options.rate.quantity);
6566
+ await this._emitParticles(quantity);
6567
+ }
6568
+ async _emitParticles(quantity) {
6569
+ const singleParticlesOptions = itemFromSingleOrMultiple(this._particlesOptions);
6570
+ for (let i = 0; i < quantity; i++) {
6571
+ const particlesOptions = deepExtend({}, singleParticlesOptions);
6572
+ if (this.spawnColor) {
6573
+ const hslAnimation = this.options.spawnColor?.animation;
6574
+ if (hslAnimation) {
6575
+ this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, 360);
6576
+ this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, 100);
6577
+ this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, 100);
6578
+ }
6579
+ setParticlesOptionsColor(particlesOptions, this.spawnColor);
6580
+ }
6581
+ const shapeOptions = this.options.shape;
6582
+ let position = this.position;
6583
+ if (this._shape) {
6584
+ const shapePosData = await this._shape.randomPosition();
6585
+ if (shapePosData) {
6586
+ position = shapePosData.position;
6587
+ const replaceData = shapeOptions.replace;
6588
+ if (replaceData.color && shapePosData.color) {
6589
+ setParticlesOptionsColor(particlesOptions, shapePosData.color);
6590
+ }
6591
+ if (replaceData.opacity) {
6592
+ if (particlesOptions.opacity) {
6593
+ particlesOptions.opacity.value = shapePosData.opacity;
6594
+ } else {
6595
+ particlesOptions.opacity = {
6596
+ value: shapePosData.opacity
6597
+ };
6598
+ }
6599
+ }
6600
+ } else {
6601
+ position = null;
6602
+ }
6603
+ }
6604
+ if (position) {
6605
+ this.container.particles.addParticle(position, particlesOptions);
6606
+ }
6607
+ }
6608
+ }
6434
6609
  }
6435
6610
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Emitters.js
6436
6611
 
@@ -6450,7 +6625,7 @@ class Emitters {
6450
6625
  value: []
6451
6626
  };
6452
6627
  container.getEmitter = idxOrName => idxOrName === undefined || isNumber(idxOrName) ? this.array[idxOrName || 0] : this.array.find(t => t.name === idxOrName);
6453
- container.addEmitter = (options, position) => this.addEmitter(options, position);
6628
+ container.addEmitter = async (options, position) => this.addEmitter(options, position);
6454
6629
  container.removeEmitter = idxOrName => {
6455
6630
  const emitter = container.getEmitter(idxOrName);
6456
6631
  if (emitter) {
@@ -6470,10 +6645,11 @@ class Emitters {
6470
6645
  }
6471
6646
  };
6472
6647
  }
6473
- addEmitter(options, position) {
6648
+ async addEmitter(options, position) {
6474
6649
  const emitterOptions = new Emitter();
6475
6650
  emitterOptions.load(options);
6476
6651
  const emitter = new EmitterInstance(this._engine, this, this.container, emitterOptions, position);
6652
+ await emitter.init();
6477
6653
  this.array.push(emitter);
6478
6654
  return emitter;
6479
6655
  }
@@ -6517,10 +6693,10 @@ class Emitters {
6517
6693
  }
6518
6694
  if (isArray(this.emitters)) {
6519
6695
  for (const emitterOptions of this.emitters) {
6520
- this.addEmitter(emitterOptions);
6696
+ await this.addEmitter(emitterOptions);
6521
6697
  }
6522
6698
  } else {
6523
- this.addEmitter(this.emitters);
6699
+ await this.addEmitter(this.emitters);
6524
6700
  }
6525
6701
  }
6526
6702
  pause() {
@@ -6547,71 +6723,41 @@ class Emitters {
6547
6723
  stop() {
6548
6724
  this.array = [];
6549
6725
  }
6550
- update(delta) {
6726
+ async update(delta) {
6551
6727
  for (const emitter of this.array) {
6552
- emitter.update(delta);
6728
+ await emitter.update(delta);
6553
6729
  }
6554
6730
  }
6555
6731
  }
6556
6732
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/ShapeManager.js
6557
- const shapes = new Map();
6733
+ const shapeGeneratorss = new Map();
6558
6734
  class ShapeManager {
6559
6735
  constructor(engine) {
6560
6736
  this._engine = engine;
6561
6737
  }
6562
- addShape(name, drawer) {
6563
- if (!this.getShape(name)) {
6564
- shapes.set(name, drawer);
6738
+ addShapeGenerator(name, generator) {
6739
+ if (!this.getShapeGenerator(name)) {
6740
+ shapeGeneratorss.set(name, generator);
6565
6741
  }
6566
6742
  }
6567
- getShape(name) {
6568
- return shapes.get(name);
6743
+ getShapeGenerator(name) {
6744
+ return shapeGeneratorss.get(name);
6569
6745
  }
6570
- getSupportedShapes() {
6571
- return shapes.keys();
6746
+ getSupportedShapeGenerators() {
6747
+ return shapeGeneratorss.keys();
6572
6748
  }
6573
6749
  }
6574
- ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Shapes/Square/SquareShape.js
6575
-
6576
- function randomSquareCoordinate(position, offset) {
6577
- return position + offset * (getRandom() - 0.5);
6578
- }
6579
- class SquareShape {
6580
- randomPosition(position, size, fill) {
6581
- if (fill) {
6582
- return {
6583
- x: randomSquareCoordinate(position.x, size.width),
6584
- y: randomSquareCoordinate(position.y, size.height)
6585
- };
6586
- } else {
6587
- const halfW = size.width / 2,
6588
- halfH = size.height / 2,
6589
- side = Math.floor(getRandom() * 4),
6590
- v = (getRandom() - 0.5) * 2;
6591
- switch (side) {
6592
- case 0:
6593
- return {
6594
- x: position.x + v * halfW,
6595
- y: position.y - halfH
6596
- };
6597
- case 1:
6598
- return {
6599
- x: position.x - halfW,
6600
- y: position.y + v * halfH
6601
- };
6602
- case 2:
6603
- return {
6604
- x: position.x + v * halfW,
6605
- y: position.y + halfH
6606
- };
6607
- case 3:
6608
- default:
6609
- return {
6610
- x: position.x + halfW,
6611
- y: position.y + v * halfH
6612
- };
6613
- }
6614
- }
6750
+ ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/EmitterShapeBase.js
6751
+ class EmitterShapeBase {
6752
+ constructor(position, size, fill, options) {
6753
+ this.position = position;
6754
+ this.size = size;
6755
+ this.fill = fill;
6756
+ this.options = options;
6757
+ }
6758
+ resize(position, size) {
6759
+ this.position = position;
6760
+ this.size = size;
6615
6761
  }
6616
6762
  }
6617
6763
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/index.js
@@ -6619,8 +6765,6 @@ class SquareShape {
6619
6765
 
6620
6766
 
6621
6767
 
6622
-
6623
-
6624
6768
  class EmittersPlugin {
6625
6769
  constructor(engine) {
6626
6770
  this._engine = engine;
@@ -6705,20 +6849,149 @@ async function loadEmittersPlugin(engine, refresh = true) {
6705
6849
  if (!engine.emitterShapeManager) {
6706
6850
  engine.emitterShapeManager = new ShapeManager(engine);
6707
6851
  }
6708
- if (!engine.addEmitterShape) {
6709
- engine.addEmitterShape = (name, shape) => {
6710
- engine.emitterShapeManager?.addShape(name, shape);
6852
+ if (!engine.addEmitterShapeGenerator) {
6853
+ engine.addEmitterShapeGenerator = (name, generator) => {
6854
+ engine.emitterShapeManager?.addShapeGenerator(name, generator);
6711
6855
  };
6712
6856
  }
6713
6857
  const plugin = new EmittersPlugin(engine);
6714
6858
  await engine.addPlugin(plugin, refresh);
6715
- engine.addEmitterShape("circle", new CircleShape());
6716
- engine.addEmitterShape("square", new SquareShape());
6717
6859
  }
6718
6860
 
6719
6861
 
6720
6862
 
6721
6863
 
6864
+
6865
+
6866
+
6867
+ ;// CONCATENATED MODULE: ../../plugins/emittersShapes/circle/dist/browser/EmittersCircleShape.js
6868
+
6869
+
6870
+ class EmittersCircleShape extends EmitterShapeBase {
6871
+ constructor(position, size, fill, options) {
6872
+ super(position, size, fill, options);
6873
+ }
6874
+ async init() {}
6875
+ async randomPosition() {
6876
+ const size = this.size,
6877
+ fill = this.fill,
6878
+ position = this.position,
6879
+ generateTheta = (x, y) => {
6880
+ const u = getRandom() / 4.0,
6881
+ theta = Math.atan(y / x * Math.tan(2 * Math.PI * u)),
6882
+ v = getRandom();
6883
+ if (v < 0.25) {
6884
+ return theta;
6885
+ } else if (v < 0.5) {
6886
+ return Math.PI - theta;
6887
+ } else if (v < 0.75) {
6888
+ return Math.PI + theta;
6889
+ } else {
6890
+ return -theta;
6891
+ }
6892
+ },
6893
+ radius = (x, y, theta) => x * y / Math.sqrt((y * Math.cos(theta)) ** 2 + (x * Math.sin(theta)) ** 2),
6894
+ [a, b] = [size.width / 2, size.height / 2],
6895
+ randomTheta = generateTheta(a, b),
6896
+ maxRadius = radius(a, b, randomTheta),
6897
+ randomRadius = fill ? maxRadius * Math.sqrt(getRandom()) : maxRadius;
6898
+ return {
6899
+ position: {
6900
+ x: position.x + randomRadius * Math.cos(randomTheta),
6901
+ y: position.y + randomRadius * Math.sin(randomTheta)
6902
+ }
6903
+ };
6904
+ }
6905
+ }
6906
+ ;// CONCATENATED MODULE: ../../plugins/emittersShapes/circle/dist/browser/EmittersCircleShapeGenerator.js
6907
+
6908
+ class EmittersCircleShapeGenerator {
6909
+ generate(position, size, fill, options) {
6910
+ return new EmittersCircleShape(position, size, fill, options);
6911
+ }
6912
+ }
6913
+ ;// CONCATENATED MODULE: ../../plugins/emittersShapes/circle/dist/browser/index.js
6914
+
6915
+ async function loadEmittersShapeCircle(engine, refresh = true) {
6916
+ const emittersEngine = engine;
6917
+ emittersEngine.addEmitterShapeGenerator && emittersEngine.addEmitterShapeGenerator("circle", new EmittersCircleShapeGenerator());
6918
+ await emittersEngine.refresh(refresh);
6919
+ }
6920
+ ;// CONCATENATED MODULE: ../../plugins/emittersShapes/square/dist/browser/EmittersSquareShape.js
6921
+
6922
+
6923
+ function randomSquareCoordinate(position, offset) {
6924
+ return position + offset * (getRandom() - 0.5);
6925
+ }
6926
+ class EmittersSquareShape extends EmitterShapeBase {
6927
+ constructor(position, size, fill, options) {
6928
+ super(position, size, fill, options);
6929
+ }
6930
+ async init() {}
6931
+ async randomPosition() {
6932
+ const fill = this.fill,
6933
+ position = this.position,
6934
+ size = this.size;
6935
+ if (fill) {
6936
+ return {
6937
+ position: {
6938
+ x: randomSquareCoordinate(position.x, size.width),
6939
+ y: randomSquareCoordinate(position.y, size.height)
6940
+ }
6941
+ };
6942
+ } else {
6943
+ const halfW = size.width / 2,
6944
+ halfH = size.height / 2,
6945
+ side = Math.floor(getRandom() * 4),
6946
+ v = (getRandom() - 0.5) * 2;
6947
+ switch (side) {
6948
+ case 0:
6949
+ return {
6950
+ position: {
6951
+ x: position.x + v * halfW,
6952
+ y: position.y - halfH
6953
+ }
6954
+ };
6955
+ case 1:
6956
+ return {
6957
+ position: {
6958
+ x: position.x - halfW,
6959
+ y: position.y + v * halfH
6960
+ }
6961
+ };
6962
+ case 2:
6963
+ return {
6964
+ position: {
6965
+ x: position.x + v * halfW,
6966
+ y: position.y + halfH
6967
+ }
6968
+ };
6969
+ case 3:
6970
+ default:
6971
+ return {
6972
+ position: {
6973
+ x: position.x + halfW,
6974
+ y: position.y + v * halfH
6975
+ }
6976
+ };
6977
+ }
6978
+ }
6979
+ }
6980
+ }
6981
+ ;// CONCATENATED MODULE: ../../plugins/emittersShapes/square/dist/browser/EmittersSquareShapeGenerator.js
6982
+
6983
+ class EmittersSquareShapeGenerator {
6984
+ generate(position, size, fill, options) {
6985
+ return new EmittersSquareShape(position, size, fill, options);
6986
+ }
6987
+ }
6988
+ ;// CONCATENATED MODULE: ../../plugins/emittersShapes/square/dist/browser/index.js
6989
+
6990
+ async function loadEmittersShapeSquare(engine, refresh = true) {
6991
+ const emittersEngine = engine;
6992
+ emittersEngine.addEmitterShapeGenerator && emittersEngine.addEmitterShapeGenerator("square", new EmittersSquareShapeGenerator());
6993
+ await emittersEngine.refresh(refresh);
6994
+ }
6722
6995
  ;// CONCATENATED MODULE: ../../interactions/external/trail/dist/browser/Options/Classes/Trail.js
6723
6996
 
6724
6997
  class Trail {
@@ -6748,6 +7021,7 @@ class Trail {
6748
7021
  ;// CONCATENATED MODULE: ../../interactions/external/trail/dist/browser/TrailMaker.js
6749
7022
 
6750
7023
 
7024
+ const trailMode = "trail";
6751
7025
  class TrailMaker extends ExternalInteractorBase {
6752
7026
  constructor(container) {
6753
7027
  super(container);
@@ -6794,7 +7068,7 @@ class TrailMaker extends ExternalInteractorBase {
6794
7068
  options = container.actualOptions,
6795
7069
  mouse = container.interactivity.mouse,
6796
7070
  events = (particle?.interactivity ?? options.interactivity).events;
6797
- return mouse.clicking && mouse.inside && !!mouse.position && isInArray("trail", events.onClick.mode) || mouse.inside && !!mouse.position && isInArray("trail", events.onHover.mode);
7071
+ return mouse.clicking && mouse.inside && !!mouse.position && isInArray(trailMode, events.onClick.mode) || mouse.inside && !!mouse.position && isInArray(trailMode, events.onHover.mode);
6798
7072
  }
6799
7073
  loadModeOptions(options, ...sources) {
6800
7074
  if (!options.trail) {
@@ -7112,10 +7386,10 @@ function applyDistance(particle) {
7112
7386
  if ((hDistance && dxFixed >= hDistance || vDistance && dyFixed >= vDistance) && !particle.misplaced) {
7113
7387
  particle.misplaced = !!hDistance && dxFixed > hDistance || !!vDistance && dyFixed > vDistance;
7114
7388
  if (hDistance) {
7115
- particle.velocity.x = particle.velocity.y / 2 - particle.velocity.x;
7389
+ particle.velocity.x = particle.velocity.y * 0.5 - particle.velocity.x;
7116
7390
  }
7117
7391
  if (vDistance) {
7118
- particle.velocity.y = particle.velocity.x / 2 - particle.velocity.y;
7392
+ particle.velocity.y = particle.velocity.x * 0.5 - particle.velocity.y;
7119
7393
  }
7120
7394
  } else if ((!hDistance || dxFixed < hDistance) && (!vDistance || dyFixed < vDistance) && particle.misplaced) {
7121
7395
  particle.misplaced = false;
@@ -7173,15 +7447,16 @@ function spin(particle, moveSpeed) {
7173
7447
  particle.position.x = particle.spin.center.x + particle.spin.radius * updateFunc.x(particle.spin.angle);
7174
7448
  particle.position.y = particle.spin.center.y + particle.spin.radius * updateFunc.y(particle.spin.angle);
7175
7449
  particle.spin.radius += particle.spin.acceleration;
7176
- const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height);
7177
- if (particle.spin.radius > maxCanvasSize / 2) {
7178
- particle.spin.radius = maxCanvasSize / 2;
7450
+ const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height),
7451
+ halfMaxSize = maxCanvasSize * 0.5;
7452
+ if (particle.spin.radius > halfMaxSize) {
7453
+ particle.spin.radius = halfMaxSize;
7179
7454
  particle.spin.acceleration *= -1;
7180
7455
  } else if (particle.spin.radius < 0) {
7181
7456
  particle.spin.radius = 0;
7182
7457
  particle.spin.acceleration *= -1;
7183
7458
  }
7184
- particle.spin.angle += moveSpeed / 100 * (1 - particle.spin.radius / maxCanvasSize);
7459
+ particle.spin.angle += moveSpeed * 0.01 * (1 - particle.spin.radius / maxCanvasSize);
7185
7460
  }
7186
7461
  function applyPath(particle, delta) {
7187
7462
  const particlesOptions = particle.options,
@@ -7225,8 +7500,8 @@ class BaseMover {
7225
7500
  y: 50
7226
7501
  },
7227
7502
  spinCenter = {
7228
- x: spinPos.x / 100 * container.canvas.size.width,
7229
- y: spinPos.y / 100 * container.canvas.size.height
7503
+ x: spinPos.x * 0.01 * container.canvas.size.width,
7504
+ y: spinPos.y * 0.01 * container.canvas.size.height
7230
7505
  },
7231
7506
  pos = particle.getPosition(),
7232
7507
  distance = getDistance(pos, spinCenter),
@@ -7285,7 +7560,12 @@ async function loadBaseMover(engine, refresh = true) {
7285
7560
  ;// CONCATENATED MODULE: ../../shapes/circle/dist/browser/CircleDrawer.js
7286
7561
 
7287
7562
  class CircleDrawer {
7288
- draw(context, particle, radius) {
7563
+ draw(data) {
7564
+ const {
7565
+ context,
7566
+ particle,
7567
+ radius
7568
+ } = data;
7289
7569
  if (!particle.circleRange) {
7290
7570
  particle.circleRange = {
7291
7571
  min: 0,
@@ -7544,7 +7824,7 @@ function bounceHorizontal(data) {
7544
7824
  const velocity = data.particle.velocity.x;
7545
7825
  let bounced = false;
7546
7826
  if (data.direction === "right" && data.bounds.right >= data.canvasSize.width && velocity > 0 || data.direction === "left" && data.bounds.left <= 0 && velocity < 0) {
7547
- const newVelocity = getValue(data.particle.options.bounce.horizontal);
7827
+ const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
7548
7828
  data.particle.velocity.x *= -newVelocity;
7549
7829
  bounced = true;
7550
7830
  }
@@ -7573,7 +7853,7 @@ function bounceVertical(data) {
7573
7853
  const velocity = data.particle.velocity.y;
7574
7854
  let bounced = false;
7575
7855
  if (data.direction === "bottom" && data.bounds.bottom >= data.canvasSize.height && velocity > 0 || data.direction === "top" && data.bounds.top <= 0 && velocity < 0) {
7576
- const newVelocity = getValue(data.particle.options.bounce.vertical);
7856
+ const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
7577
7857
  data.particle.velocity.y *= -newVelocity;
7578
7858
  bounced = true;
7579
7859
  }
@@ -8023,6 +8303,7 @@ class Attract {
8023
8303
  ;// CONCATENATED MODULE: ../../interactions/external/attract/dist/browser/Attractor.js
8024
8304
 
8025
8305
 
8306
+ const attractMode = "attract";
8026
8307
  class Attractor extends ExternalInteractorBase {
8027
8308
  constructor(engine, container) {
8028
8309
  super(container);
@@ -8094,7 +8375,7 @@ class Attractor extends ExternalInteractorBase {
8094
8375
  this.handleClickMode = mode => {
8095
8376
  const options = this.container.actualOptions,
8096
8377
  attract = options.interactivity.modes.attract;
8097
- if (!attract || mode !== "attract") {
8378
+ if (!attract || mode !== attractMode) {
8098
8379
  return;
8099
8380
  }
8100
8381
  if (!container.attract) {
@@ -8143,9 +8424,9 @@ class Attractor extends ExternalInteractorBase {
8143
8424
  hoverMode = events.onHover.mode,
8144
8425
  clickEnabled = events.onClick.enable,
8145
8426
  clickMode = events.onClick.mode;
8146
- if (mouseMoveStatus && hoverEnabled && isInArray("attract", hoverMode)) {
8427
+ if (mouseMoveStatus && hoverEnabled && isInArray(attractMode, hoverMode)) {
8147
8428
  this._hoverAttract();
8148
- } else if (clickEnabled && isInArray("attract", clickMode)) {
8429
+ } else if (clickEnabled && isInArray(attractMode, clickMode)) {
8149
8430
  this._clickAttract();
8150
8431
  }
8151
8432
  }
@@ -8159,7 +8440,7 @@ class Attractor extends ExternalInteractorBase {
8159
8440
  }
8160
8441
  const hoverMode = events.onHover.mode,
8161
8442
  clickMode = events.onClick.mode;
8162
- return isInArray("attract", hoverMode) || isInArray("attract", clickMode);
8443
+ return isInArray(attractMode, hoverMode) || isInArray(attractMode, clickMode);
8163
8444
  }
8164
8445
  loadModeOptions(options, ...sources) {
8165
8446
  if (!options.attract) {
@@ -8195,6 +8476,7 @@ class Bounce {
8195
8476
  ;// CONCATENATED MODULE: ../../interactions/external/bounce/dist/browser/Bouncer.js
8196
8477
 
8197
8478
 
8479
+ const bounceMode = "bounce";
8198
8480
  class Bouncer extends ExternalInteractorBase {
8199
8481
  constructor(container) {
8200
8482
  super(container);
@@ -8262,10 +8544,10 @@ class Bouncer extends ExternalInteractorBase {
8262
8544
  hoverEnabled = events.onHover.enable,
8263
8545
  hoverMode = events.onHover.mode,
8264
8546
  divs = events.onDiv;
8265
- if (mouseMoveStatus && hoverEnabled && isInArray("bounce", hoverMode)) {
8547
+ if (mouseMoveStatus && hoverEnabled && isInArray(bounceMode, hoverMode)) {
8266
8548
  this._processMouseBounce();
8267
8549
  } else {
8268
- divModeExecute("bounce", divs, (selector, div) => this._singleSelectorBounce(selector, div));
8550
+ divModeExecute(bounceMode, divs, (selector, div) => this._singleSelectorBounce(selector, div));
8269
8551
  }
8270
8552
  }
8271
8553
  isEnabled(particle) {
@@ -8274,7 +8556,7 @@ class Bouncer extends ExternalInteractorBase {
8274
8556
  mouse = container.interactivity.mouse,
8275
8557
  events = (particle?.interactivity ?? options.interactivity).events,
8276
8558
  divs = events.onDiv;
8277
- return mouse.position && events.onHover.enable && isInArray("bounce", events.onHover.mode) || isDivModeEnabled("bounce", divs);
8559
+ return mouse.position && events.onHover.enable && isInArray(bounceMode, events.onHover.mode) || isDivModeEnabled(bounceMode, divs);
8278
8560
  }
8279
8561
  loadModeOptions(options, ...sources) {
8280
8562
  if (!options.bounce) {
@@ -8377,6 +8659,7 @@ function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
8377
8659
 
8378
8660
 
8379
8661
 
8662
+ const bubbleMode = "bubble";
8380
8663
  class Bubbler extends ExternalInteractorBase {
8381
8664
  constructor(container) {
8382
8665
  super(container);
@@ -8613,7 +8896,7 @@ class Bubbler extends ExternalInteractorBase {
8613
8896
  container.bubble = {};
8614
8897
  }
8615
8898
  this.handleClickMode = mode => {
8616
- if (mode !== "bubble") {
8899
+ if (mode !== bubbleMode) {
8617
8900
  return;
8618
8901
  }
8619
8902
  if (!container.bubble) {
@@ -8652,12 +8935,12 @@ class Bubbler extends ExternalInteractorBase {
8652
8935
  clickEnabled = onClick.enable,
8653
8936
  clickMode = onClick.mode,
8654
8937
  divs = events.onDiv;
8655
- if (hoverEnabled && isInArray("bubble", hoverMode)) {
8938
+ if (hoverEnabled && isInArray(bubbleMode, hoverMode)) {
8656
8939
  this._hoverBubble();
8657
- } else if (clickEnabled && isInArray("bubble", clickMode)) {
8940
+ } else if (clickEnabled && isInArray(bubbleMode, clickMode)) {
8658
8941
  this._clickBubble();
8659
8942
  } else {
8660
- divModeExecute("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
8943
+ divModeExecute(bubbleMode, divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
8661
8944
  }
8662
8945
  }
8663
8946
  isEnabled(particle) {
@@ -8670,11 +8953,11 @@ class Bubbler extends ExternalInteractorBase {
8670
8953
  onDiv,
8671
8954
  onHover
8672
8955
  } = events,
8673
- divBubble = isDivModeEnabled("bubble", onDiv);
8956
+ divBubble = isDivModeEnabled(bubbleMode, onDiv);
8674
8957
  if (!(divBubble || onHover.enable && mouse.position || onClick.enable && mouse.clickPosition)) {
8675
8958
  return false;
8676
8959
  }
8677
- return isInArray("bubble", onHover.mode) || isInArray("bubble", onClick.mode) || divBubble;
8960
+ return isInArray(bubbleMode, onHover.mode) || isInArray(bubbleMode, onClick.mode) || divBubble;
8678
8961
  }
8679
8962
  loadModeOptions(options, ...sources) {
8680
8963
  if (!options.bubble) {
@@ -8781,6 +9064,7 @@ function drawConnection(container, p1, p2) {
8781
9064
 
8782
9065
 
8783
9066
 
9067
+ const connectMode = "connect";
8784
9068
  class Connector extends ExternalInteractorBase {
8785
9069
  constructor(container) {
8786
9070
  super(container);
@@ -8828,7 +9112,7 @@ class Connector extends ExternalInteractorBase {
8828
9112
  if (!(events.onHover.enable && mouse.position)) {
8829
9113
  return false;
8830
9114
  }
8831
- return isInArray("connect", events.onHover.mode);
9115
+ return isInArray(connectMode, events.onHover.mode);
8832
9116
  }
8833
9117
  loadModeOptions(options, ...sources) {
8834
9118
  if (!options.connect) {
@@ -8922,6 +9206,7 @@ function drawGrab(container, particle, lineColor, opacity, mousePos) {
8922
9206
 
8923
9207
 
8924
9208
 
9209
+ const grabMode = "grab";
8925
9210
  class Grabber extends ExternalInteractorBase {
8926
9211
  constructor(container) {
8927
9212
  super(container);
@@ -8979,7 +9264,7 @@ class Grabber extends ExternalInteractorBase {
8979
9264
  const container = this.container,
8980
9265
  mouse = container.interactivity.mouse,
8981
9266
  events = (particle?.interactivity ?? container.actualOptions.interactivity).events;
8982
- return events.onHover.enable && !!mouse.position && isInArray("grab", events.onHover.mode);
9267
+ return events.onHover.enable && !!mouse.position && isInArray(grabMode, events.onHover.mode);
8983
9268
  }
8984
9269
  loadModeOptions(options, ...sources) {
8985
9270
  if (!options.grab) {
@@ -9002,11 +9287,12 @@ async function loadExternalGrabInteraction(engine, refresh = true) {
9002
9287
 
9003
9288
  ;// CONCATENATED MODULE: ../../interactions/external/pause/dist/browser/Pauser.js
9004
9289
 
9290
+ const pauseMode = "pause";
9005
9291
  class Pauser extends ExternalInteractorBase {
9006
9292
  constructor(container) {
9007
9293
  super(container);
9008
9294
  this.handleClickMode = mode => {
9009
- if (mode !== "pause") {
9295
+ if (mode !== pauseMode) {
9010
9296
  return;
9011
9297
  }
9012
9298
  const container = this.container;
@@ -9066,11 +9352,12 @@ class Push {
9066
9352
  ;// CONCATENATED MODULE: ../../interactions/external/push/dist/browser/Pusher.js
9067
9353
 
9068
9354
 
9355
+ const pushMode = "push";
9069
9356
  class Pusher extends ExternalInteractorBase {
9070
9357
  constructor(container) {
9071
9358
  super(container);
9072
9359
  this.handleClickMode = mode => {
9073
- if (mode !== "push") {
9360
+ if (mode !== pushMode) {
9074
9361
  return;
9075
9362
  }
9076
9363
  const container = this.container,
@@ -9136,13 +9423,14 @@ class Remove {
9136
9423
  ;// CONCATENATED MODULE: ../../interactions/external/remove/dist/browser/Remover.js
9137
9424
 
9138
9425
 
9426
+ const removeMode = "remove";
9139
9427
  class Remover extends ExternalInteractorBase {
9140
9428
  constructor(container) {
9141
9429
  super(container);
9142
9430
  this.handleClickMode = mode => {
9143
9431
  const container = this.container,
9144
9432
  options = container.actualOptions;
9145
- if (!options.interactivity.modes.remove || mode !== "remove") {
9433
+ if (!options.interactivity.modes.remove || mode !== removeMode) {
9146
9434
  return;
9147
9435
  }
9148
9436
  const removeNb = getRangeValue(options.interactivity.modes.remove.quantity);
@@ -9243,6 +9531,7 @@ class Repulse extends RepulseBase {
9243
9531
  ;// CONCATENATED MODULE: ../../interactions/external/repulse/dist/browser/Repulser.js
9244
9532
 
9245
9533
 
9534
+ const repulseMode = "repulse";
9246
9535
  class Repulser extends ExternalInteractorBase {
9247
9536
  constructor(engine, container) {
9248
9537
  super(container);
@@ -9315,14 +9604,21 @@ class Repulser extends ExternalInteractorBase {
9315
9604
  if (!repulseOptions) {
9316
9605
  return;
9317
9606
  }
9607
+ const {
9608
+ easing,
9609
+ speed,
9610
+ factor,
9611
+ maxSpeed
9612
+ } = repulseOptions,
9613
+ easingFunc = getEasing(easing),
9614
+ velocity = (divRepulse?.speed ?? speed) * factor;
9318
9615
  for (const particle of query) {
9319
9616
  const {
9320
9617
  dx,
9321
9618
  dy,
9322
9619
  distance
9323
9620
  } = getDistances(particle.position, position),
9324
- velocity = (divRepulse?.speed ?? repulseOptions.speed) * repulseOptions.factor,
9325
- repulseFactor = clamp(getEasing(repulseOptions.easing)(1 - distance / repulseRadius) * velocity, 0, repulseOptions.maxSpeed),
9621
+ repulseFactor = clamp(easingFunc(1 - distance / repulseRadius) * velocity, 0, maxSpeed),
9326
9622
  normVec = Vector.create(distance === 0 ? velocity : dx / distance * repulseFactor, distance === 0 ? velocity : dy / distance * repulseFactor);
9327
9623
  particle.position.addTo(normVec);
9328
9624
  }
@@ -9360,7 +9656,7 @@ class Repulser extends ExternalInteractorBase {
9360
9656
  this.handleClickMode = mode => {
9361
9657
  const options = this.container.actualOptions,
9362
9658
  repulseOpts = options.interactivity.modes.repulse;
9363
- if (!repulseOpts || mode !== "repulse") {
9659
+ if (!repulseOpts || mode !== repulseMode) {
9364
9660
  return;
9365
9661
  }
9366
9662
  if (!container.repulse) {
@@ -9408,12 +9704,12 @@ class Repulser extends ExternalInteractorBase {
9408
9704
  clickEnabled = click.enable,
9409
9705
  clickMode = click.mode,
9410
9706
  divs = events.onDiv;
9411
- if (mouseMoveStatus && hoverEnabled && isInArray("repulse", hoverMode)) {
9707
+ if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
9412
9708
  this._hoverRepulse();
9413
- } else if (clickEnabled && isInArray("repulse", clickMode)) {
9709
+ } else if (clickEnabled && isInArray(repulseMode, clickMode)) {
9414
9710
  this._clickRepulse();
9415
9711
  } else {
9416
- divModeExecute("repulse", divs, (selector, div) => this._singleSelectorRepulse(selector, div));
9712
+ divModeExecute(repulseMode, divs, (selector, div) => this._singleSelectorRepulse(selector, div));
9417
9713
  }
9418
9714
  }
9419
9715
  isEnabled(particle) {
@@ -9424,13 +9720,13 @@ class Repulser extends ExternalInteractorBase {
9424
9720
  divs = events.onDiv,
9425
9721
  hover = events.onHover,
9426
9722
  click = events.onClick,
9427
- divRepulse = isDivModeEnabled("repulse", divs);
9723
+ divRepulse = isDivModeEnabled(repulseMode, divs);
9428
9724
  if (!(divRepulse || hover.enable && mouse.position || click.enable && mouse.clickPosition)) {
9429
9725
  return false;
9430
9726
  }
9431
9727
  const hoverMode = hover.mode,
9432
9728
  clickMode = click.mode;
9433
- return isInArray("repulse", hoverMode) || isInArray("repulse", clickMode) || divRepulse;
9729
+ return isInArray(repulseMode, hoverMode) || isInArray(repulseMode, clickMode) || divRepulse;
9434
9730
  }
9435
9731
  loadModeOptions(options, ...sources) {
9436
9732
  if (!options.repulse) {
@@ -9474,6 +9770,7 @@ class Slow {
9474
9770
  ;// CONCATENATED MODULE: ../../interactions/external/slow/dist/browser/Slower.js
9475
9771
 
9476
9772
 
9773
+ const slowMode = "slow";
9477
9774
  class Slower extends ExternalInteractorBase {
9478
9775
  constructor(container) {
9479
9776
  super(container);
@@ -9497,7 +9794,7 @@ class Slower extends ExternalInteractorBase {
9497
9794
  const container = this.container,
9498
9795
  mouse = container.interactivity.mouse,
9499
9796
  events = (particle?.interactivity ?? container.actualOptions.interactivity).events;
9500
- return events.onHover.enable && !!mouse.position && isInArray("slow", events.onHover.mode);
9797
+ return events.onHover.enable && !!mouse.position && isInArray(slowMode, events.onHover.mode);
9501
9798
  }
9502
9799
  loadModeOptions(options, ...sources) {
9503
9800
  if (!options.slow) {
@@ -10089,8 +10386,15 @@ class ImageDrawer {
10089
10386
  }
10090
10387
  this._engine.images.push(image);
10091
10388
  }
10092
- draw(context, particle, radius, opacity, delta) {
10093
- const image = particle.image,
10389
+ draw(data) {
10390
+ const {
10391
+ context,
10392
+ radius,
10393
+ particle,
10394
+ opacity,
10395
+ delta
10396
+ } = data,
10397
+ image = particle.image,
10094
10398
  element = image?.element;
10095
10399
  if (!image) {
10096
10400
  return;
@@ -10197,8 +10501,11 @@ class ImageDrawer {
10197
10501
  if (!this._engine.images) {
10198
10502
  this._engine.images = [];
10199
10503
  }
10200
- const imageData = particle.shapeData,
10201
- image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);
10504
+ const imageData = particle.shapeData;
10505
+ if (!imageData) {
10506
+ return;
10507
+ }
10508
+ const image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);
10202
10509
  if (!image) {
10203
10510
  this.loadImageShape(imageData).then(() => {
10204
10511
  this.loadShape(particle);
@@ -10213,8 +10520,11 @@ class ImageDrawer {
10213
10520
  this._engine.images = [];
10214
10521
  }
10215
10522
  const images = this._engine.images,
10216
- imageData = particle.shapeData,
10217
- color = particle.getFillColor(),
10523
+ imageData = particle.shapeData;
10524
+ if (!imageData) {
10525
+ return;
10526
+ }
10527
+ const color = particle.getFillColor(),
10218
10528
  image = images.find(t => t.name === imageData.name || t.source === imageData.src);
10219
10529
  if (!image) {
10220
10530
  return;
@@ -10247,16 +10557,16 @@ class ImageDrawer {
10247
10557
  if (!imageRes.ratio) {
10248
10558
  imageRes.ratio = 1;
10249
10559
  }
10250
- const fill = imageData.fill ?? particle.fill,
10251
- close = imageData.close ?? particle.close,
10560
+ const fill = imageData.fill ?? particle.shapeFill,
10561
+ close = imageData.close ?? particle.shapeClose,
10252
10562
  imageShape = {
10253
10563
  image: imageRes,
10254
10564
  fill,
10255
10565
  close
10256
10566
  };
10257
10567
  particle.image = imageShape.image;
10258
- particle.fill = imageShape.fill;
10259
- particle.close = imageShape.close;
10568
+ particle.shapeFill = imageShape.fill;
10569
+ particle.shapeClose = imageShape.close;
10260
10570
  })();
10261
10571
  }
10262
10572
  }
@@ -10389,7 +10699,6 @@ class LifeDelay extends ValueWithRandom {
10389
10699
  class LifeDuration extends ValueWithRandom {
10390
10700
  constructor() {
10391
10701
  super();
10392
- this.random.minimumValue = 0.0001;
10393
10702
  this.sync = false;
10394
10703
  }
10395
10704
  load(data) {
@@ -10526,8 +10835,13 @@ async function loadLifeUpdater(engine, refresh = true) {
10526
10835
  }
10527
10836
  ;// CONCATENATED MODULE: ../../shapes/line/dist/browser/LineDrawer.js
10528
10837
  class LineDrawer {
10529
- draw(context, particle, radius) {
10530
- const shapeData = particle.shapeData;
10838
+ draw(data) {
10839
+ const {
10840
+ context,
10841
+ particle,
10842
+ radius
10843
+ } = data,
10844
+ shapeData = particle.shapeData;
10531
10845
  context.moveTo(-radius / 2, 0);
10532
10846
  context.lineTo(radius / 2, 0);
10533
10847
  context.lineCap = shapeData?.cap ?? "butt";
@@ -10562,8 +10876,8 @@ class ParallaxMover {
10562
10876
  }
10563
10877
  const canvasSize = container.canvas.size,
10564
10878
  canvasCenter = {
10565
- x: canvasSize.width / 2,
10566
- y: canvasSize.height / 2
10879
+ x: canvasSize.width * 0.5,
10880
+ y: canvasSize.height * 0.5
10567
10881
  },
10568
10882
  parallaxSmooth = parallaxOptions.smooth,
10569
10883
  factor = particle.getRadius() / parallaxForce,
@@ -10592,8 +10906,11 @@ class Attractor_Attractor extends ParticlesInteractorBase {
10592
10906
  clear() {}
10593
10907
  init() {}
10594
10908
  async interact(p1) {
10595
- const container = this.container,
10596
- distance = p1.retina.attractDistance ?? container.retina.attractDistance,
10909
+ const container = this.container;
10910
+ if (p1.attractDistance === undefined) {
10911
+ p1.attractDistance = getRangeValue(p1.options.move.attract.distance) * container.retina.pixelRatio;
10912
+ }
10913
+ const distance = p1.attractDistance,
10597
10914
  pos1 = p1.getPosition(),
10598
10915
  query = container.particles.quadTree.queryCircle(pos1, distance);
10599
10916
  for (const p2 of query) {
@@ -11010,6 +11327,13 @@ async function loadLinksInteraction(engine, refresh = true) {
11010
11327
  }
11011
11328
  ;// CONCATENATED MODULE: ../../interactions/particles/links/dist/browser/Utils.js
11012
11329
 
11330
+ function drawTriangle(context, p1, p2, p3) {
11331
+ context.beginPath();
11332
+ context.moveTo(p1.x, p1.y);
11333
+ context.lineTo(p2.x, p2.y);
11334
+ context.lineTo(p3.x, p3.y);
11335
+ context.closePath();
11336
+ }
11013
11337
  function drawLinkLine(params) {
11014
11338
  let drawn = false;
11015
11339
  const {
@@ -11343,8 +11667,13 @@ async function loadParticlesLinksInteraction(engine, refresh = true) {
11343
11667
  ;// CONCATENATED MODULE: ../../shapes/polygon/dist/browser/PolygonDrawerBase.js
11344
11668
 
11345
11669
  class PolygonDrawerBase {
11346
- draw(context, particle, radius) {
11347
- const start = this.getCenter(particle, radius),
11670
+ draw(data) {
11671
+ const {
11672
+ context,
11673
+ particle,
11674
+ radius
11675
+ } = data,
11676
+ start = this.getCenter(particle, radius),
11348
11677
  side = this.getSidesData(particle, radius),
11349
11678
  sideCount = side.count.numerator * side.count.denominator,
11350
11679
  decimalSides = side.count.numerator / side.count.denominator,
@@ -11578,8 +11907,12 @@ async function loadRotateUpdater(engine, refresh = true) {
11578
11907
  ;// CONCATENATED MODULE: ../../shapes/square/dist/browser/SquareDrawer.js
11579
11908
  const fixFactor = Math.sqrt(2);
11580
11909
  class SquareDrawer {
11581
- draw(context, particle, radius) {
11582
- const fixedRadius = radius / fixFactor,
11910
+ draw(data) {
11911
+ const {
11912
+ context,
11913
+ radius
11914
+ } = data,
11915
+ fixedRadius = radius / fixFactor,
11583
11916
  fixedDiameter = fixedRadius * 2;
11584
11917
  context.rect(-fixedRadius, -fixedRadius, fixedDiameter, fixedDiameter);
11585
11918
  }
@@ -11595,8 +11928,13 @@ async function loadSquareShape(engine, refresh = true) {
11595
11928
  ;// CONCATENATED MODULE: ../../shapes/star/dist/browser/StarDrawer.js
11596
11929
 
11597
11930
  class StarDrawer {
11598
- draw(context, particle, radius) {
11599
- const sides = particle.sides,
11931
+ draw(data) {
11932
+ const {
11933
+ context,
11934
+ particle,
11935
+ radius
11936
+ } = data,
11937
+ sides = particle.sides,
11600
11938
  inset = particle.starInset ?? 2;
11601
11939
  context.moveTo(0, 0 - radius);
11602
11940
  for (let i = 0; i < sides; i++) {
@@ -11732,11 +12070,31 @@ async function loadStrokeColorUpdater(engine, refresh = true) {
11732
12070
  }
11733
12071
  ;// CONCATENATED MODULE: ../../shapes/text/dist/browser/TextDrawer.js
11734
12072
 
11735
- const validTypes = ["text", "character", "char"];
12073
+ const validTypes = ["text", "character", "char", "multiline-text"];
11736
12074
  class TextDrawer {
11737
- draw(context, particle, radius, opacity) {
11738
- const character = particle.shapeData;
11739
- if (character === undefined) {
12075
+ constructor() {
12076
+ this._drawLine = (context, line, radius, opacity, index, fill) => {
12077
+ const offsetX = line.length * radius / 2,
12078
+ pos = {
12079
+ x: -offsetX,
12080
+ y: radius / 2
12081
+ };
12082
+ if (fill) {
12083
+ context.fillText(line, pos.x, pos.y + radius * 2 * index);
12084
+ } else {
12085
+ context.strokeText(line, pos.x, pos.y + radius * 2 * index);
12086
+ }
12087
+ };
12088
+ }
12089
+ draw(data) {
12090
+ const {
12091
+ context,
12092
+ particle,
12093
+ radius,
12094
+ opacity
12095
+ } = data,
12096
+ character = particle.shapeData;
12097
+ if (!character) {
11740
12098
  return;
11741
12099
  }
11742
12100
  const textData = character.value;
@@ -11751,24 +12109,18 @@ class TextDrawer {
11751
12109
  weight = character.weight ?? "400",
11752
12110
  size = Math.round(radius) * 2,
11753
12111
  font = character.font ?? "Verdana",
11754
- fill = particle.fill,
11755
- offsetX = text.length * radius / 2;
12112
+ fill = particle.shapeFill;
12113
+ const lines = text?.split("\n");
12114
+ if (!lines) {
12115
+ return;
12116
+ }
11756
12117
  context.font = `${style} ${weight} ${size}px "${font}"`;
11757
- const pos = {
11758
- x: -offsetX,
11759
- y: radius / 2
11760
- };
11761
12118
  context.globalAlpha = opacity;
11762
- if (fill) {
11763
- context.fillText(text, pos.x, pos.y);
11764
- } else {
11765
- context.strokeText(text, pos.x, pos.y);
12119
+ for (let i = 0; i < lines.length; i++) {
12120
+ this._drawLine(context, lines[i], radius, opacity, i, fill);
11766
12121
  }
11767
12122
  context.globalAlpha = 1;
11768
12123
  }
11769
- getSidesCount() {
11770
- return 12;
11771
- }
11772
12124
  async init(container) {
11773
12125
  const options = container.actualOptions;
11774
12126
  if (validTypes.find(t => isInArray(t, options.particles.shape.type))) {
@@ -12239,6 +12591,8 @@ async function loadWobbleUpdater(engine, refresh = true) {
12239
12591
 
12240
12592
 
12241
12593
 
12594
+
12595
+
12242
12596
  async function loadFull(engine, refresh = true) {
12243
12597
  await loadDestroyUpdater(engine, false);
12244
12598
  await loadRollUpdater(engine, false);
@@ -12248,6 +12602,8 @@ async function loadFull(engine, refresh = true) {
12248
12602
  await loadExternalTrailInteraction(engine, false);
12249
12603
  await loadAbsorbersPlugin(engine, false);
12250
12604
  await loadEmittersPlugin(engine, false);
12605
+ await loadEmittersShapeCircle(engine, false);
12606
+ await loadEmittersShapeSquare(engine, false);
12251
12607
  await loadSlim(engine, refresh);
12252
12608
  }
12253
12609
  ;// CONCATENATED MODULE: ./dist/browser/bundle.js