@tsparticles/confetti 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),
@@ -141,13 +142,13 @@ __webpack_require__.d(__webpack_exports__, {
141
142
  deepExtend: () => (/* reexport */ deepExtend),
142
143
  divMode: () => (/* reexport */ divMode),
143
144
  divModeExecute: () => (/* reexport */ divModeExecute),
145
+ drawEffect: () => (/* reexport */ drawEffect),
144
146
  drawLine: () => (/* reexport */ drawLine),
145
147
  drawParticle: () => (/* reexport */ drawParticle),
146
148
  drawParticlePlugin: () => (/* reexport */ drawParticlePlugin),
147
149
  drawPlugin: () => (/* reexport */ drawPlugin),
148
150
  drawShape: () => (/* reexport */ drawShape),
149
- drawShapeAfterEffect: () => (/* reexport */ drawShapeAfterEffect),
150
- drawTriangle: () => (/* reexport */ drawTriangle),
151
+ drawShapeAfterDraw: () => (/* reexport */ drawShapeAfterDraw),
151
152
  errorPrefix: () => (/* reexport */ errorPrefix),
152
153
  executeOnSingleOrMultiple: () => (/* reexport */ executeOnSingleOrMultiple),
153
154
  findItemFromSingleOrMultiple: () => (/* reexport */ findItemFromSingleOrMultiple),
@@ -171,7 +172,6 @@ __webpack_require__.d(__webpack_exports__, {
171
172
  getSize: () => (/* reexport */ getSize),
172
173
  getStyleFromHsl: () => (/* reexport */ getStyleFromHsl),
173
174
  getStyleFromRgb: () => (/* reexport */ getStyleFromRgb),
174
- getValue: () => (/* reexport */ getValue),
175
175
  hasMatchMedia: () => (/* reexport */ hasMatchMedia),
176
176
  hslToRgb: () => (/* reexport */ hslToRgb),
177
177
  hslaToRgba: () => (/* reexport */ hslaToRgba),
@@ -206,6 +206,7 @@ __webpack_require__.d(__webpack_exports__, {
206
206
  rectBounce: () => (/* reexport */ rectBounce),
207
207
  resizeEvent: () => (/* reexport */ resizeEvent),
208
208
  rgbToHsl: () => (/* reexport */ rgbToHsl),
209
+ safeIntersectionObserver: () => (/* reexport */ safeIntersectionObserver),
209
210
  safeMatchMedia: () => (/* reexport */ safeMatchMedia),
210
211
  safeMutationObserver: () => (/* reexport */ safeMutationObserver),
211
212
  setLogger: () => (/* reexport */ setLogger),
@@ -409,17 +410,6 @@ function setRangeValue(source, value) {
409
410
  max: Math.max(max, value)
410
411
  } : setRangeValue(min, max);
411
412
  }
412
- function getValue(options) {
413
- const random = options.random,
414
- {
415
- enable,
416
- minimumValue
417
- } = isBoolean(random) ? {
418
- enable: random,
419
- minimumValue: 0
420
- } : random;
421
- return enable ? getRangeValue(setRangeValue(options.value, minimumValue)) : getRangeValue(options.value);
422
- }
423
413
  function getDistances(pointA, pointB) {
424
414
  const dx = pointA.x - pointB.x,
425
415
  dy = pointA.y - pointB.y;
@@ -438,21 +428,21 @@ function getParticleDirectionAngle(direction, position, center) {
438
428
  }
439
429
  switch (direction) {
440
430
  case "top":
441
- return -Math.PI / 2;
431
+ return -Math.PI * 0.5;
442
432
  case "top-right":
443
- return -Math.PI / 4;
433
+ return -Math.PI * 0.25;
444
434
  case "right":
445
435
  return 0;
446
436
  case "bottom-right":
447
- return Math.PI / 4;
437
+ return Math.PI * 0.25;
448
438
  case "bottom":
449
- return Math.PI / 2;
439
+ return Math.PI * 0.5;
450
440
  case "bottom-left":
451
- return 3 * Math.PI / 4;
441
+ return Math.PI * 0.75;
452
442
  case "left":
453
443
  return Math.PI;
454
444
  case "top-left":
455
- return -3 * Math.PI / 4;
445
+ return -Math.PI * 0.75;
456
446
  case "inside":
457
447
  return Math.atan2(center.y - position.y, center.x - position.x);
458
448
  case "outside":
@@ -548,7 +538,7 @@ function rectSideBounce(data) {
548
538
  if (pOtherSide.min < rectOtherSide.min || pOtherSide.min > rectOtherSide.max || pOtherSide.max < rectOtherSide.min || pOtherSide.max > rectOtherSide.max) {
549
539
  return res;
550
540
  }
551
- 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) {
541
+ 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) {
552
542
  res.velocity = velocity * -factor;
553
543
  res.bounced = true;
554
544
  }
@@ -572,6 +562,12 @@ function safeMatchMedia(query) {
572
562
  }
573
563
  return matchMedia(query);
574
564
  }
565
+ function safeIntersectionObserver(callback) {
566
+ if (isSsr() || typeof IntersectionObserver === "undefined") {
567
+ return;
568
+ }
569
+ return new IntersectionObserver(callback);
570
+ }
575
571
  function safeMutationObserver(callback) {
576
572
  if (isSsr() || typeof MutationObserver === "undefined") {
577
573
  return;
@@ -678,7 +674,7 @@ function circleBounceDataFromParticle(p) {
678
674
  radius: p.getRadius(),
679
675
  mass: p.getMass(),
680
676
  velocity: p.velocity,
681
- factor: Vector.create(getValue(p.options.bounce.horizontal), getValue(p.options.bounce.vertical))
677
+ factor: Vector.create(getRangeValue(p.options.bounce.horizontal.value), getRangeValue(p.options.bounce.vertical.value))
682
678
  };
683
679
  }
684
680
  function circleBounce(p1, p2) {
@@ -712,6 +708,7 @@ function rectBounce(particle, divBounds) {
712
708
  const pPos = particle.getPosition(),
713
709
  size = particle.getRadius(),
714
710
  bounds = calculateBounds(pPos, size),
711
+ bounceOptions = particle.options.bounce,
715
712
  resH = rectSideBounce({
716
713
  pSide: {
717
714
  min: bounds.left,
@@ -730,7 +727,7 @@ function rectBounce(particle, divBounds) {
730
727
  max: divBounds.bottom
731
728
  },
732
729
  velocity: particle.velocity.x,
733
- factor: getValue(particle.options.bounce.horizontal)
730
+ factor: getRangeValue(bounceOptions.horizontal.value)
734
731
  });
735
732
  if (resH.bounced) {
736
733
  if (resH.velocity !== undefined) {
@@ -758,7 +755,7 @@ function rectBounce(particle, divBounds) {
758
755
  max: divBounds.right
759
756
  },
760
757
  velocity: particle.velocity.y,
761
- factor: getValue(particle.options.bounce.vertical)
758
+ factor: getRangeValue(bounceOptions.vertical.value)
762
759
  });
763
760
  if (resV.bounced) {
764
761
  if (resV.velocity !== undefined) {
@@ -885,24 +882,6 @@ const randomColorValue = "random",
885
882
  function addColorManager(manager) {
886
883
  colorManagers.set(manager.key, manager);
887
884
  }
888
- function hue2rgb(p, q, t) {
889
- if (t < 0) {
890
- t += 1;
891
- }
892
- if (t > 1) {
893
- t -= 1;
894
- }
895
- if (t < 1 / 6) {
896
- return p + (q - p) * 6 * t;
897
- }
898
- if (t < 1 / 2) {
899
- return q;
900
- }
901
- if (t < 2 / 3) {
902
- return p + (q - p) * (2 / 3 - t) * 6;
903
- }
904
- return p;
905
- }
906
885
  function stringToRgba(input) {
907
886
  for (const [, manager] of colorManagers) {
908
887
  if (input.startsWith(manager.stringPrefix)) {
@@ -982,7 +961,7 @@ function rgbToHsl(color) {
982
961
  min = Math.min(r1, g1, b1),
983
962
  res = {
984
963
  h: 0,
985
- l: (max + min) / 2,
964
+ l: (max + min) * 0.5,
986
965
  s: 0
987
966
  };
988
967
  if (max !== min) {
@@ -1007,29 +986,48 @@ function stringToRgb(input) {
1007
986
  return stringToRgba(input);
1008
987
  }
1009
988
  function hslToRgb(hsl) {
1010
- const result = {
1011
- b: 0,
1012
- g: 0,
1013
- r: 0
1014
- },
1015
- hslPercent = {
1016
- h: hsl.h / 360,
1017
- l: hsl.l / 100,
1018
- s: hsl.s / 100
989
+ const h = (hsl.h % 360 + 360) % 360,
990
+ s = Math.max(0, Math.min(100, hsl.s)),
991
+ l = Math.max(0, Math.min(100, hsl.l)),
992
+ hNormalized = h / 360,
993
+ sNormalized = s / 100,
994
+ lNormalized = l / 100;
995
+ if (s === 0) {
996
+ const grayscaleValue = Math.round(lNormalized * 255);
997
+ return {
998
+ r: grayscaleValue,
999
+ g: grayscaleValue,
1000
+ b: grayscaleValue
1019
1001
  };
1020
- if (!hslPercent.s) {
1021
- result.r = result.g = result.b = hslPercent.l;
1022
- } else {
1023
- const q = hslPercent.l < 0.5 ? hslPercent.l * (1 + hslPercent.s) : hslPercent.l + hslPercent.s - hslPercent.l * hslPercent.s,
1024
- p = 2 * hslPercent.l - q;
1025
- result.r = hue2rgb(p, q, hslPercent.h + 1 / 3);
1026
- result.g = hue2rgb(p, q, hslPercent.h);
1027
- result.b = hue2rgb(p, q, hslPercent.h - 1 / 3);
1028
1002
  }
1029
- result.r = Math.floor(result.r * 255);
1030
- result.g = Math.floor(result.g * 255);
1031
- result.b = Math.floor(result.b * 255);
1032
- return result;
1003
+ const channel = (temp1, temp2, temp3) => {
1004
+ if (temp3 < 0) {
1005
+ temp3 += 1;
1006
+ }
1007
+ if (temp3 > 1) {
1008
+ temp3 -= 1;
1009
+ }
1010
+ if (temp3 * 6 < 1) {
1011
+ return temp1 + (temp2 - temp1) * 6 * temp3;
1012
+ }
1013
+ if (temp3 * 2 < 1) {
1014
+ return temp2;
1015
+ }
1016
+ if (temp3 * 3 < 2) {
1017
+ return temp1 + (temp2 - temp1) * (2 / 3 - temp3) * 6;
1018
+ }
1019
+ return temp1;
1020
+ },
1021
+ temp1 = lNormalized < 0.5 ? lNormalized * (1 + sNormalized) : lNormalized + sNormalized - lNormalized * sNormalized,
1022
+ temp2 = 2 * lNormalized - temp1,
1023
+ red = Math.min(255, 255 * channel(temp2, temp1, hNormalized + 1 / 3)),
1024
+ green = Math.min(255, 255 * channel(temp2, temp1, hNormalized)),
1025
+ blue = Math.min(255, 255 * channel(temp2, temp1, hNormalized - 1 / 3));
1026
+ return {
1027
+ r: Math.round(red),
1028
+ g: Math.round(green),
1029
+ b: Math.round(blue)
1030
+ };
1033
1031
  }
1034
1032
  function hslaToRgba(hsla) {
1035
1033
  const rgbResult = hslToRgb(hsla);
@@ -1163,13 +1161,6 @@ function drawLine(context, begin, end) {
1163
1161
  context.lineTo(end.x, end.y);
1164
1162
  context.closePath();
1165
1163
  }
1166
- function drawTriangle(context, p1, p2, p3) {
1167
- context.beginPath();
1168
- context.moveTo(p1.x, p1.y);
1169
- context.lineTo(p2.x, p2.y);
1170
- context.lineTo(p3.x, p3.y);
1171
- context.closePath();
1172
- }
1173
1164
  function paintBase(context, dimension, baseColor) {
1174
1165
  context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1175
1166
  context.fillRect(0, 0, dimension.width, dimension.height);
@@ -1212,7 +1203,6 @@ function drawParticle(data) {
1212
1203
  d: rotateData.cos * (transform.d ?? 1)
1213
1204
  };
1214
1205
  context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1215
- context.beginPath();
1216
1206
  if (backgroundMask) {
1217
1207
  context.globalCompositeOperation = composite;
1218
1208
  }
@@ -1231,39 +1221,104 @@ function drawParticle(data) {
1231
1221
  if (colorStyles.stroke) {
1232
1222
  context.strokeStyle = colorStyles.stroke;
1233
1223
  }
1234
- drawShape(container, context, particle, radius, opacity, delta);
1224
+ const drawData = {
1225
+ container,
1226
+ context,
1227
+ particle,
1228
+ radius,
1229
+ opacity,
1230
+ delta
1231
+ };
1232
+ context.beginPath();
1233
+ drawShape(drawData);
1234
+ if (particle.shapeClose) {
1235
+ context.closePath();
1236
+ }
1235
1237
  if (strokeWidth > 0) {
1236
1238
  context.stroke();
1237
1239
  }
1238
- if (particle.close) {
1239
- context.closePath();
1240
- }
1241
- if (particle.fill) {
1240
+ if (particle.shapeFill) {
1242
1241
  context.fill();
1243
1242
  }
1244
- drawShapeAfterEffect(container, context, particle, radius, opacity, delta);
1243
+ drawShapeAfterDraw(drawData);
1244
+ drawEffect(drawData);
1245
1245
  context.globalCompositeOperation = "source-over";
1246
1246
  context.setTransform(1, 0, 0, 1, 0, 0);
1247
1247
  }
1248
- function drawShape(container, context, particle, radius, opacity, delta) {
1248
+ function drawEffect(data) {
1249
+ const {
1250
+ container,
1251
+ context,
1252
+ particle,
1253
+ radius,
1254
+ opacity,
1255
+ delta
1256
+ } = data;
1257
+ if (!particle.effect) {
1258
+ return;
1259
+ }
1260
+ const drawer = container.effectDrawers.get(particle.effect);
1261
+ if (!drawer) {
1262
+ return;
1263
+ }
1264
+ drawer.draw({
1265
+ context,
1266
+ particle,
1267
+ radius,
1268
+ opacity,
1269
+ delta,
1270
+ pixelRatio: container.retina.pixelRatio
1271
+ });
1272
+ }
1273
+ function drawShape(data) {
1274
+ const {
1275
+ container,
1276
+ context,
1277
+ particle,
1278
+ radius,
1279
+ opacity,
1280
+ delta
1281
+ } = data;
1249
1282
  if (!particle.shape) {
1250
1283
  return;
1251
1284
  }
1252
- const drawer = container.drawers.get(particle.shape);
1285
+ const drawer = container.shapeDrawers.get(particle.shape);
1253
1286
  if (!drawer) {
1254
1287
  return;
1255
1288
  }
1256
- drawer.draw(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1289
+ drawer.draw({
1290
+ context,
1291
+ particle,
1292
+ radius,
1293
+ opacity,
1294
+ delta,
1295
+ pixelRatio: container.retina.pixelRatio
1296
+ });
1257
1297
  }
1258
- function drawShapeAfterEffect(container, context, particle, radius, opacity, delta) {
1298
+ function drawShapeAfterDraw(data) {
1299
+ const {
1300
+ container,
1301
+ context,
1302
+ particle,
1303
+ radius,
1304
+ opacity,
1305
+ delta
1306
+ } = data;
1259
1307
  if (!particle.shape) {
1260
1308
  return;
1261
1309
  }
1262
- const drawer = container.drawers.get(particle.shape);
1263
- if (!drawer || !drawer.afterEffect) {
1310
+ const drawer = container.shapeDrawers.get(particle.shape);
1311
+ if (!drawer || !drawer.afterDraw) {
1264
1312
  return;
1265
1313
  }
1266
- drawer.afterEffect(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1314
+ drawer.afterDraw({
1315
+ context,
1316
+ particle,
1317
+ radius,
1318
+ opacity,
1319
+ delta,
1320
+ pixelRatio: container.retina.pixelRatio
1321
+ });
1267
1322
  }
1268
1323
  function drawPlugin(context, plugin, delta) {
1269
1324
  if (!plugin.draw) {
@@ -1710,10 +1765,10 @@ class Canvas {
1710
1765
  this.element.width = size.width = this.element.offsetWidth * pxRatio;
1711
1766
  this.element.height = size.height = this.element.offsetHeight * pxRatio;
1712
1767
  if (this.container.started) {
1713
- this.resizeFactor = {
1768
+ container.particles.setResizeFactor({
1714
1769
  width: size.width / oldSize.width,
1715
1770
  height: size.height / oldSize.height
1716
- };
1771
+ });
1717
1772
  }
1718
1773
  return true;
1719
1774
  }
@@ -2183,10 +2238,10 @@ class BackgroundMask {
2183
2238
  this.composite = data.composite;
2184
2239
  }
2185
2240
  if (data.cover !== undefined) {
2186
- const cover = data.cover;
2187
- const color = isString(data.cover) ? {
2188
- color: data.cover
2189
- } : data.cover;
2241
+ const cover = data.cover,
2242
+ color = isString(data.cover) ? {
2243
+ color: data.cover
2244
+ } : data.cover;
2190
2245
  this.cover.load(cover.color !== undefined ? cover : {
2191
2246
  color: color
2192
2247
  });
@@ -2488,17 +2543,16 @@ class Theme {
2488
2543
  }
2489
2544
  }
2490
2545
  }
2491
- ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/ColorAnimation.js
2546
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/AnimationOptions.js
2492
2547
 
2493
- class ColorAnimation {
2548
+ class AnimationOptions {
2494
2549
  constructor() {
2495
2550
  this.count = 0;
2496
2551
  this.enable = false;
2497
- this.offset = 0;
2498
2552
  this.speed = 1;
2499
- this.delay = 0;
2500
2553
  this.decay = 0;
2501
- this.sync = true;
2554
+ this.delay = 0;
2555
+ this.sync = false;
2502
2556
  }
2503
2557
  load(data) {
2504
2558
  if (!data) {
@@ -2510,9 +2564,6 @@ class ColorAnimation {
2510
2564
  if (data.enable !== undefined) {
2511
2565
  this.enable = data.enable;
2512
2566
  }
2513
- if (data.offset !== undefined) {
2514
- this.offset = setRangeValue(data.offset);
2515
- }
2516
2567
  if (data.speed !== undefined) {
2517
2568
  this.speed = setRangeValue(data.speed);
2518
2569
  }
@@ -2527,6 +2578,44 @@ class ColorAnimation {
2527
2578
  }
2528
2579
  }
2529
2580
  }
2581
+ class RangedAnimationOptions extends AnimationOptions {
2582
+ constructor() {
2583
+ super();
2584
+ this.mode = "auto";
2585
+ this.startValue = "random";
2586
+ }
2587
+ load(data) {
2588
+ super.load(data);
2589
+ if (!data) {
2590
+ return;
2591
+ }
2592
+ if (data.mode !== undefined) {
2593
+ this.mode = data.mode;
2594
+ }
2595
+ if (data.startValue !== undefined) {
2596
+ this.startValue = data.startValue;
2597
+ }
2598
+ }
2599
+ }
2600
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/ColorAnimation.js
2601
+
2602
+
2603
+ class ColorAnimation extends AnimationOptions {
2604
+ constructor() {
2605
+ super();
2606
+ this.offset = 0;
2607
+ this.sync = true;
2608
+ }
2609
+ load(data) {
2610
+ super.load(data);
2611
+ if (!data) {
2612
+ return;
2613
+ }
2614
+ if (data.offset !== undefined) {
2615
+ this.offset = setRangeValue(data.offset);
2616
+ }
2617
+ }
2618
+ }
2530
2619
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/HslAnimation.js
2531
2620
 
2532
2621
  class HslAnimation {
@@ -2614,99 +2703,19 @@ class CollisionsOverlap {
2614
2703
  }
2615
2704
  }
2616
2705
  }
2617
- ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/AnimationOptions.js
2618
-
2619
- class AnimationOptions {
2620
- constructor() {
2621
- this.count = 0;
2622
- this.enable = false;
2623
- this.speed = 1;
2624
- this.decay = 0;
2625
- this.delay = 0;
2626
- this.sync = false;
2627
- }
2628
- load(data) {
2629
- if (!data) {
2630
- return;
2631
- }
2632
- if (data.count !== undefined) {
2633
- this.count = setRangeValue(data.count);
2634
- }
2635
- if (data.enable !== undefined) {
2636
- this.enable = data.enable;
2637
- }
2638
- if (data.speed !== undefined) {
2639
- this.speed = setRangeValue(data.speed);
2640
- }
2641
- if (data.decay !== undefined) {
2642
- this.decay = setRangeValue(data.decay);
2643
- }
2644
- if (data.delay !== undefined) {
2645
- this.delay = setRangeValue(data.delay);
2646
- }
2647
- if (data.sync !== undefined) {
2648
- this.sync = data.sync;
2649
- }
2650
- }
2651
- }
2652
- class RangedAnimationOptions extends AnimationOptions {
2653
- constructor() {
2654
- super();
2655
- this.mode = "auto";
2656
- this.startValue = "random";
2657
- }
2658
- load(data) {
2659
- super.load(data);
2660
- if (!data) {
2661
- return;
2662
- }
2663
- if (data.mode !== undefined) {
2664
- this.mode = data.mode;
2665
- }
2666
- if (data.startValue !== undefined) {
2667
- this.startValue = data.startValue;
2668
- }
2669
- }
2670
- }
2671
- ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Random.js
2672
- class Random {
2673
- constructor() {
2674
- this.enable = false;
2675
- this.minimumValue = 0;
2676
- }
2677
- load(data) {
2678
- if (!data) {
2679
- return;
2680
- }
2681
- if (data.enable !== undefined) {
2682
- this.enable = data.enable;
2683
- }
2684
- if (data.minimumValue !== undefined) {
2685
- this.minimumValue = data.minimumValue;
2686
- }
2687
- }
2688
- }
2689
2706
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/ValueWithRandom.js
2690
2707
 
2691
2708
 
2692
-
2693
-
2694
2709
  class ValueWithRandom {
2695
2710
  constructor() {
2696
- this.random = new Random();
2697
2711
  this.value = 0;
2698
2712
  }
2699
2713
  load(data) {
2700
2714
  if (!data) {
2701
2715
  return;
2702
2716
  }
2703
- if (isBoolean(data.random)) {
2704
- this.random.enable = data.random;
2705
- } else {
2706
- this.random.load(data.random);
2707
- }
2708
2717
  if (data.value !== undefined) {
2709
- this.value = setRangeValue(data.value, this.random.enable ? this.random.minimumValue : undefined);
2718
+ this.value = setRangeValue(data.value);
2710
2719
  }
2711
2720
  }
2712
2721
  }
@@ -2740,7 +2749,6 @@ class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
2740
2749
  class ParticlesBounceFactor extends ValueWithRandom {
2741
2750
  constructor() {
2742
2751
  super();
2743
- this.random.minimumValue = 0.1;
2744
2752
  this.value = 1;
2745
2753
  }
2746
2754
  }
@@ -2791,6 +2799,39 @@ class Collisions {
2791
2799
  this.overlap.load(data.overlap);
2792
2800
  }
2793
2801
  }
2802
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Effect/Effect.js
2803
+
2804
+ class Effect {
2805
+ constructor() {
2806
+ this.close = true;
2807
+ this.fill = true;
2808
+ this.options = {};
2809
+ this.type = [];
2810
+ }
2811
+ load(data) {
2812
+ if (!data) {
2813
+ return;
2814
+ }
2815
+ const options = data.options;
2816
+ if (options !== undefined) {
2817
+ for (const effect in options) {
2818
+ const item = options[effect];
2819
+ if (item) {
2820
+ this.options[effect] = deepExtend(this.options[effect] ?? {}, item);
2821
+ }
2822
+ }
2823
+ }
2824
+ if (data.close !== undefined) {
2825
+ this.close = data.close;
2826
+ }
2827
+ if (data.fill !== undefined) {
2828
+ this.fill = data.fill;
2829
+ }
2830
+ if (data.type !== undefined) {
2831
+ this.type = data.type;
2832
+ }
2833
+ }
2834
+ }
2794
2835
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Move/MoveAngle.js
2795
2836
 
2796
2837
  class MoveAngle {
@@ -3119,11 +3160,10 @@ class OpacityAnimation extends RangedAnimationOptions {
3119
3160
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Opacity/Opacity.js
3120
3161
 
3121
3162
 
3122
- class Opacity extends ValueWithRandom {
3163
+ class Opacity extends RangedAnimationValueWithRandom {
3123
3164
  constructor() {
3124
3165
  super();
3125
3166
  this.animation = new OpacityAnimation();
3126
- this.random.minimumValue = 0.1;
3127
3167
  this.value = 1;
3128
3168
  }
3129
3169
  load(data) {
@@ -3161,12 +3201,31 @@ class ParticlesDensity {
3161
3201
  }
3162
3202
  }
3163
3203
  }
3204
+ ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js
3205
+ class ParticlesNumberLimit {
3206
+ constructor() {
3207
+ this.mode = "delete";
3208
+ this.value = 0;
3209
+ }
3210
+ load(data) {
3211
+ if (!data) {
3212
+ return;
3213
+ }
3214
+ if (data.mode !== undefined) {
3215
+ this.mode = data.mode;
3216
+ }
3217
+ if (data.value !== undefined) {
3218
+ this.value = data.value;
3219
+ }
3220
+ }
3221
+ }
3164
3222
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Number/ParticlesNumber.js
3165
3223
 
3224
+
3166
3225
  class ParticlesNumber {
3167
3226
  constructor() {
3168
3227
  this.density = new ParticlesDensity();
3169
- this.limit = 0;
3228
+ this.limit = new ParticlesNumberLimit();
3170
3229
  this.value = 0;
3171
3230
  }
3172
3231
  load(data) {
@@ -3174,10 +3233,7 @@ class ParticlesNumber {
3174
3233
  return;
3175
3234
  }
3176
3235
  this.density.load(data.density);
3177
- const limit = data.limit;
3178
- if (limit !== undefined) {
3179
- this.limit = limit;
3180
- }
3236
+ this.limit.load(data.limit);
3181
3237
  if (data.value !== undefined) {
3182
3238
  this.value = data.value;
3183
3239
  }
@@ -3272,11 +3328,10 @@ class SizeAnimation extends RangedAnimationOptions {
3272
3328
  ;// CONCATENATED MODULE: ../../engine/dist/browser/Options/Classes/Particles/Size/Size.js
3273
3329
 
3274
3330
 
3275
- class Size extends ValueWithRandom {
3331
+ class Size extends RangedAnimationValueWithRandom {
3276
3332
  constructor() {
3277
3333
  super();
3278
3334
  this.animation = new SizeAnimation();
3279
- this.random.minimumValue = 1;
3280
3335
  this.value = 3;
3281
3336
  }
3282
3337
  load(data) {
@@ -3350,6 +3405,7 @@ class ZIndex extends ValueWithRandom {
3350
3405
 
3351
3406
 
3352
3407
 
3408
+
3353
3409
  class ParticlesOptions {
3354
3410
  constructor(engine, container) {
3355
3411
  this._engine = engine;
@@ -3358,6 +3414,7 @@ class ParticlesOptions {
3358
3414
  this.collisions = new Collisions();
3359
3415
  this.color = new AnimatableColor();
3360
3416
  this.color.value = "#fff";
3417
+ this.effect = new Effect();
3361
3418
  this.groups = {};
3362
3419
  this.move = new Move();
3363
3420
  this.number = new ParticlesNumber();
@@ -3375,6 +3432,7 @@ class ParticlesOptions {
3375
3432
  }
3376
3433
  this.bounce.load(data.bounce);
3377
3434
  this.color.load(AnimatableColor.create(this.color, data.color));
3435
+ this.effect.load(data.effect);
3378
3436
  if (data.groups !== undefined) {
3379
3437
  for (const group in data.groups) {
3380
3438
  const item = data.groups[group];
@@ -3647,7 +3705,27 @@ class InteractionManager {
3647
3705
 
3648
3706
 
3649
3707
 
3650
- const fixOutMode = data => {
3708
+ function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
3709
+ const effectData = effectOptions.options[effect];
3710
+ if (!effectData) {
3711
+ return;
3712
+ }
3713
+ return deepExtend({
3714
+ close: effectOptions.close,
3715
+ fill: effectOptions.fill
3716
+ }, itemFromSingleOrMultiple(effectData, id, reduceDuplicates));
3717
+ }
3718
+ function loadShapeData(shape, shapeOptions, id, reduceDuplicates) {
3719
+ const shapeData = shapeOptions.options[shape];
3720
+ if (!shapeData) {
3721
+ return;
3722
+ }
3723
+ return deepExtend({
3724
+ close: shapeOptions.close,
3725
+ fill: shapeOptions.fill
3726
+ }, itemFromSingleOrMultiple(shapeData, id, reduceDuplicates));
3727
+ }
3728
+ function fixOutMode(data) {
3651
3729
  if (!isInArray(data.outMode, data.checkModes)) {
3652
3730
  return;
3653
3731
  }
@@ -3657,7 +3735,7 @@ const fixOutMode = data => {
3657
3735
  } else if (data.coord < diameter) {
3658
3736
  data.setCb(data.radius);
3659
3737
  }
3660
- };
3738
+ }
3661
3739
  class Particle {
3662
3740
  constructor(engine, id, container, position, overrideOptions, group) {
3663
3741
  this.container = container;
@@ -3715,8 +3793,8 @@ class Particle {
3715
3793
  const rad = Math.PI / 180 * getRangeValue(moveOptions.angle.value),
3716
3794
  radOffset = Math.PI / 180 * getRangeValue(moveOptions.angle.offset),
3717
3795
  range = {
3718
- left: radOffset - rad / 2,
3719
- right: radOffset + rad / 2
3796
+ left: radOffset - rad * 0.5,
3797
+ right: radOffset + rad * 0.5
3720
3798
  };
3721
3799
  if (!moveOptions.straight) {
3722
3800
  res.angle += randomInRange(setRangeValue(range.left, range.right));
@@ -3747,7 +3825,7 @@ class Particle {
3747
3825
  return color;
3748
3826
  }
3749
3827
  const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1,
3750
- backSum = this.roll.horizontal ? Math.PI / 2 : 0,
3828
+ backSum = this.roll.horizontal ? Math.PI * 0.5 : 0,
3751
3829
  rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
3752
3830
  if (!rolled) {
3753
3831
  return color;
@@ -3782,16 +3860,6 @@ class Particle {
3782
3860
  }
3783
3861
  this.offset = Vector.origin;
3784
3862
  };
3785
- this._loadShapeData = (shapeOptions, reduceDuplicates) => {
3786
- const shapeData = shapeOptions.options[this.shape];
3787
- if (!shapeData) {
3788
- return;
3789
- }
3790
- return deepExtend({
3791
- close: shapeOptions.close,
3792
- fill: shapeOptions.fill
3793
- }, itemFromSingleOrMultiple(shapeData, this.id, reduceDuplicates));
3794
- };
3795
3863
  this._engine = engine;
3796
3864
  this.init(id, position, overrideOptions, group);
3797
3865
  }
@@ -3805,18 +3873,12 @@ class Particle {
3805
3873
  const container = this.container,
3806
3874
  pathGenerator = this.pathGenerator;
3807
3875
  for (const [, plugin] of container.plugins) {
3808
- if (plugin.particleDestroyed) {
3809
- plugin.particleDestroyed(this, override);
3810
- }
3876
+ plugin.particleDestroyed && plugin.particleDestroyed(this, override);
3811
3877
  }
3812
3878
  for (const updater of container.particles.updaters) {
3813
- if (updater.particleDestroyed) {
3814
- updater.particleDestroyed(this, override);
3815
- }
3816
- }
3817
- if (pathGenerator) {
3818
- pathGenerator.reset(this);
3879
+ updater.particleDestroyed && updater.particleDestroyed(this, override);
3819
3880
  }
3881
+ pathGenerator && pathGenerator.reset(this);
3820
3882
  }
3821
3883
  draw(delta) {
3822
3884
  const container = this.container,
@@ -3830,7 +3892,7 @@ class Particle {
3830
3892
  return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.color));
3831
3893
  }
3832
3894
  getMass() {
3833
- return this.getRadius() ** 2 * Math.PI / 2;
3895
+ return this.getRadius() ** 2 * Math.PI * 0.5;
3834
3896
  }
3835
3897
  getPosition() {
3836
3898
  return {
@@ -3850,9 +3912,11 @@ class Particle {
3850
3912
  engine = this._engine;
3851
3913
  this.id = id;
3852
3914
  this.group = group;
3853
- this.fill = true;
3915
+ this.effectClose = true;
3916
+ this.effectFill = true;
3917
+ this.shapeClose = true;
3918
+ this.shapeFill = true;
3854
3919
  this.pathRotation = false;
3855
- this.close = true;
3856
3920
  this.lastPathTime = 0;
3857
3921
  this.destroyed = false;
3858
3922
  this.unbreakable = false;
@@ -3866,22 +3930,40 @@ class Particle {
3866
3930
  const pxRatio = container.retina.pixelRatio,
3867
3931
  mainOptions = container.actualOptions,
3868
3932
  particlesOptions = loadParticlesOptions(this._engine, container, mainOptions.particles),
3933
+ effectType = particlesOptions.effect.type,
3869
3934
  shapeType = particlesOptions.shape.type,
3870
3935
  {
3871
3936
  reduceDuplicates
3872
3937
  } = particlesOptions;
3938
+ this.effect = itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
3873
3939
  this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
3874
- const shapeOptions = particlesOptions.shape;
3875
- if (overrideOptions && overrideOptions.shape && overrideOptions.shape.type) {
3876
- const overrideShapeType = overrideOptions.shape.type,
3877
- shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3878
- if (shape) {
3879
- this.shape = shape;
3880
- shapeOptions.load(overrideOptions.shape);
3940
+ const effectOptions = particlesOptions.effect,
3941
+ shapeOptions = particlesOptions.shape;
3942
+ if (overrideOptions) {
3943
+ if (overrideOptions.effect && overrideOptions.effect.type) {
3944
+ const overrideEffectType = overrideOptions.effect.type,
3945
+ effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
3946
+ if (effect) {
3947
+ this.effect = effect;
3948
+ effectOptions.load(overrideOptions.effect);
3949
+ }
3950
+ }
3951
+ if (overrideOptions.shape && overrideOptions.shape.type) {
3952
+ const overrideShapeType = overrideOptions.shape.type,
3953
+ shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
3954
+ if (shape) {
3955
+ this.shape = shape;
3956
+ shapeOptions.load(overrideOptions.shape);
3957
+ }
3881
3958
  }
3882
3959
  }
3883
- this.shapeData = this._loadShapeData(shapeOptions, reduceDuplicates);
3960
+ this.effectData = loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates);
3961
+ this.shapeData = loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates);
3884
3962
  particlesOptions.load(overrideOptions);
3963
+ const effectData = this.effectData;
3964
+ if (effectData) {
3965
+ particlesOptions.load(effectData.particles);
3966
+ }
3885
3967
  const shapeData = this.shapeData;
3886
3968
  if (shapeData) {
3887
3969
  particlesOptions.load(shapeData.particles);
@@ -3890,11 +3972,13 @@ class Particle {
3890
3972
  interactivity.load(container.actualOptions.interactivity);
3891
3973
  interactivity.load(particlesOptions.interactivity);
3892
3974
  this.interactivity = interactivity;
3893
- this.fill = shapeData?.fill ?? particlesOptions.shape.fill;
3894
- this.close = shapeData?.close ?? particlesOptions.shape.close;
3975
+ this.effectFill = effectData?.fill ?? particlesOptions.effect.fill;
3976
+ this.effectClose = effectData?.close ?? particlesOptions.effect.close;
3977
+ this.shapeFill = shapeData?.fill ?? particlesOptions.shape.fill;
3978
+ this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
3895
3979
  this.options = particlesOptions;
3896
3980
  const pathOptions = this.options.move.path;
3897
- this.pathDelay = getValue(pathOptions.delay) * 1000;
3981
+ this.pathDelay = getRangeValue(pathOptions.delay.value) * 1000;
3898
3982
  if (pathOptions.generator) {
3899
3983
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
3900
3984
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
@@ -3915,34 +3999,46 @@ class Particle {
3915
3999
  this.velocity = this.initialVelocity.copy();
3916
4000
  this.moveDecay = 1 - getRangeValue(this.options.move.decay);
3917
4001
  const particles = container.particles;
3918
- particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
3919
- particles.lastZIndex = this.position.z;
4002
+ particles.setLastZIndex(this.position.z);
3920
4003
  this.zIndexFactor = this.position.z / container.zLayers;
3921
4004
  this.sides = 24;
3922
- let drawer = container.drawers.get(this.shape);
3923
- if (!drawer) {
3924
- drawer = this._engine.getShapeDrawer(this.shape);
3925
- if (drawer) {
3926
- container.drawers.set(this.shape, drawer);
4005
+ let effectDrawer = container.effectDrawers.get(this.effect);
4006
+ if (!effectDrawer) {
4007
+ effectDrawer = this._engine.getEffectDrawer(this.effect);
4008
+ if (effectDrawer) {
4009
+ container.effectDrawers.set(this.effect, effectDrawer);
4010
+ }
4011
+ }
4012
+ if (effectDrawer && effectDrawer.loadEffect) {
4013
+ effectDrawer.loadEffect(this);
4014
+ }
4015
+ let shapeDrawer = container.shapeDrawers.get(this.shape);
4016
+ if (!shapeDrawer) {
4017
+ shapeDrawer = this._engine.getShapeDrawer(this.shape);
4018
+ if (shapeDrawer) {
4019
+ container.shapeDrawers.set(this.shape, shapeDrawer);
3927
4020
  }
3928
4021
  }
3929
- if (drawer && drawer.loadShape) {
3930
- drawer.loadShape(this);
4022
+ if (shapeDrawer && shapeDrawer.loadShape) {
4023
+ shapeDrawer.loadShape(this);
3931
4024
  }
3932
- const sideCountFunc = drawer?.getSidesCount;
4025
+ const sideCountFunc = shapeDrawer?.getSidesCount;
3933
4026
  if (sideCountFunc) {
3934
4027
  this.sides = sideCountFunc(this);
3935
4028
  }
3936
4029
  this.spawning = false;
3937
4030
  this.shadowColor = rangeColorToRgb(this.options.shadow.color);
3938
- for (const updater of container.particles.updaters) {
4031
+ for (const updater of particles.updaters) {
3939
4032
  updater.init(this);
3940
4033
  }
3941
- for (const mover of container.particles.movers) {
4034
+ for (const mover of particles.movers) {
3942
4035
  mover.init && mover.init(this);
3943
4036
  }
3944
- if (drawer && drawer.particleInit) {
3945
- drawer.particleInit(container, this);
4037
+ if (effectDrawer && effectDrawer.particleInit) {
4038
+ effectDrawer.particleInit(container, this);
4039
+ }
4040
+ if (shapeDrawer && shapeDrawer.particleInit) {
4041
+ shapeDrawer.particleInit(container, this);
3946
4042
  }
3947
4043
  for (const [, plugin] of container.plugins) {
3948
4044
  plugin.particleCreated && plugin.particleCreated(this);
@@ -4069,7 +4165,7 @@ class QuadTree {
4069
4165
  capacity
4070
4166
  } = this;
4071
4167
  for (let i = 0; i < 4; i++) {
4072
- 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));
4168
+ 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));
4073
4169
  }
4074
4170
  this._divided = true;
4075
4171
  };
@@ -4125,21 +4221,36 @@ class QuadTree {
4125
4221
 
4126
4222
  const qTreeCapacity = 4;
4127
4223
  const qTreeRectangle = canvasSize => {
4128
- return new Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, canvasSize.width * 3 / 2, canvasSize.height * 3 / 2);
4224
+ const {
4225
+ height,
4226
+ width
4227
+ } = canvasSize,
4228
+ posOffset = -0.25,
4229
+ sizeFactor = 1.5;
4230
+ return new Rectangle(posOffset * width, posOffset * height, sizeFactor * width, sizeFactor * height);
4129
4231
  };
4130
4232
  class Particles {
4131
4233
  constructor(engine, container) {
4132
4234
  this._applyDensity = (options, manualCount, group) => {
4235
+ const numberOptions = options.number;
4133
4236
  if (!options.number.density?.enable) {
4237
+ if (group === undefined) {
4238
+ this._limit = numberOptions.limit.value;
4239
+ } else {
4240
+ this._groupLimits.set(group, numberOptions.limit.value);
4241
+ }
4134
4242
  return;
4135
4243
  }
4136
- const numberOptions = options.number,
4137
- densityFactor = this._initDensityFactor(numberOptions.density),
4244
+ const densityFactor = this._initDensityFactor(numberOptions.density),
4138
4245
  optParticlesNumber = numberOptions.value,
4139
- optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber,
4246
+ optParticlesLimit = numberOptions.limit.value > 0 ? numberOptions.limit.value : optParticlesNumber,
4140
4247
  particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount,
4141
4248
  particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
4142
- this.limit = numberOptions.limit * densityFactor;
4249
+ if (group === undefined) {
4250
+ this._limit = numberOptions.limit.value * densityFactor;
4251
+ } else {
4252
+ this._groupLimits.set(group, numberOptions.limit.value * densityFactor);
4253
+ }
4143
4254
  if (particlesCount < particlesNumber) {
4144
4255
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
4145
4256
  } else if (particlesCount > particlesNumber) {
@@ -4157,7 +4268,7 @@ class Particles {
4157
4268
  };
4158
4269
  this._pushParticle = (position, overrideOptions, group, initializer) => {
4159
4270
  try {
4160
- let particle = this.pool.pop();
4271
+ let particle = this._pool.pop();
4161
4272
  if (particle) {
4162
4273
  particle.init(this._nextId, position, overrideOptions, group);
4163
4274
  } else {
@@ -4194,7 +4305,7 @@ class Particles {
4194
4305
  const zIdx = this._zArray.indexOf(particle);
4195
4306
  this._array.splice(index, 1);
4196
4307
  this._zArray.splice(zIdx, 1);
4197
- this.pool.push(particle);
4308
+ this._pool.push(particle);
4198
4309
  this._engine.dispatchEvent("particleRemoved", {
4199
4310
  container: this._container,
4200
4311
  data: {
@@ -4208,10 +4319,11 @@ class Particles {
4208
4319
  this._nextId = 0;
4209
4320
  this._array = [];
4210
4321
  this._zArray = [];
4211
- this.pool = [];
4212
- this.limit = 0;
4213
- this.needsSort = false;
4214
- this.lastZIndex = 0;
4322
+ this._pool = [];
4323
+ this._limit = 0;
4324
+ this._groupLimits = new Map();
4325
+ this._needsSort = false;
4326
+ this._lastZIndex = 0;
4215
4327
  this._interactionManager = new InteractionManager(engine, container);
4216
4328
  const canvasSize = container.canvas.size;
4217
4329
  this.quadTree = new QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
@@ -4229,19 +4341,22 @@ class Particles {
4229
4341
  }
4230
4342
  }
4231
4343
  addParticle(position, overrideOptions, group, initializer) {
4232
- this.pushing = true;
4233
- const container = this._container,
4234
- options = container.actualOptions,
4235
- limit = options.particles.number.limit;
4344
+ const limitOptions = this._container.actualOptions.particles.number.limit,
4345
+ limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit,
4346
+ currentCount = this.count;
4236
4347
  if (limit > 0) {
4237
- const countToRemove = this.count + 1 - limit;
4238
- if (countToRemove > 0) {
4239
- this.removeQuantity(countToRemove);
4348
+ if (limitOptions.mode === "delete") {
4349
+ const countToRemove = currentCount + 1 - limit;
4350
+ if (countToRemove > 0) {
4351
+ this.removeQuantity(countToRemove);
4352
+ }
4353
+ } else if (limitOptions.mode === "wait") {
4354
+ if (currentCount >= limit) {
4355
+ return;
4356
+ }
4240
4357
  }
4241
4358
  }
4242
- const res = this._pushParticle(position, overrideOptions, group, initializer);
4243
- this.pushing = false;
4244
- return res;
4359
+ return this._pushParticle(position, overrideOptions, group, initializer);
4245
4360
  }
4246
4361
  clear() {
4247
4362
  this._array = [];
@@ -4280,8 +4395,8 @@ class Particles {
4280
4395
  init() {
4281
4396
  const container = this._container,
4282
4397
  options = container.actualOptions;
4283
- this.lastZIndex = 0;
4284
- this.needsSort = false;
4398
+ this._lastZIndex = 0;
4399
+ this._needsSort = false;
4285
4400
  let handled = false;
4286
4401
  this.updaters = this._engine.getUpdaters(container, true);
4287
4402
  this._interactionManager.init();
@@ -4348,6 +4463,13 @@ class Particles {
4348
4463
  }
4349
4464
  this._applyDensity(options.particles, options.manualParticles.length);
4350
4465
  }
4466
+ setLastZIndex(zIndex) {
4467
+ this._lastZIndex = zIndex;
4468
+ this._needsSort = this._needsSort || this._lastZIndex < zIndex;
4469
+ }
4470
+ setResizeFactor(factor) {
4471
+ this._resizeFactor = factor;
4472
+ }
4351
4473
  async update(delta) {
4352
4474
  const container = this._container,
4353
4475
  particlesToDelete = new Set();
@@ -4356,10 +4478,10 @@ class Particles {
4356
4478
  pathGenerator.update();
4357
4479
  }
4358
4480
  for (const [, plugin] of container.plugins) {
4359
- plugin.update && plugin.update(delta);
4481
+ plugin.update && (await plugin.update(delta));
4360
4482
  }
4483
+ const resizeFactor = this._resizeFactor;
4361
4484
  for (const particle of this._array) {
4362
- const resizeFactor = container.canvas.resizeFactor;
4363
4485
  if (resizeFactor && !particle.ignoresResizeRatio) {
4364
4486
  particle.position.x *= resizeFactor.width;
4365
4487
  particle.position.y *= resizeFactor.height;
@@ -4387,7 +4509,7 @@ class Particles {
4387
4509
  const checkDelete = p => !particlesToDelete.has(p);
4388
4510
  this._array = this.filter(checkDelete);
4389
4511
  this._zArray = this._zArray.filter(checkDelete);
4390
- this.pool.push(...particlesToDelete);
4512
+ this._pool.push(...particlesToDelete);
4391
4513
  }
4392
4514
  await this._interactionManager.externalInteract(delta);
4393
4515
  for (const particle of this._array) {
@@ -4398,12 +4520,12 @@ class Particles {
4398
4520
  await this._interactionManager.particlesInteract(particle, delta);
4399
4521
  }
4400
4522
  }
4401
- delete container.canvas.resizeFactor;
4402
- if (this.needsSort) {
4523
+ delete this._resizeFactor;
4524
+ if (this._needsSort) {
4403
4525
  const zArray = this._zArray;
4404
4526
  zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
4405
- this.lastZIndex = zArray[zArray.length - 1].position.z;
4406
- this.needsSort = false;
4527
+ this._lastZIndex = zArray[zArray.length - 1].position.z;
4528
+ this._needsSort = false;
4407
4529
  }
4408
4530
  }
4409
4531
  }
@@ -4430,7 +4552,6 @@ class Retina {
4430
4552
  }
4431
4553
  const particles = options.particles,
4432
4554
  moveOptions = particles.move;
4433
- this.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4434
4555
  this.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
4435
4556
  this.sizeAnimationSpeed = getRangeValue(particles.size.animation.speed) * ratio;
4436
4557
  }
@@ -4440,7 +4561,6 @@ class Retina {
4440
4561
  moveOptions = options.move,
4441
4562
  moveDistance = moveOptions.distance,
4442
4563
  props = particle.retina;
4443
- props.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4444
4564
  props.moveDrift = getRangeValue(moveOptions.drift) * ratio;
4445
4565
  props.moveSpeed = getRangeValue(moveOptions.speed) * ratio;
4446
4566
  props.sizeAnimationSpeed = getRangeValue(options.size.animation.speed) * ratio;
@@ -4476,7 +4596,6 @@ function loadContainerOptions(engine, container, ...sourceOptionsArr) {
4476
4596
  }
4477
4597
  class Container {
4478
4598
  constructor(engine, id, sourceOptions) {
4479
- this.id = id;
4480
4599
  this._intersectionManager = entries => {
4481
4600
  if (!guardCheck(this) || !this.actualOptions.pauseOnOutsideViewport) {
4482
4601
  return;
@@ -4490,14 +4609,14 @@ class Container {
4490
4609
  };
4491
4610
  this._nextFrame = async timestamp => {
4492
4611
  try {
4493
- if (!this.smooth && this.lastFrameTime !== undefined && timestamp < this.lastFrameTime + 1000 / this.fpsLimit) {
4612
+ if (!this._smooth && this._lastFrameTime !== undefined && timestamp < this._lastFrameTime + 1000 / this.fpsLimit) {
4494
4613
  this.draw(false);
4495
4614
  return;
4496
4615
  }
4497
- this.lastFrameTime ??= timestamp;
4498
- const delta = initDelta(timestamp - this.lastFrameTime, this.fpsLimit, this.smooth);
4616
+ this._lastFrameTime ??= timestamp;
4617
+ const delta = initDelta(timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
4499
4618
  this.addLifeTime(delta.value);
4500
- this.lastFrameTime = timestamp;
4619
+ this._lastFrameTime = timestamp;
4501
4620
  if (delta.value > 1000) {
4502
4621
  this.draw(false);
4503
4622
  return;
@@ -4515,8 +4634,9 @@ class Container {
4515
4634
  }
4516
4635
  };
4517
4636
  this._engine = engine;
4637
+ this.id = Symbol(id);
4518
4638
  this.fpsLimit = 120;
4519
- this.smooth = false;
4639
+ this._smooth = false;
4520
4640
  this._delay = 0;
4521
4641
  this._duration = 0;
4522
4642
  this._lifeTime = 0;
@@ -4524,7 +4644,7 @@ class Container {
4524
4644
  this.started = false;
4525
4645
  this.destroyed = false;
4526
4646
  this._paused = true;
4527
- this.lastFrameTime = 0;
4647
+ this._lastFrameTime = 0;
4528
4648
  this.zLayers = 100;
4529
4649
  this.pageHidden = false;
4530
4650
  this._sourceOptions = sourceOptions;
@@ -4540,13 +4660,12 @@ class Container {
4540
4660
  }
4541
4661
  };
4542
4662
  this.plugins = new Map();
4543
- this.drawers = new Map();
4663
+ this.effectDrawers = new Map();
4664
+ this.shapeDrawers = new Map();
4544
4665
  this._options = loadContainerOptions(this._engine, this);
4545
4666
  this.actualOptions = loadContainerOptions(this._engine, this);
4546
4667
  this._eventListeners = new EventListeners(this);
4547
- if (typeof IntersectionObserver !== "undefined" && IntersectionObserver) {
4548
- this._intersectionObserver = new IntersectionObserver(entries => this._intersectionManager(entries));
4549
- }
4668
+ this._intersectionObserver = safeIntersectionObserver(entries => this._intersectionManager(entries));
4550
4669
  this._engine.dispatchEvent("containerBuilt", {
4551
4670
  container: this
4552
4671
  });
@@ -4660,11 +4779,17 @@ class Container {
4660
4779
  this.stop();
4661
4780
  this.particles.destroy();
4662
4781
  this.canvas.destroy();
4663
- for (const [, drawer] of this.drawers) {
4664
- drawer.destroy && drawer.destroy(this);
4782
+ for (const [, effectDrawer] of this.effectDrawers) {
4783
+ effectDrawer.destroy && effectDrawer.destroy(this);
4784
+ }
4785
+ for (const [, shapeDrawer] of this.shapeDrawers) {
4786
+ shapeDrawer.destroy && shapeDrawer.destroy(this);
4665
4787
  }
4666
- for (const key of this.drawers.keys()) {
4667
- this.drawers.delete(key);
4788
+ for (const key of this.effectDrawers.keys()) {
4789
+ this.effectDrawers.delete(key);
4790
+ }
4791
+ for (const key of this.shapeDrawers.keys()) {
4792
+ this.shapeDrawers.delete(key);
4668
4793
  }
4669
4794
  this._engine.clearPlugins(this);
4670
4795
  this.destroyed = true;
@@ -4684,7 +4809,7 @@ class Container {
4684
4809
  let refreshTime = force;
4685
4810
  this._drawAnimationFrame = requestAnimationFrame(async timestamp => {
4686
4811
  if (refreshTime) {
4687
- this.lastFrameTime = undefined;
4812
+ this._lastFrameTime = undefined;
4688
4813
  refreshTime = false;
4689
4814
  }
4690
4815
  await this._nextFrame(timestamp);
@@ -4719,11 +4844,18 @@ class Container {
4719
4844
  if (!guardCheck(this)) {
4720
4845
  return;
4721
4846
  }
4847
+ const effects = this._engine.getSupportedEffects();
4848
+ for (const type of effects) {
4849
+ const drawer = this._engine.getEffectDrawer(type);
4850
+ if (drawer) {
4851
+ this.effectDrawers.set(type, drawer);
4852
+ }
4853
+ }
4722
4854
  const shapes = this._engine.getSupportedShapes();
4723
4855
  for (const type of shapes) {
4724
4856
  const drawer = this._engine.getShapeDrawer(type);
4725
4857
  if (drawer) {
4726
- this.drawers.set(type, drawer);
4858
+ this.shapeDrawers.set(type, drawer);
4727
4859
  }
4728
4860
  }
4729
4861
  this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
@@ -4742,8 +4874,11 @@ class Container {
4742
4874
  this._delay = getRangeValue(this.actualOptions.delay) * 1000;
4743
4875
  this._lifeTime = 0;
4744
4876
  this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
4745
- this.smooth = this.actualOptions.smooth;
4746
- for (const [, drawer] of this.drawers) {
4877
+ this._smooth = this.actualOptions.smooth;
4878
+ for (const [, drawer] of this.effectDrawers) {
4879
+ drawer.init && (await drawer.init(this));
4880
+ }
4881
+ for (const [, drawer] of this.shapeDrawers) {
4747
4882
  drawer.init && (await drawer.init(this));
4748
4883
  }
4749
4884
  for (const [, plugin] of this.plugins) {
@@ -4884,10 +5019,10 @@ class Container {
4884
5019
  this.actualOptions.responsive = [];
4885
5020
  const newMaxWidth = this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
4886
5021
  this.actualOptions.setTheme(this._currentTheme);
4887
- if (this.responsiveMaxWidth === newMaxWidth) {
5022
+ if (this._responsiveMaxWidth === newMaxWidth) {
4888
5023
  return false;
4889
5024
  }
4890
- this.responsiveMaxWidth = newMaxWidth;
5025
+ this._responsiveMaxWidth = newMaxWidth;
4891
5026
  return true;
4892
5027
  }
4893
5028
  }
@@ -4978,7 +5113,8 @@ class Engine {
4978
5113
  this.movers = new Map();
4979
5114
  this.updaters = new Map();
4980
5115
  this.presets = new Map();
4981
- this.drawers = new Map();
5116
+ this.effectDrawers = new Map();
5117
+ this.shapeDrawers = new Map();
4982
5118
  this.pathGenerators = new Map();
4983
5119
  }
4984
5120
  get configs() {
@@ -4989,17 +5125,23 @@ class Engine {
4989
5125
  return res;
4990
5126
  }
4991
5127
  get version() {
4992
- return "3.0.0-beta.2";
5128
+ return "3.0.0-beta.4";
4993
5129
  }
4994
- addConfig(nameOrConfig, config) {
4995
- if (isString(nameOrConfig)) {
4996
- if (config) {
4997
- config.name = nameOrConfig;
4998
- this._configs.set(nameOrConfig, config);
5130
+ addConfig(config) {
5131
+ const name = config.name ?? "default";
5132
+ this._configs.set(name, config);
5133
+ this._eventDispatcher.dispatchEvent("configAdded", {
5134
+ data: {
5135
+ name,
5136
+ config
4999
5137
  }
5000
- } else {
5001
- this._configs.set(nameOrConfig.name ?? "default", nameOrConfig);
5002
- }
5138
+ });
5139
+ }
5140
+ async addEffect(effect, drawer, refresh = true) {
5141
+ executeOnSingleOrMultiple(effect, type => {
5142
+ !this.getEffectDrawer(type) && this.effectDrawers.set(type, drawer);
5143
+ });
5144
+ await this.refresh(refresh);
5003
5145
  }
5004
5146
  addEventListener(type, listener) {
5005
5147
  this._eventDispatcher.addEventListener(type, listener);
@@ -5028,44 +5170,11 @@ class Engine {
5028
5170
  (override || !this.getPreset(preset)) && this.presets.set(preset, options);
5029
5171
  await this.refresh(refresh);
5030
5172
  }
5031
- async addShape(shape, drawer, initOrRefresh, afterEffectOrRefresh, destroyOrRefresh, refresh = true) {
5032
- let customDrawer;
5033
- let realRefresh = refresh,
5034
- realInit,
5035
- realAfterEffect,
5036
- realDestroy;
5037
- if (isBoolean(initOrRefresh)) {
5038
- realRefresh = initOrRefresh;
5039
- realInit = undefined;
5040
- } else {
5041
- realInit = initOrRefresh;
5042
- }
5043
- if (isBoolean(afterEffectOrRefresh)) {
5044
- realRefresh = afterEffectOrRefresh;
5045
- realAfterEffect = undefined;
5046
- } else {
5047
- realAfterEffect = afterEffectOrRefresh;
5048
- }
5049
- if (isBoolean(destroyOrRefresh)) {
5050
- realRefresh = destroyOrRefresh;
5051
- realDestroy = undefined;
5052
- } else {
5053
- realDestroy = destroyOrRefresh;
5054
- }
5055
- if (isFunction(drawer)) {
5056
- customDrawer = {
5057
- afterEffect: realAfterEffect,
5058
- destroy: realDestroy,
5059
- draw: drawer,
5060
- init: realInit
5061
- };
5062
- } else {
5063
- customDrawer = drawer;
5064
- }
5173
+ async addShape(shape, drawer, refresh = true) {
5065
5174
  executeOnSingleOrMultiple(shape, type => {
5066
- !this.getShapeDrawer(type) && this.drawers.set(type, customDrawer);
5175
+ !this.getShapeDrawer(type) && this.shapeDrawers.set(type, drawer);
5067
5176
  });
5068
- await this.refresh(realRefresh);
5177
+ await this.refresh(refresh);
5069
5178
  }
5070
5179
  clearPlugins(container) {
5071
5180
  this.updaters.delete(container);
@@ -5094,6 +5203,9 @@ class Engine {
5094
5203
  }
5095
5204
  return res;
5096
5205
  }
5206
+ getEffectDrawer(type) {
5207
+ return this.effectDrawers.get(type);
5208
+ }
5097
5209
  getInteractors(container, force = false) {
5098
5210
  return getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
5099
5211
  }
@@ -5110,10 +5222,13 @@ class Engine {
5110
5222
  return this.presets.get(preset);
5111
5223
  }
5112
5224
  getShapeDrawer(type) {
5113
- return this.drawers.get(type);
5225
+ return this.shapeDrawers.get(type);
5226
+ }
5227
+ getSupportedEffects() {
5228
+ return this.effectDrawers.keys();
5114
5229
  }
5115
5230
  getSupportedShapes() {
5116
- return this.drawers.keys();
5231
+ return this.shapeDrawers.keys();
5117
5232
  }
5118
5233
  getUpdaters(container, force = false) {
5119
5234
  return getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
@@ -5143,7 +5258,7 @@ class Engine {
5143
5258
  }
5144
5259
  const currentOptions = itemFromSingleOrMultiple(options, index),
5145
5260
  dom = this.dom(),
5146
- oldIndex = dom.findIndex(v => v.id === id);
5261
+ oldIndex = dom.findIndex(v => v.id.description === id);
5147
5262
  if (oldIndex >= 0) {
5148
5263
  const old = this.domItem(oldIndex);
5149
5264
  if (old && !old.destroyed) {
@@ -5409,7 +5524,6 @@ class ParticlesInteractorBase {
5409
5524
 
5410
5525
 
5411
5526
 
5412
-
5413
5527
 
5414
5528
 
5415
5529
  ;// CONCATENATED MODULE: ../../engine/dist/browser/index.js
@@ -5443,6 +5557,7 @@ class ConfettiOptions {
5443
5557
  this.scalar = 1;
5444
5558
  this.zIndex = 100;
5445
5559
  this.disableForReducedMotion = true;
5560
+ this.flat = false;
5446
5561
  this.shapeOptions = {};
5447
5562
  }
5448
5563
  get origin() {
@@ -5481,6 +5596,9 @@ class ConfettiOptions {
5481
5596
  if (data.decay !== undefined) {
5482
5597
  this.decay = data.decay;
5483
5598
  }
5599
+ if (data.flat !== undefined) {
5600
+ this.flat = data.flat;
5601
+ }
5484
5602
  if (data.gravity !== undefined) {
5485
5603
  this.gravity = data.gravity;
5486
5604
  }
@@ -5561,10 +5679,10 @@ function applyDistance(particle) {
5561
5679
  if ((hDistance && dxFixed >= hDistance || vDistance && dyFixed >= vDistance) && !particle.misplaced) {
5562
5680
  particle.misplaced = !!hDistance && dxFixed > hDistance || !!vDistance && dyFixed > vDistance;
5563
5681
  if (hDistance) {
5564
- particle.velocity.x = particle.velocity.y / 2 - particle.velocity.x;
5682
+ particle.velocity.x = particle.velocity.y * 0.5 - particle.velocity.x;
5565
5683
  }
5566
5684
  if (vDistance) {
5567
- particle.velocity.y = particle.velocity.x / 2 - particle.velocity.y;
5685
+ particle.velocity.y = particle.velocity.x * 0.5 - particle.velocity.y;
5568
5686
  }
5569
5687
  } else if ((!hDistance || dxFixed < hDistance) && (!vDistance || dyFixed < vDistance) && particle.misplaced) {
5570
5688
  particle.misplaced = false;
@@ -5622,15 +5740,16 @@ function spin(particle, moveSpeed) {
5622
5740
  particle.position.x = particle.spin.center.x + particle.spin.radius * updateFunc.x(particle.spin.angle);
5623
5741
  particle.position.y = particle.spin.center.y + particle.spin.radius * updateFunc.y(particle.spin.angle);
5624
5742
  particle.spin.radius += particle.spin.acceleration;
5625
- const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height);
5626
- if (particle.spin.radius > maxCanvasSize / 2) {
5627
- particle.spin.radius = maxCanvasSize / 2;
5743
+ const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height),
5744
+ halfMaxSize = maxCanvasSize * 0.5;
5745
+ if (particle.spin.radius > halfMaxSize) {
5746
+ particle.spin.radius = halfMaxSize;
5628
5747
  particle.spin.acceleration *= -1;
5629
5748
  } else if (particle.spin.radius < 0) {
5630
5749
  particle.spin.radius = 0;
5631
5750
  particle.spin.acceleration *= -1;
5632
5751
  }
5633
- particle.spin.angle += moveSpeed / 100 * (1 - particle.spin.radius / maxCanvasSize);
5752
+ particle.spin.angle += moveSpeed * 0.01 * (1 - particle.spin.radius / maxCanvasSize);
5634
5753
  }
5635
5754
  function applyPath(particle, delta) {
5636
5755
  const particlesOptions = particle.options,
@@ -5674,8 +5793,8 @@ class BaseMover {
5674
5793
  y: 50
5675
5794
  },
5676
5795
  spinCenter = {
5677
- x: spinPos.x / 100 * container.canvas.size.width,
5678
- y: spinPos.y / 100 * container.canvas.size.height
5796
+ x: spinPos.x * 0.01 * container.canvas.size.width,
5797
+ y: spinPos.y * 0.01 * container.canvas.size.height
5679
5798
  },
5680
5799
  pos = particle.getPosition(),
5681
5800
  distance = getDistance(pos, spinCenter),
@@ -5734,7 +5853,12 @@ async function loadBaseMover(engine, refresh = true) {
5734
5853
  ;// CONCATENATED MODULE: ../../shapes/circle/dist/browser/CircleDrawer.js
5735
5854
 
5736
5855
  class CircleDrawer {
5737
- draw(context, particle, radius) {
5856
+ draw(data) {
5857
+ const {
5858
+ context,
5859
+ particle,
5860
+ radius
5861
+ } = data;
5738
5862
  if (!particle.circleRange) {
5739
5863
  particle.circleRange = {
5740
5864
  min: 0,
@@ -5993,7 +6117,7 @@ function bounceHorizontal(data) {
5993
6117
  const velocity = data.particle.velocity.x;
5994
6118
  let bounced = false;
5995
6119
  if (data.direction === "right" && data.bounds.right >= data.canvasSize.width && velocity > 0 || data.direction === "left" && data.bounds.left <= 0 && velocity < 0) {
5996
- const newVelocity = getValue(data.particle.options.bounce.horizontal);
6120
+ const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
5997
6121
  data.particle.velocity.x *= -newVelocity;
5998
6122
  bounced = true;
5999
6123
  }
@@ -6022,7 +6146,7 @@ function bounceVertical(data) {
6022
6146
  const velocity = data.particle.velocity.y;
6023
6147
  let bounced = false;
6024
6148
  if (data.direction === "bottom" && data.bounds.bottom >= data.canvasSize.height && velocity > 0 || data.direction === "top" && data.bounds.top <= 0 && velocity < 0) {
6025
- const newVelocity = getValue(data.particle.options.bounce.vertical);
6149
+ const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
6026
6150
  data.particle.velocity.y *= -newVelocity;
6027
6151
  bounced = true;
6028
6152
  }
@@ -6429,18 +6553,22 @@ async function loadBasic(engine, refresh = true) {
6429
6553
  await engine.refresh(refresh);
6430
6554
  }
6431
6555
  ;// CONCATENATED MODULE: ../../shapes/cards/dist/browser/Utils.js
6432
- function drawPath(ctx, radius, path) {
6556
+ function drawPath(data, path) {
6433
6557
  if (!path.segments.length || !path.segments[0].values.length) {
6434
6558
  return;
6435
6559
  }
6436
- ctx.moveTo(path.segments[0].values[0].x * radius, path.segments[0].values[0].y * radius);
6560
+ const {
6561
+ context,
6562
+ radius
6563
+ } = data;
6564
+ context.moveTo(path.segments[0].values[0].x * radius, path.segments[0].values[0].y * radius);
6437
6565
  for (let i = 0; i < path.segments.length; i++) {
6438
6566
  const segment = path.segments[i];
6439
- ctx.bezierCurveTo(segment.values[1].x * radius, segment.values[1].y * radius, segment.values[2].x * radius, segment.values[2].y * radius, segment.values[3].x * radius, segment.values[3].y * radius);
6567
+ context.bezierCurveTo(segment.values[1].x * radius, segment.values[1].y * radius, segment.values[2].x * radius, segment.values[2].y * radius, segment.values[3].x * radius, segment.values[3].y * radius);
6440
6568
  }
6441
6569
  for (let i = path.segments.length - 1; i >= 0; i--) {
6442
6570
  const segment = path.segments[i];
6443
- ctx.bezierCurveTo(-segment.values[2].x * radius, segment.values[2].y * radius, -segment.values[1].x * radius, segment.values[1].y * radius, -segment.values[0].x * radius, segment.values[0].y * radius);
6571
+ context.bezierCurveTo(-segment.values[2].x * radius, segment.values[2].y * radius, -segment.values[1].x * radius, segment.values[1].y * radius, -segment.values[0].x * radius, segment.values[0].y * radius);
6444
6572
  }
6445
6573
  }
6446
6574
  const n = 1.0 / 2;
@@ -6685,23 +6813,23 @@ const paths = {
6685
6813
  ;// CONCATENATED MODULE: ../../shapes/cards/dist/browser/CardsSuitsDrawers.js
6686
6814
 
6687
6815
  class SpadeDrawer {
6688
- draw(context, _particle, radius) {
6689
- drawPath(context, radius, paths.spade);
6816
+ draw(data) {
6817
+ drawPath(data, paths.spade);
6690
6818
  }
6691
6819
  }
6692
6820
  class HeartDrawer {
6693
- draw(context, _particle, radius) {
6694
- drawPath(context, radius, paths.heart);
6821
+ draw(data) {
6822
+ drawPath(data, paths.heart);
6695
6823
  }
6696
6824
  }
6697
6825
  class DiamondDrawer {
6698
- draw(context, _particle, radius) {
6699
- drawPath(context, radius, paths.diamond);
6826
+ draw(data) {
6827
+ drawPath(data, paths.diamond);
6700
6828
  }
6701
6829
  }
6702
6830
  class ClubDrawer {
6703
- draw(context, _particle, radius) {
6704
- drawPath(context, radius, paths.club);
6831
+ draw(data) {
6832
+ drawPath(data, paths.club);
6705
6833
  }
6706
6834
  }
6707
6835
  ;// CONCATENATED MODULE: ../../shapes/cards/dist/browser/index.js
@@ -6712,35 +6840,6 @@ async function loadCardsShape(engine, refresh = true) {
6712
6840
  await engine.addShape(["diamond", "diamonds"], new DiamondDrawer(), refresh);
6713
6841
  await engine.addShape(["club", "clubs"], new ClubDrawer(), refresh);
6714
6842
  }
6715
- ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Shapes/Circle/CircleShape.js
6716
-
6717
- class CircleShape {
6718
- randomPosition(position, size, fill) {
6719
- const generateTheta = (x, y) => {
6720
- const u = getRandom() / 4.0,
6721
- theta = Math.atan(y / x * Math.tan(2 * Math.PI * u)),
6722
- v = getRandom();
6723
- if (v < 0.25) {
6724
- return theta;
6725
- } else if (v < 0.5) {
6726
- return Math.PI - theta;
6727
- } else if (v < 0.75) {
6728
- return Math.PI + theta;
6729
- } else {
6730
- return -theta;
6731
- }
6732
- },
6733
- radius = (x, y, theta) => x * y / Math.sqrt((y * Math.cos(theta)) ** 2 + (x * Math.sin(theta)) ** 2),
6734
- [a, b] = [size.width / 2, size.height / 2],
6735
- randomTheta = generateTheta(a, b),
6736
- maxRadius = radius(a, b, randomTheta),
6737
- randomRadius = fill ? maxRadius * Math.sqrt(getRandom()) : maxRadius;
6738
- return {
6739
- x: position.x + randomRadius * Math.cos(randomTheta),
6740
- y: position.y + randomRadius * Math.sin(randomTheta)
6741
- };
6742
- }
6743
- }
6744
6843
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterLife.js
6745
6844
 
6746
6845
  class EmitterLife {
@@ -6784,6 +6883,46 @@ class EmitterRate {
6784
6883
  }
6785
6884
  }
6786
6885
  }
6886
+ ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterShapeReplace.js
6887
+ class EmitterShapeReplace {
6888
+ constructor() {
6889
+ this.color = false;
6890
+ this.opacity = false;
6891
+ }
6892
+ load(data) {
6893
+ if (!data) {
6894
+ return;
6895
+ }
6896
+ if (data.color !== undefined) {
6897
+ this.color = data.color;
6898
+ }
6899
+ if (data.opacity !== undefined) {
6900
+ this.opacity = data.opacity;
6901
+ }
6902
+ }
6903
+ }
6904
+ ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterShape.js
6905
+
6906
+
6907
+ class EmitterShape {
6908
+ constructor() {
6909
+ this.options = {};
6910
+ this.replace = new EmitterShapeReplace();
6911
+ this.type = "square";
6912
+ }
6913
+ load(data) {
6914
+ if (!data) {
6915
+ return;
6916
+ }
6917
+ if (data.options !== undefined) {
6918
+ this.options = deepExtend({}, data.options ?? {});
6919
+ }
6920
+ this.replace.load(data.replace);
6921
+ if (data.type !== undefined) {
6922
+ this.type = data.type;
6923
+ }
6924
+ }
6925
+ }
6787
6926
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Options/Classes/EmitterSize.js
6788
6927
  class EmitterSize {
6789
6928
  constructor() {
@@ -6811,13 +6950,14 @@ class EmitterSize {
6811
6950
 
6812
6951
 
6813
6952
 
6953
+
6814
6954
  class Emitter {
6815
6955
  constructor() {
6816
6956
  this.autoPlay = true;
6817
6957
  this.fill = true;
6818
6958
  this.life = new EmitterLife();
6819
6959
  this.rate = new EmitterRate();
6820
- this.shape = "square";
6960
+ this.shape = new EmitterShape();
6821
6961
  this.startCount = 0;
6822
6962
  }
6823
6963
  load(data) {
@@ -6846,9 +6986,7 @@ class Emitter {
6846
6986
  return deepExtend({}, particles);
6847
6987
  });
6848
6988
  this.rate.load(data.rate);
6849
- if (data.shape !== undefined) {
6850
- this.shape = data.shape;
6851
- }
6989
+ this.shape.load(data.shape);
6852
6990
  if (data.position !== undefined) {
6853
6991
  this.position = {};
6854
6992
  if (data.position.x !== undefined) {
@@ -6873,17 +7011,24 @@ class Emitter {
6873
7011
 
6874
7012
 
6875
7013
 
7014
+ function setParticlesOptionsColor(particlesOptions, color) {
7015
+ if (particlesOptions.color) {
7016
+ particlesOptions.color.value = color;
7017
+ } else {
7018
+ particlesOptions.color = {
7019
+ value: color
7020
+ };
7021
+ }
7022
+ }
6876
7023
  class EmitterInstance {
6877
7024
  constructor(engine, emitters, container, options, position) {
6878
7025
  this.emitters = emitters;
6879
7026
  this.container = container;
6880
- this._calcPosition = () => {
6881
- return calcPositionOrRandomFromSizeRanged({
6882
- size: this.container.canvas.size,
6883
- position: this.options.position
6884
- });
6885
- };
6886
7027
  this._destroy = () => {
7028
+ this._mutationObserver?.disconnect();
7029
+ this._mutationObserver = undefined;
7030
+ this._resizeObserver?.disconnect();
7031
+ this._resizeObserver = undefined;
6887
7032
  this.emitters.removeEmitter(this);
6888
7033
  this._engine.dispatchEvent("emitterDestroyed", {
6889
7034
  container: this.container,
@@ -6892,41 +7037,6 @@ class EmitterInstance {
6892
7037
  }
6893
7038
  });
6894
7039
  };
6895
- this._emit = () => {
6896
- if (this._paused) {
6897
- return;
6898
- }
6899
- const quantity = getRangeValue(this.options.rate.quantity);
6900
- this._emitParticles(quantity);
6901
- };
6902
- this._emitParticles = quantity => {
6903
- const position = this.getPosition(),
6904
- size = this.getSize(),
6905
- singleParticlesOptions = itemFromSingleOrMultiple(this._particlesOptions);
6906
- for (let i = 0; i < quantity; i++) {
6907
- const particlesOptions = deepExtend({}, singleParticlesOptions);
6908
- if (this.spawnColor) {
6909
- const hslAnimation = this.options.spawnColor?.animation;
6910
- if (hslAnimation) {
6911
- this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, 360);
6912
- this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, 100);
6913
- this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, 100);
6914
- }
6915
- if (!particlesOptions.color) {
6916
- particlesOptions.color = {
6917
- value: this.spawnColor
6918
- };
6919
- } else {
6920
- particlesOptions.color.value = this.spawnColor;
6921
- }
6922
- }
6923
- if (!position) {
6924
- return;
6925
- }
6926
- const pPosition = this._shape?.randomPosition(position, size, this.fill) ?? position;
6927
- this.container.particles.addParticle(pPosition, particlesOptions);
6928
- }
6929
- };
6930
7040
  this._prepareToDie = () => {
6931
7041
  if (this._paused) {
6932
7042
  return;
@@ -6961,7 +7071,6 @@ class EmitterInstance {
6961
7071
  this._spawnDelay = getRangeValue(this.options.life.delay ?? 0) * 1000 / this.container.retina.reduceFactor;
6962
7072
  this.position = this._initialPosition ?? this._calcPosition();
6963
7073
  this.name = this.options.name;
6964
- this._shape = this._engine.emitterShapeManager?.getShape(this.options.shape);
6965
7074
  this.fill = this.options.fill;
6966
7075
  this._firstSpawn = !this.options.life.wait;
6967
7076
  this._startParticlesAdded = false;
@@ -6974,17 +7083,31 @@ class EmitterInstance {
6974
7083
  }
6975
7084
  this._paused = !this.options.autoPlay;
6976
7085
  this._particlesOptions = particlesOptions;
6977
- this.size = this.options.size ?? (() => {
6978
- const size = new EmitterSize();
6979
- size.load({
6980
- height: 0,
6981
- mode: "percent",
6982
- width: 0
6983
- });
6984
- return size;
6985
- })();
7086
+ this._size = this._calcSize();
7087
+ this.size = getSize(this._size, this.container.canvas.size);
6986
7088
  this._lifeCount = this.options.life.count ?? -1;
6987
7089
  this._immortal = this._lifeCount <= 0;
7090
+ if (this.options.domId) {
7091
+ const element = document.getElementById(this.options.domId);
7092
+ if (element) {
7093
+ this._mutationObserver = new MutationObserver(() => {
7094
+ this.resize();
7095
+ });
7096
+ this._resizeObserver = new ResizeObserver(() => {
7097
+ this.resize();
7098
+ });
7099
+ this._mutationObserver.observe(element, {
7100
+ attributes: true,
7101
+ attributeFilter: ["style", "width", "height"]
7102
+ });
7103
+ this._resizeObserver.observe(element);
7104
+ }
7105
+ }
7106
+ const shapeOptions = this.options.shape,
7107
+ shapeGenerator = this._engine.emitterShapeManager?.getShapeGenerator(shapeOptions.type);
7108
+ if (shapeGenerator) {
7109
+ this._shape = shapeGenerator.generate(this.position, this.size, this.fill, shapeOptions.options);
7110
+ }
6988
7111
  this._engine.dispatchEvent("emitterCreated", {
6989
7112
  container,
6990
7113
  data: {
@@ -7001,33 +7124,8 @@ class EmitterInstance {
7001
7124
  this._paused = false;
7002
7125
  this.play();
7003
7126
  }
7004
- getPosition() {
7005
- if (this.options.domId) {
7006
- const container = this.container,
7007
- element = document.getElementById(this.options.domId);
7008
- if (element) {
7009
- const elRect = element.getBoundingClientRect();
7010
- return {
7011
- x: (elRect.x + elRect.width / 2) * container.retina.pixelRatio,
7012
- y: (elRect.y + elRect.height / 2) * container.retina.pixelRatio
7013
- };
7014
- }
7015
- }
7016
- return this.position;
7017
- }
7018
- getSize() {
7019
- const container = this.container;
7020
- if (this.options.domId) {
7021
- const element = document.getElementById(this.options.domId);
7022
- if (element) {
7023
- const elRect = element.getBoundingClientRect();
7024
- return {
7025
- width: elRect.width * container.retina.pixelRatio,
7026
- height: elRect.height * container.retina.pixelRatio
7027
- };
7028
- }
7029
- }
7030
- return getSize(this.size, container.canvas.size);
7127
+ async init() {
7128
+ await this._shape?.init();
7031
7129
  }
7032
7130
  pause() {
7033
7131
  if (this._paused) {
@@ -7053,8 +7151,11 @@ class EmitterInstance {
7053
7151
  resize() {
7054
7152
  const initialPosition = this._initialPosition;
7055
7153
  this.position = initialPosition && isPointInside(initialPosition, this.container.canvas.size, Vector.origin) ? initialPosition : this._calcPosition();
7154
+ this._size = this._calcSize();
7155
+ this.size = getSize(this._size, this.container.canvas.size);
7156
+ this._shape?.resize(this.position, this.size);
7056
7157
  }
7057
- update(delta) {
7158
+ async update(delta) {
7058
7159
  if (this._paused) {
7059
7160
  return;
7060
7161
  }
@@ -7065,7 +7166,7 @@ class EmitterInstance {
7065
7166
  }
7066
7167
  if (!this._startParticlesAdded) {
7067
7168
  this._startParticlesAdded = true;
7068
- this._emitParticles(this.options.startCount);
7169
+ await this._emitParticles(this.options.startCount);
7069
7170
  }
7070
7171
  if (this._duration !== undefined) {
7071
7172
  this._currentDuration += delta.value;
@@ -7106,6 +7207,94 @@ class EmitterInstance {
7106
7207
  }
7107
7208
  }
7108
7209
  }
7210
+ _calcPosition() {
7211
+ if (this.options.domId) {
7212
+ const container = this.container,
7213
+ element = document.getElementById(this.options.domId);
7214
+ if (element) {
7215
+ const elRect = element.getBoundingClientRect();
7216
+ return {
7217
+ x: (elRect.x + elRect.width / 2) * container.retina.pixelRatio,
7218
+ y: (elRect.y + elRect.height / 2) * container.retina.pixelRatio
7219
+ };
7220
+ }
7221
+ }
7222
+ return calcPositionOrRandomFromSizeRanged({
7223
+ size: this.container.canvas.size,
7224
+ position: this.options.position
7225
+ });
7226
+ }
7227
+ _calcSize() {
7228
+ const container = this.container;
7229
+ if (this.options.domId) {
7230
+ const element = document.getElementById(this.options.domId);
7231
+ if (element) {
7232
+ const elRect = element.getBoundingClientRect();
7233
+ return {
7234
+ width: elRect.width * container.retina.pixelRatio,
7235
+ height: elRect.height * container.retina.pixelRatio,
7236
+ mode: "precise"
7237
+ };
7238
+ }
7239
+ }
7240
+ return this.options.size ?? (() => {
7241
+ const size = new EmitterSize();
7242
+ size.load({
7243
+ height: 0,
7244
+ mode: "percent",
7245
+ width: 0
7246
+ });
7247
+ return size;
7248
+ })();
7249
+ }
7250
+ async _emit() {
7251
+ if (this._paused) {
7252
+ return;
7253
+ }
7254
+ const quantity = getRangeValue(this.options.rate.quantity);
7255
+ await this._emitParticles(quantity);
7256
+ }
7257
+ async _emitParticles(quantity) {
7258
+ const singleParticlesOptions = itemFromSingleOrMultiple(this._particlesOptions);
7259
+ for (let i = 0; i < quantity; i++) {
7260
+ const particlesOptions = deepExtend({}, singleParticlesOptions);
7261
+ if (this.spawnColor) {
7262
+ const hslAnimation = this.options.spawnColor?.animation;
7263
+ if (hslAnimation) {
7264
+ this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, 360);
7265
+ this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, 100);
7266
+ this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, 100);
7267
+ }
7268
+ setParticlesOptionsColor(particlesOptions, this.spawnColor);
7269
+ }
7270
+ const shapeOptions = this.options.shape;
7271
+ let position = this.position;
7272
+ if (this._shape) {
7273
+ const shapePosData = await this._shape.randomPosition();
7274
+ if (shapePosData) {
7275
+ position = shapePosData.position;
7276
+ const replaceData = shapeOptions.replace;
7277
+ if (replaceData.color && shapePosData.color) {
7278
+ setParticlesOptionsColor(particlesOptions, shapePosData.color);
7279
+ }
7280
+ if (replaceData.opacity) {
7281
+ if (particlesOptions.opacity) {
7282
+ particlesOptions.opacity.value = shapePosData.opacity;
7283
+ } else {
7284
+ particlesOptions.opacity = {
7285
+ value: shapePosData.opacity
7286
+ };
7287
+ }
7288
+ }
7289
+ } else {
7290
+ position = null;
7291
+ }
7292
+ }
7293
+ if (position) {
7294
+ this.container.particles.addParticle(position, particlesOptions);
7295
+ }
7296
+ }
7297
+ }
7109
7298
  }
7110
7299
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Emitters.js
7111
7300
 
@@ -7125,7 +7314,7 @@ class Emitters {
7125
7314
  value: []
7126
7315
  };
7127
7316
  container.getEmitter = idxOrName => idxOrName === undefined || isNumber(idxOrName) ? this.array[idxOrName || 0] : this.array.find(t => t.name === idxOrName);
7128
- container.addEmitter = (options, position) => this.addEmitter(options, position);
7317
+ container.addEmitter = async (options, position) => this.addEmitter(options, position);
7129
7318
  container.removeEmitter = idxOrName => {
7130
7319
  const emitter = container.getEmitter(idxOrName);
7131
7320
  if (emitter) {
@@ -7145,10 +7334,11 @@ class Emitters {
7145
7334
  }
7146
7335
  };
7147
7336
  }
7148
- addEmitter(options, position) {
7337
+ async addEmitter(options, position) {
7149
7338
  const emitterOptions = new Emitter();
7150
7339
  emitterOptions.load(options);
7151
7340
  const emitter = new EmitterInstance(this._engine, this, this.container, emitterOptions, position);
7341
+ await emitter.init();
7152
7342
  this.array.push(emitter);
7153
7343
  return emitter;
7154
7344
  }
@@ -7192,10 +7382,10 @@ class Emitters {
7192
7382
  }
7193
7383
  if (isArray(this.emitters)) {
7194
7384
  for (const emitterOptions of this.emitters) {
7195
- this.addEmitter(emitterOptions);
7385
+ await this.addEmitter(emitterOptions);
7196
7386
  }
7197
7387
  } else {
7198
- this.addEmitter(this.emitters);
7388
+ await this.addEmitter(this.emitters);
7199
7389
  }
7200
7390
  }
7201
7391
  pause() {
@@ -7222,71 +7412,28 @@ class Emitters {
7222
7412
  stop() {
7223
7413
  this.array = [];
7224
7414
  }
7225
- update(delta) {
7415
+ async update(delta) {
7226
7416
  for (const emitter of this.array) {
7227
- emitter.update(delta);
7417
+ await emitter.update(delta);
7228
7418
  }
7229
7419
  }
7230
7420
  }
7231
7421
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/ShapeManager.js
7232
- const shapes = new Map();
7422
+ const shapeGeneratorss = new Map();
7233
7423
  class ShapeManager {
7234
7424
  constructor(engine) {
7235
7425
  this._engine = engine;
7236
7426
  }
7237
- addShape(name, drawer) {
7238
- if (!this.getShape(name)) {
7239
- shapes.set(name, drawer);
7427
+ addShapeGenerator(name, generator) {
7428
+ if (!this.getShapeGenerator(name)) {
7429
+ shapeGeneratorss.set(name, generator);
7240
7430
  }
7241
7431
  }
7242
- getShape(name) {
7243
- return shapes.get(name);
7432
+ getShapeGenerator(name) {
7433
+ return shapeGeneratorss.get(name);
7244
7434
  }
7245
- getSupportedShapes() {
7246
- return shapes.keys();
7247
- }
7248
- }
7249
- ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/Shapes/Square/SquareShape.js
7250
-
7251
- function randomSquareCoordinate(position, offset) {
7252
- return position + offset * (getRandom() - 0.5);
7253
- }
7254
- class SquareShape {
7255
- randomPosition(position, size, fill) {
7256
- if (fill) {
7257
- return {
7258
- x: randomSquareCoordinate(position.x, size.width),
7259
- y: randomSquareCoordinate(position.y, size.height)
7260
- };
7261
- } else {
7262
- const halfW = size.width / 2,
7263
- halfH = size.height / 2,
7264
- side = Math.floor(getRandom() * 4),
7265
- v = (getRandom() - 0.5) * 2;
7266
- switch (side) {
7267
- case 0:
7268
- return {
7269
- x: position.x + v * halfW,
7270
- y: position.y - halfH
7271
- };
7272
- case 1:
7273
- return {
7274
- x: position.x - halfW,
7275
- y: position.y + v * halfH
7276
- };
7277
- case 2:
7278
- return {
7279
- x: position.x + v * halfW,
7280
- y: position.y + halfH
7281
- };
7282
- case 3:
7283
- default:
7284
- return {
7285
- x: position.x + halfW,
7286
- y: position.y + v * halfH
7287
- };
7288
- }
7289
- }
7435
+ getSupportedShapeGenerators() {
7436
+ return shapeGeneratorss.keys();
7290
7437
  }
7291
7438
  }
7292
7439
  ;// CONCATENATED MODULE: ../../plugins/emitters/dist/browser/index.js
@@ -7294,8 +7441,6 @@ class SquareShape {
7294
7441
 
7295
7442
 
7296
7443
 
7297
-
7298
-
7299
7444
  class EmittersPlugin {
7300
7445
  constructor(engine) {
7301
7446
  this._engine = engine;
@@ -7380,23 +7525,28 @@ async function loadEmittersPlugin(engine, refresh = true) {
7380
7525
  if (!engine.emitterShapeManager) {
7381
7526
  engine.emitterShapeManager = new ShapeManager(engine);
7382
7527
  }
7383
- if (!engine.addEmitterShape) {
7384
- engine.addEmitterShape = (name, shape) => {
7385
- engine.emitterShapeManager?.addShape(name, shape);
7528
+ if (!engine.addEmitterShapeGenerator) {
7529
+ engine.addEmitterShapeGenerator = (name, generator) => {
7530
+ engine.emitterShapeManager?.addShapeGenerator(name, generator);
7386
7531
  };
7387
7532
  }
7388
7533
  const plugin = new EmittersPlugin(engine);
7389
7534
  await engine.addPlugin(plugin, refresh);
7390
- engine.addEmitterShape("circle", new CircleShape());
7391
- engine.addEmitterShape("square", new SquareShape());
7392
7535
  }
7393
7536
 
7394
7537
 
7395
7538
 
7396
7539
 
7540
+
7541
+
7542
+
7397
7543
  ;// CONCATENATED MODULE: ../../shapes/heart/dist/browser/HeartDrawer.js
7398
7544
  class HeartDrawer_HeartDrawer {
7399
- draw(context, _particle, radius) {
7545
+ draw(data) {
7546
+ const {
7547
+ context,
7548
+ radius
7549
+ } = data;
7400
7550
  const x = -radius,
7401
7551
  y = -radius;
7402
7552
  context.moveTo(x, y + radius / 2);
@@ -7966,8 +8116,15 @@ class ImageDrawer {
7966
8116
  }
7967
8117
  this._engine.images.push(image);
7968
8118
  }
7969
- draw(context, particle, radius, opacity, delta) {
7970
- const image = particle.image,
8119
+ draw(data) {
8120
+ const {
8121
+ context,
8122
+ radius,
8123
+ particle,
8124
+ opacity,
8125
+ delta
8126
+ } = data,
8127
+ image = particle.image,
7971
8128
  element = image?.element;
7972
8129
  if (!image) {
7973
8130
  return;
@@ -8074,8 +8231,11 @@ class ImageDrawer {
8074
8231
  if (!this._engine.images) {
8075
8232
  this._engine.images = [];
8076
8233
  }
8077
- const imageData = particle.shapeData,
8078
- image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);
8234
+ const imageData = particle.shapeData;
8235
+ if (!imageData) {
8236
+ return;
8237
+ }
8238
+ const image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);
8079
8239
  if (!image) {
8080
8240
  this.loadImageShape(imageData).then(() => {
8081
8241
  this.loadShape(particle);
@@ -8090,8 +8250,11 @@ class ImageDrawer {
8090
8250
  this._engine.images = [];
8091
8251
  }
8092
8252
  const images = this._engine.images,
8093
- imageData = particle.shapeData,
8094
- color = particle.getFillColor(),
8253
+ imageData = particle.shapeData;
8254
+ if (!imageData) {
8255
+ return;
8256
+ }
8257
+ const color = particle.getFillColor(),
8095
8258
  image = images.find(t => t.name === imageData.name || t.source === imageData.src);
8096
8259
  if (!image) {
8097
8260
  return;
@@ -8124,16 +8287,16 @@ class ImageDrawer {
8124
8287
  if (!imageRes.ratio) {
8125
8288
  imageRes.ratio = 1;
8126
8289
  }
8127
- const fill = imageData.fill ?? particle.fill,
8128
- close = imageData.close ?? particle.close,
8290
+ const fill = imageData.fill ?? particle.shapeFill,
8291
+ close = imageData.close ?? particle.shapeClose,
8129
8292
  imageShape = {
8130
8293
  image: imageRes,
8131
8294
  fill,
8132
8295
  close
8133
8296
  };
8134
8297
  particle.image = imageShape.image;
8135
- particle.fill = imageShape.fill;
8136
- particle.close = imageShape.close;
8298
+ particle.shapeFill = imageShape.fill;
8299
+ particle.shapeClose = imageShape.close;
8137
8300
  })();
8138
8301
  }
8139
8302
  }
@@ -8266,7 +8429,6 @@ class LifeDelay extends ValueWithRandom {
8266
8429
  class LifeDuration extends ValueWithRandom {
8267
8430
  constructor() {
8268
8431
  super();
8269
- this.random.minimumValue = 0.0001;
8270
8432
  this.sync = false;
8271
8433
  }
8272
8434
  load(data) {
@@ -8508,8 +8670,13 @@ async function loadMotionPlugin(engine, refresh = true) {
8508
8670
  ;// CONCATENATED MODULE: ../../shapes/polygon/dist/browser/PolygonDrawerBase.js
8509
8671
 
8510
8672
  class PolygonDrawerBase {
8511
- draw(context, particle, radius) {
8512
- const start = this.getCenter(particle, radius),
8673
+ draw(data) {
8674
+ const {
8675
+ context,
8676
+ particle,
8677
+ radius
8678
+ } = data,
8679
+ start = this.getCenter(particle, radius),
8513
8680
  side = this.getSidesData(particle, radius),
8514
8681
  sideCount = side.count.numerator * side.count.denominator,
8515
8682
  decimalSides = side.count.numerator / side.count.denominator,
@@ -8887,8 +9054,12 @@ async function loadRotateUpdater(engine, refresh = true) {
8887
9054
  ;// CONCATENATED MODULE: ../../shapes/square/dist/browser/SquareDrawer.js
8888
9055
  const fixFactor = Math.sqrt(2);
8889
9056
  class SquareDrawer {
8890
- draw(context, particle, radius) {
8891
- const fixedRadius = radius / fixFactor,
9057
+ draw(data) {
9058
+ const {
9059
+ context,
9060
+ radius
9061
+ } = data,
9062
+ fixedRadius = radius / fixFactor,
8892
9063
  fixedDiameter = fixedRadius * 2;
8893
9064
  context.rect(-fixedRadius, -fixedRadius, fixedDiameter, fixedDiameter);
8894
9065
  }
@@ -8904,8 +9075,13 @@ async function loadSquareShape(engine, refresh = true) {
8904
9075
  ;// CONCATENATED MODULE: ../../shapes/star/dist/browser/StarDrawer.js
8905
9076
 
8906
9077
  class StarDrawer {
8907
- draw(context, particle, radius) {
8908
- const sides = particle.sides,
9078
+ draw(data) {
9079
+ const {
9080
+ context,
9081
+ particle,
9082
+ radius
9083
+ } = data,
9084
+ sides = particle.sides,
8909
9085
  inset = particle.starInset ?? 2;
8910
9086
  context.moveTo(0, 0 - radius);
8911
9087
  for (let i = 0; i < sides; i++) {
@@ -8931,11 +9107,31 @@ async function loadStarShape(engine, refresh = true) {
8931
9107
  }
8932
9108
  ;// CONCATENATED MODULE: ../../shapes/text/dist/browser/TextDrawer.js
8933
9109
 
8934
- const validTypes = ["text", "character", "char"];
9110
+ const validTypes = ["text", "character", "char", "multiline-text"];
8935
9111
  class TextDrawer {
8936
- draw(context, particle, radius, opacity) {
8937
- const character = particle.shapeData;
8938
- if (character === undefined) {
9112
+ constructor() {
9113
+ this._drawLine = (context, line, radius, opacity, index, fill) => {
9114
+ const offsetX = line.length * radius / 2,
9115
+ pos = {
9116
+ x: -offsetX,
9117
+ y: radius / 2
9118
+ };
9119
+ if (fill) {
9120
+ context.fillText(line, pos.x, pos.y + radius * 2 * index);
9121
+ } else {
9122
+ context.strokeText(line, pos.x, pos.y + radius * 2 * index);
9123
+ }
9124
+ };
9125
+ }
9126
+ draw(data) {
9127
+ const {
9128
+ context,
9129
+ particle,
9130
+ radius,
9131
+ opacity
9132
+ } = data,
9133
+ character = particle.shapeData;
9134
+ if (!character) {
8939
9135
  return;
8940
9136
  }
8941
9137
  const textData = character.value;
@@ -8950,24 +9146,18 @@ class TextDrawer {
8950
9146
  weight = character.weight ?? "400",
8951
9147
  size = Math.round(radius) * 2,
8952
9148
  font = character.font ?? "Verdana",
8953
- fill = particle.fill,
8954
- offsetX = text.length * radius / 2;
9149
+ fill = particle.shapeFill;
9150
+ const lines = text?.split("\n");
9151
+ if (!lines) {
9152
+ return;
9153
+ }
8955
9154
  context.font = `${style} ${weight} ${size}px "${font}"`;
8956
- const pos = {
8957
- x: -offsetX,
8958
- y: radius / 2
8959
- };
8960
9155
  context.globalAlpha = opacity;
8961
- if (fill) {
8962
- context.fillText(text, pos.x, pos.y);
8963
- } else {
8964
- context.strokeText(text, pos.x, pos.y);
9156
+ for (let i = 0; i < lines.length; i++) {
9157
+ this._drawLine(context, lines[i], radius, opacity, i, fill);
8965
9158
  }
8966
9159
  context.globalAlpha = 1;
8967
9160
  }
8968
- getSidesCount() {
8969
- return 12;
8970
- }
8971
9161
  async init(container) {
8972
9162
  const options = container.actualOptions;
8973
9163
  if (validTypes.find(t => isInArray(t, options.particles.shape.type))) {
@@ -9479,20 +9669,20 @@ async function setConfetti(params) {
9479
9669
  }
9480
9670
  },
9481
9671
  rotate: {
9482
- value: {
9672
+ value: actualOptions.flat ? 0 : {
9483
9673
  min: 0,
9484
9674
  max: 360
9485
9675
  },
9486
9676
  direction: "random",
9487
9677
  animation: {
9488
- enable: true,
9678
+ enable: actualOptions.flat,
9489
9679
  speed: 60
9490
9680
  }
9491
9681
  },
9492
9682
  tilt: {
9493
9683
  direction: "random",
9494
- enable: true,
9495
- value: {
9684
+ enable: actualOptions.flat,
9685
+ value: actualOptions.flat ? 0 : {
9496
9686
  min: 0,
9497
9687
  max: 360
9498
9688
  },
@@ -9506,7 +9696,7 @@ async function setConfetti(params) {
9506
9696
  enable: true,
9507
9697
  value: 25
9508
9698
  },
9509
- enable: true,
9699
+ enable: actualOptions.flat,
9510
9700
  speed: {
9511
9701
  min: 15,
9512
9702
  max: 25
@@ -9514,7 +9704,7 @@ async function setConfetti(params) {
9514
9704
  },
9515
9705
  wobble: {
9516
9706
  distance: 30,
9517
- enable: true,
9707
+ enable: actualOptions.flat,
9518
9708
  speed: {
9519
9709
  min: -15,
9520
9710
  max: 15