@tsparticles/preset-bubbles 4.1.2 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* Preset v4.1.2 */
2
+ /* Preset v4.2.0 */
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
5
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -15,7 +15,7 @@
15
15
  b: 0,
16
16
  c: 0,
17
17
  d: 1,
18
- }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
18
+ }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
19
19
 
20
20
  var MoveDirection;
21
21
  (function (MoveDirection) {
@@ -82,11 +82,6 @@
82
82
  div(n) {
83
83
  return Vector3d.create(this.x / n, this.y / n, this.z / n);
84
84
  }
85
- divTo(n) {
86
- this.x /= n;
87
- this.y /= n;
88
- this.z /= n;
89
- }
90
85
  getLengthSq() {
91
86
  return this.x ** squareExp + this.y ** squareExp;
92
87
  }
@@ -295,27 +290,6 @@
295
290
  return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
296
291
  }
297
292
 
298
- var AnimationMode;
299
- (function (AnimationMode) {
300
- AnimationMode["auto"] = "auto";
301
- AnimationMode["increase"] = "increase";
302
- AnimationMode["decrease"] = "decrease";
303
- AnimationMode["random"] = "random";
304
- })(AnimationMode || (AnimationMode = {}));
305
-
306
- var AnimationStatus;
307
- (function (AnimationStatus) {
308
- AnimationStatus["increasing"] = "increasing";
309
- AnimationStatus["decreasing"] = "decreasing";
310
- })(AnimationStatus || (AnimationStatus = {}));
311
-
312
- var DestroyType;
313
- (function (DestroyType) {
314
- DestroyType["none"] = "none";
315
- DestroyType["max"] = "max";
316
- DestroyType["min"] = "min";
317
- })(DestroyType || (DestroyType = {}));
318
-
319
293
  var OutModeDirection;
320
294
  (function (OutModeDirection) {
321
295
  OutModeDirection["bottom"] = "bottom";
@@ -330,67 +304,7 @@
330
304
  PixelMode["percent"] = "percent";
331
305
  })(PixelMode || (PixelMode = {}));
332
306
 
333
- var StartValueType;
334
- (function (StartValueType) {
335
- StartValueType["max"] = "max";
336
- StartValueType["min"] = "min";
337
- StartValueType["random"] = "random";
338
- })(StartValueType || (StartValueType = {}));
339
-
340
307
  const minRadius = 0;
341
- function memoize(fn, options) {
342
- const cache = new Map(), stableStringify = (obj, seen = new WeakSet()) => {
343
- if (obj === null) {
344
- return "null";
345
- }
346
- const t = typeof obj;
347
- if (t === "undefined") {
348
- return "undefined";
349
- }
350
- if (t === "number" || t === "boolean" || t === "string") {
351
- return JSON.stringify(obj);
352
- }
353
- if (t === "function") {
354
- try {
355
- const fn = obj;
356
- return fn.toString();
357
- }
358
- catch {
359
- return '"[Function]"';
360
- }
361
- }
362
- if (t === "symbol") {
363
- try {
364
- return obj.toString();
365
- }
366
- catch {
367
- return '"[Symbol]"';
368
- }
369
- }
370
- if (Array.isArray(obj)) {
371
- return `[${obj.map(i => stableStringify(i, seen)).join(",")}]`;
372
- }
373
- if (seen.has(obj)) {
374
- return '"[Circular]"';
375
- }
376
- seen.add(obj);
377
- const keys = Object.keys(obj).sort();
378
- return `{${keys.map(k => `${JSON.stringify(k)}:${stableStringify(obj[k], seen)}`).join(",")}}`;
379
- }, defaultKeyer = (args) => stableStringify(args), makeKey = (args) => (defaultKeyer(args));
380
- return (...args) => {
381
- const key = makeKey(args), now = Date.now(), entry = cache.get(key);
382
- if (entry !== undefined) {
383
- {
384
- cache.delete(key);
385
- cache.set(key, { value: entry.value, ts: entry.ts });
386
- return entry.value;
387
- }
388
- }
389
- const result = fn(...args);
390
- cache.set(key, { value: result, ts: now });
391
- return result;
392
- };
393
- }
394
308
  function hasMatchMedia() {
395
309
  return typeof matchMedia !== "undefined";
396
310
  }
@@ -412,11 +326,8 @@
412
326
  function isInArray(value, array) {
413
327
  return value === array || (isArray(array) && array.includes(value));
414
328
  }
415
- function arrayRandomIndex(array) {
416
- return Math.floor(getRandom() * array.length);
417
- }
418
329
  function itemFromArray(array, index, useIndex = true) {
419
- return array[index !== undefined && useIndex ? index % array.length : arrayRandomIndex(array)];
330
+ return array[index !== undefined && useIndex ? index % array.length : Math.floor(getRandom() * array.length)];
420
331
  }
421
332
  function isPointInside(point, size, offset, radius, direction) {
422
333
  return areBoundsInside(calculateBounds(point, radius ?? minRadius), size, offset, direction);
@@ -500,56 +411,6 @@
500
411
  function itemFromSingleOrMultiple(obj, index, useIndex) {
501
412
  return isArray(obj) ? itemFromArray(obj, index, useIndex) : obj;
502
413
  }
503
- function initParticleNumericAnimationValue(options, pxRatio) {
504
- const valueRange = options.value, animationOptions = options.animation, res = {
505
- delayTime: getRangeValue(animationOptions.delay) * millisecondsToSeconds,
506
- enable: animationOptions.enable,
507
- value: getRangeValue(options.value) * pxRatio,
508
- max: getRangeMax(valueRange) * pxRatio,
509
- min: getRangeMin(valueRange) * pxRatio,
510
- loops: 0,
511
- maxLoops: getRangeValue(animationOptions.count),
512
- time: 0,
513
- }, decayOffset = 1;
514
- if (animationOptions.enable) {
515
- res.decay = decayOffset - getRangeValue(animationOptions.decay);
516
- switch (animationOptions.mode) {
517
- case AnimationMode.increase:
518
- res.status = AnimationStatus.increasing;
519
- break;
520
- case AnimationMode.decrease:
521
- res.status = AnimationStatus.decreasing;
522
- break;
523
- case AnimationMode.random:
524
- res.status = getRandom() >= half ? AnimationStatus.increasing : AnimationStatus.decreasing;
525
- break;
526
- }
527
- const autoStatus = animationOptions.mode === AnimationMode.auto;
528
- switch (animationOptions.startValue) {
529
- case StartValueType.min:
530
- res.value = res.min;
531
- if (autoStatus) {
532
- res.status = AnimationStatus.increasing;
533
- }
534
- break;
535
- case StartValueType.max:
536
- res.value = res.max;
537
- if (autoStatus) {
538
- res.status = AnimationStatus.decreasing;
539
- }
540
- break;
541
- case StartValueType.random:
542
- default:
543
- res.value = randomInRangeValue(res);
544
- if (autoStatus) {
545
- res.status = getRandom() >= half ? AnimationStatus.increasing : AnimationStatus.decreasing;
546
- }
547
- break;
548
- }
549
- }
550
- res.initialValue = res.value;
551
- return res;
552
- }
553
414
  function getPositionOrSize(positionOrSize, canvasSize) {
554
415
  const isPercent = positionOrSize.mode === PixelMode.percent;
555
416
  if (!isPercent) {
@@ -573,74 +434,6 @@
573
434
  function getPosition(position, canvasSize) {
574
435
  return getPositionOrSize(position, canvasSize);
575
436
  }
576
- function getSize(size, canvasSize) {
577
- return getPositionOrSize(size, canvasSize);
578
- }
579
- function checkDestroy(particle, destroyType, value, minValue, maxValue) {
580
- switch (destroyType) {
581
- case DestroyType.max:
582
- if (value >= maxValue) {
583
- particle.destroy();
584
- }
585
- break;
586
- case DestroyType.min:
587
- if (value <= minValue) {
588
- particle.destroy();
589
- }
590
- break;
591
- }
592
- }
593
- function updateAnimation(particle, data, changeDirection, destroyType, delta) {
594
- const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minDecay = 1;
595
- if (particle.destroyed ||
596
- !data.enable ||
597
- ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
598
- return;
599
- }
600
- const velocity = (data.velocity ?? minVelocity) * delta.factor, minValue = data.min, maxValue = data.max, decay = data.decay ?? minDecay;
601
- data.time ??= 0;
602
- if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
603
- data.time += delta.value;
604
- }
605
- if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
606
- return;
607
- }
608
- switch (data.status) {
609
- case AnimationStatus.increasing:
610
- data.value += velocity;
611
- break;
612
- case AnimationStatus.decreasing:
613
- data.value -= velocity;
614
- break;
615
- }
616
- if (data.velocity && decay !== identity) {
617
- data.velocity *= decay;
618
- }
619
- switch (data.status) {
620
- case AnimationStatus.increasing:
621
- if (data.value >= maxValue) {
622
- {
623
- data.status = AnimationStatus.decreasing;
624
- }
625
- data.loops ??= minLoops;
626
- data.loops++;
627
- }
628
- break;
629
- case AnimationStatus.decreasing:
630
- if (data.value <= minValue) {
631
- {
632
- data.status = AnimationStatus.increasing;
633
- }
634
- data.loops ??= minLoops;
635
- data.loops++;
636
- }
637
- break;
638
- }
639
- checkDestroy(particle, destroyType, data.value, minValue, maxValue);
640
- if (!particle.destroyed) {
641
- data.value = clamp(data.value, minValue, maxValue);
642
- }
643
- }
644
437
  function cloneStyle(style) {
645
438
  const clonedStyle = safeDocument().createElement("div").style;
646
439
  for (const key in style) {
@@ -662,30 +455,34 @@
662
455
  }
663
456
  return clonedStyle;
664
457
  }
665
- function computeFullScreenStyle(zIndex) {
666
- const fullScreenStyle = safeDocument().createElement("div").style, radix = 10, style = {
667
- width: "100%",
668
- height: "100%",
669
- margin: "0",
670
- padding: "0",
671
- borderWidth: "0",
672
- position: "fixed",
673
- zIndex: zIndex.toString(radix),
674
- "z-index": zIndex.toString(radix),
675
- top: "0",
676
- left: "0",
677
- "pointer-events": "none",
678
- };
679
- for (const key in style) {
680
- const value = style[key];
681
- if (value === undefined) {
682
- continue;
458
+ let _cachedZIndex, _cachedStyle;
459
+ function getFullScreenStyle(zIndex) {
460
+ if (_cachedZIndex !== zIndex || !_cachedStyle) {
461
+ _cachedZIndex = zIndex;
462
+ const fullScreenStyle = safeDocument().createElement("div").style, radix = 10, style = {
463
+ width: "100%",
464
+ height: "100%",
465
+ margin: "0",
466
+ padding: "0",
467
+ borderWidth: "0",
468
+ position: "fixed",
469
+ zIndex: zIndex.toString(radix),
470
+ "z-index": zIndex.toString(radix),
471
+ top: "0",
472
+ left: "0",
473
+ "pointer-events": "none",
474
+ };
475
+ for (const key in style) {
476
+ const value = style[key];
477
+ if (value === undefined) {
478
+ continue;
479
+ }
480
+ fullScreenStyle.setProperty(key, value);
683
481
  }
684
- fullScreenStyle.setProperty(key, value);
482
+ _cachedStyle = fullScreenStyle;
685
483
  }
686
- return fullScreenStyle;
484
+ return _cachedStyle;
687
485
  }
688
- const getFullScreenStyle = memoize(computeFullScreenStyle);
689
486
  function manageListener(element, event, handler, add, options) {
690
487
  if (add) {
691
488
  let addOptions = { passive: true };
@@ -1012,7 +809,7 @@
1012
809
  return this.#domArray;
1013
810
  }
1014
811
  get version() {
1015
- return "4.1.2";
812
+ return "4.2.0";
1016
813
  }
1017
814
  addEventListener(type, listener) {
1018
815
  this.#eventDispatcher.addEventListener(type, listener);
@@ -1182,6 +979,14 @@
1182
979
  RotateDirection["random"] = "random";
1183
980
  })(RotateDirection || (RotateDirection = {}));
1184
981
 
982
+ var AnimationMode;
983
+ (function (AnimationMode) {
984
+ AnimationMode["auto"] = "auto";
985
+ AnimationMode["increase"] = "increase";
986
+ AnimationMode["decrease"] = "decrease";
987
+ AnimationMode["random"] = "random";
988
+ })(AnimationMode || (AnimationMode = {}));
989
+
1185
990
  var LimitMode;
1186
991
  (function (LimitMode) {
1187
992
  LimitMode["delete"] = "delete";
@@ -1203,6 +1008,13 @@
1203
1008
  AlterType["enlighten"] = "enlighten";
1204
1009
  })(AlterType || (AlterType = {}));
1205
1010
 
1011
+ var DestroyType;
1012
+ (function (DestroyType) {
1013
+ DestroyType["none"] = "none";
1014
+ DestroyType["max"] = "max";
1015
+ DestroyType["min"] = "min";
1016
+ })(DestroyType || (DestroyType = {}));
1017
+
1206
1018
  var GradientType;
1207
1019
  (function (GradientType) {
1208
1020
  GradientType["linear"] = "linear";
@@ -1217,160 +1029,121 @@
1217
1029
  ParticleOutType["outside"] = "outside";
1218
1030
  })(ParticleOutType || (ParticleOutType = {}));
1219
1031
 
1220
- var EasingType;
1221
- (function (EasingType) {
1222
- EasingType["easeInBack"] = "ease-in-back";
1223
- EasingType["easeInBounce"] = "ease-in-bounce";
1224
- EasingType["easeInCirc"] = "ease-in-circ";
1225
- EasingType["easeInCubic"] = "ease-in-cubic";
1226
- EasingType["easeInElastic"] = "ease-in-elastic";
1227
- EasingType["easeInExpo"] = "ease-in-expo";
1228
- EasingType["easeInGaussian"] = "ease-in-gaussian";
1229
- EasingType["easeInLinear"] = "ease-in-linear";
1230
- EasingType["easeInQuad"] = "ease-in-quad";
1231
- EasingType["easeInQuart"] = "ease-in-quart";
1232
- EasingType["easeInQuint"] = "ease-in-quint";
1233
- EasingType["easeInSigmoid"] = "ease-in-sigmoid";
1234
- EasingType["easeInSine"] = "ease-in-sine";
1235
- EasingType["easeInSmoothstep"] = "ease-in-smoothstep";
1236
- EasingType["easeOutBack"] = "ease-out-back";
1237
- EasingType["easeOutBounce"] = "ease-out-bounce";
1238
- EasingType["easeOutCirc"] = "ease-out-circ";
1239
- EasingType["easeOutCubic"] = "ease-out-cubic";
1240
- EasingType["easeOutElastic"] = "ease-out-elastic";
1241
- EasingType["easeOutExpo"] = "ease-out-expo";
1242
- EasingType["easeOutGaussian"] = "ease-out-gaussian";
1243
- EasingType["easeOutLinear"] = "ease-out-linear";
1244
- EasingType["easeOutQuad"] = "ease-out-quad";
1245
- EasingType["easeOutQuart"] = "ease-out-quart";
1246
- EasingType["easeOutQuint"] = "ease-out-quint";
1247
- EasingType["easeOutSigmoid"] = "ease-out-sigmoid";
1248
- EasingType["easeOutSine"] = "ease-out-sine";
1249
- EasingType["easeOutSmoothstep"] = "ease-out-smoothstep";
1250
- EasingType["easeInOutBack"] = "ease-in-out-back";
1251
- EasingType["easeInOutBounce"] = "ease-in-out-bounce";
1252
- EasingType["easeInOutCirc"] = "ease-in-out-circ";
1253
- EasingType["easeInOutCubic"] = "ease-in-out-cubic";
1254
- EasingType["easeInOutElastic"] = "ease-in-out-elastic";
1255
- EasingType["easeInOutExpo"] = "ease-in-out-expo";
1256
- EasingType["easeInOutGaussian"] = "ease-in-out-gaussian";
1257
- EasingType["easeInOutLinear"] = "ease-in-out-linear";
1258
- EasingType["easeInOutQuad"] = "ease-in-out-quad";
1259
- EasingType["easeInOutQuart"] = "ease-in-out-quart";
1260
- EasingType["easeInOutQuint"] = "ease-in-out-quint";
1261
- EasingType["easeInOutSigmoid"] = "ease-in-out-sigmoid";
1262
- EasingType["easeInOutSine"] = "ease-in-out-sine";
1263
- EasingType["easeInOutSmoothstep"] = "ease-in-out-smoothstep";
1264
- })(EasingType || (EasingType = {}));
1265
-
1266
- class AnimationOptions {
1267
- count;
1268
- decay;
1269
- delay;
1270
- enable;
1271
- speed;
1272
- sync;
1273
- constructor() {
1274
- this.count = 0;
1275
- this.enable = false;
1276
- this.speed = 1;
1277
- this.decay = 0;
1278
- this.delay = 0;
1279
- this.sync = false;
1280
- }
1032
+ var StartValueType;
1033
+ (function (StartValueType) {
1034
+ StartValueType["max"] = "max";
1035
+ StartValueType["min"] = "min";
1036
+ StartValueType["random"] = "random";
1037
+ })(StartValueType || (StartValueType = {}));
1038
+
1039
+ var AnimationStatus;
1040
+ (function (AnimationStatus) {
1041
+ AnimationStatus["increasing"] = "increasing";
1042
+ AnimationStatus["decreasing"] = "decreasing";
1043
+ })(AnimationStatus || (AnimationStatus = {}));
1044
+
1045
+ class OptionLoader {
1281
1046
  load(data) {
1282
1047
  if (isNull(data)) {
1283
1048
  return;
1284
1049
  }
1285
- if (data.count !== undefined) {
1286
- this.count = setRangeValue(data.count);
1287
- }
1288
- if (data.enable !== undefined) {
1289
- this.enable = data.enable;
1290
- }
1291
- if (data.speed !== undefined) {
1292
- this.speed = setRangeValue(data.speed);
1293
- }
1294
- if (data.decay !== undefined) {
1295
- this.decay = setRangeValue(data.decay);
1296
- }
1297
- if (data.delay !== undefined) {
1298
- this.delay = setRangeValue(data.delay);
1299
- }
1300
- if (data.sync !== undefined) {
1301
- this.sync = data.sync;
1302
- }
1050
+ this.doLoad(data);
1303
1051
  }
1304
1052
  }
1305
- class RangedAnimationOptions extends AnimationOptions {
1306
- mode;
1307
- startValue;
1308
- constructor() {
1309
- super();
1310
- this.mode = AnimationMode.auto;
1311
- this.startValue = StartValueType.random;
1053
+ function loadOptions(options, ...sourceOptionsArr) {
1054
+ for (const sourceOptions of sourceOptionsArr) {
1055
+ options.load(sourceOptions);
1312
1056
  }
1313
- load(data) {
1314
- super.load(data);
1315
- if (isNull(data)) {
1316
- return;
1317
- }
1318
- if (data.mode !== undefined) {
1319
- this.mode = data.mode;
1320
- }
1321
- if (data.startValue !== undefined) {
1322
- this.startValue = data.startValue;
1323
- }
1057
+ }
1058
+
1059
+ function loadProperty(obj, key, value) {
1060
+ if (value !== undefined) {
1061
+ obj[key] = value;
1062
+ }
1063
+ }
1064
+ function loadRangeProperty(obj, key, value) {
1065
+ if (value !== undefined) {
1066
+ obj[key] = setRangeValue(value);
1067
+ }
1068
+ }
1069
+ function loadNestedProperty(obj, key, value) {
1070
+ if (value !== undefined) {
1071
+ obj[key].load(value);
1072
+ }
1073
+ }
1074
+ function loadLazyProperty(obj, key, value, factory) {
1075
+ if (value !== undefined) {
1076
+ const objRecord = obj;
1077
+ objRecord[key] ??= factory();
1078
+ objRecord[key].load(value);
1079
+ }
1080
+ }
1081
+ function loadOptionProperty(obj, key, optionClass, ...sources) {
1082
+ const objRecord = obj;
1083
+ objRecord[key] ??= new optionClass();
1084
+ const target = objRecord[key];
1085
+ for (const source of sources) {
1086
+ target.load(source?.[key]);
1087
+ }
1088
+ }
1089
+
1090
+ class AnimationOptions extends OptionLoader {
1091
+ count = 0;
1092
+ decay = 0;
1093
+ delay = 0;
1094
+ enable = false;
1095
+ speed = 1;
1096
+ sync = false;
1097
+ doLoad(data) {
1098
+ loadRangeProperty(this, "count", data.count);
1099
+ loadProperty(this, "enable", data.enable);
1100
+ loadRangeProperty(this, "speed", data.speed);
1101
+ loadRangeProperty(this, "decay", data.decay);
1102
+ loadRangeProperty(this, "delay", data.delay);
1103
+ loadProperty(this, "sync", data.sync);
1104
+ }
1105
+ }
1106
+ class RangedAnimationOptions extends AnimationOptions {
1107
+ mode = AnimationMode.auto;
1108
+ startValue = StartValueType.random;
1109
+ doLoad(data) {
1110
+ super.doLoad(data);
1111
+ loadProperty(this, "mode", data.mode);
1112
+ loadProperty(this, "startValue", data.startValue);
1324
1113
  }
1325
1114
  }
1326
1115
 
1327
1116
  class ColorAnimation extends AnimationOptions {
1328
1117
  max;
1329
1118
  min;
1330
- offset;
1119
+ offset = 0;
1120
+ sync = true;
1331
1121
  constructor(min, max) {
1332
1122
  super();
1333
1123
  this.min = min;
1334
1124
  this.max = max;
1335
- this.offset = 0;
1336
- this.sync = true;
1337
1125
  }
1338
- load(data) {
1339
- super.load(data);
1340
- if (isNull(data)) {
1341
- return;
1342
- }
1343
- if (data.max !== undefined) {
1344
- this.max = data.max;
1345
- }
1346
- if (data.min !== undefined) {
1347
- this.min = data.min;
1348
- }
1349
- if (data.offset !== undefined) {
1350
- this.offset = setRangeValue(data.offset);
1351
- }
1126
+ doLoad(data) {
1127
+ super.doLoad(data);
1128
+ loadProperty(this, "max", data.max);
1129
+ loadProperty(this, "min", data.min);
1130
+ loadRangeProperty(this, "offset", data.offset);
1352
1131
  }
1353
1132
  }
1354
1133
 
1355
- class HslAnimation {
1134
+ class HslAnimation extends OptionLoader {
1356
1135
  h = new ColorAnimation(hMin, hMax);
1357
1136
  l = new ColorAnimation(lMin, lMax);
1358
1137
  s = new ColorAnimation(sMin, sMax);
1359
- load(data) {
1360
- if (isNull(data)) {
1361
- return;
1362
- }
1138
+ doLoad(data) {
1363
1139
  this.h.load(data.h);
1364
1140
  this.s.load(data.s);
1365
1141
  this.l.load(data.l);
1366
1142
  }
1367
1143
  }
1368
1144
 
1369
- class OptionsColor {
1370
- value;
1371
- constructor() {
1372
- this.value = "";
1373
- }
1145
+ class OptionsColor extends OptionLoader {
1146
+ value = "";
1374
1147
  static create(source, data) {
1375
1148
  const color = new OptionsColor();
1376
1149
  color.load(source);
@@ -1384,10 +1157,7 @@
1384
1157
  }
1385
1158
  return color;
1386
1159
  }
1387
- load(data) {
1388
- if (isNull(data)) {
1389
- return;
1390
- }
1160
+ doLoad(data) {
1391
1161
  if (!isNull(data.value)) {
1392
1162
  this.value = data.value;
1393
1163
  }
@@ -1395,11 +1165,7 @@
1395
1165
  }
1396
1166
 
1397
1167
  class AnimatableColor extends OptionsColor {
1398
- animation;
1399
- constructor() {
1400
- super();
1401
- this.animation = new HslAnimation();
1402
- }
1168
+ animation = new HslAnimation();
1403
1169
  static create(source, data) {
1404
1170
  const color = new AnimatableColor();
1405
1171
  color.load(source);
@@ -1413,11 +1179,8 @@
1413
1179
  }
1414
1180
  return color;
1415
1181
  }
1416
- load(data) {
1417
- super.load(data);
1418
- if (isNull(data)) {
1419
- return;
1420
- }
1182
+ doLoad(data) {
1183
+ super.doLoad(data);
1421
1184
  const colorAnimation = data.animation;
1422
1185
  if (colorAnimation !== undefined) {
1423
1186
  if (colorAnimation.enable === undefined) {
@@ -1430,100 +1193,53 @@
1430
1193
  }
1431
1194
  }
1432
1195
 
1433
- class Background {
1196
+ class Background extends OptionLoader {
1434
1197
  color;
1435
- image;
1436
- opacity;
1437
- position;
1438
- repeat;
1439
- size;
1198
+ image = "";
1199
+ opacity = 1;
1200
+ position = "";
1201
+ repeat = "";
1202
+ size = "";
1440
1203
  constructor() {
1204
+ super();
1441
1205
  this.color = new OptionsColor();
1442
1206
  this.color.value = "";
1443
- this.image = "";
1444
- this.position = "";
1445
- this.repeat = "";
1446
- this.size = "";
1447
- this.opacity = 1;
1448
1207
  }
1449
- load(data) {
1450
- if (isNull(data)) {
1451
- return;
1452
- }
1208
+ doLoad(data) {
1453
1209
  if (data.color !== undefined) {
1454
1210
  this.color = OptionsColor.create(this.color, data.color);
1455
1211
  }
1456
- if (data.image !== undefined) {
1457
- this.image = data.image;
1458
- }
1459
- if (data.position !== undefined) {
1460
- this.position = data.position;
1461
- }
1462
- if (data.repeat !== undefined) {
1463
- this.repeat = data.repeat;
1464
- }
1465
- if (data.size !== undefined) {
1466
- this.size = data.size;
1467
- }
1468
- if (data.opacity !== undefined) {
1469
- this.opacity = data.opacity;
1470
- }
1212
+ loadProperty(this, "image", data.image);
1213
+ loadProperty(this, "position", data.position);
1214
+ loadProperty(this, "repeat", data.repeat);
1215
+ loadProperty(this, "size", data.size);
1216
+ loadProperty(this, "opacity", data.opacity);
1471
1217
  }
1472
1218
  }
1473
1219
 
1474
- class FullScreen {
1475
- enable;
1476
- zIndex;
1477
- constructor() {
1478
- this.enable = true;
1479
- this.zIndex = 0;
1480
- }
1481
- load(data) {
1482
- if (isNull(data)) {
1483
- return;
1484
- }
1485
- if (data.enable !== undefined) {
1486
- this.enable = data.enable;
1487
- }
1488
- if (data.zIndex !== undefined) {
1489
- this.zIndex = data.zIndex;
1490
- }
1220
+ class FullScreen extends OptionLoader {
1221
+ enable = true;
1222
+ zIndex = 0;
1223
+ doLoad(data) {
1224
+ loadProperty(this, "enable", data.enable);
1225
+ loadProperty(this, "zIndex", data.zIndex);
1491
1226
  }
1492
1227
  }
1493
1228
 
1494
- class ResizeEvent {
1495
- delay;
1496
- enable;
1497
- constructor() {
1498
- this.delay = 0.5;
1499
- this.enable = true;
1500
- }
1501
- load(data) {
1502
- if (isNull(data)) {
1503
- return;
1504
- }
1505
- if (data.delay !== undefined) {
1506
- this.delay = data.delay;
1507
- }
1508
- if (data.enable !== undefined) {
1509
- this.enable = data.enable;
1510
- }
1229
+ class ResizeEvent extends OptionLoader {
1230
+ delay = 0.5;
1231
+ enable = true;
1232
+ doLoad(data) {
1233
+ loadProperty(this, "delay", data.delay);
1234
+ loadProperty(this, "enable", data.enable);
1511
1235
  }
1512
1236
  }
1513
1237
 
1514
- class Effect {
1515
- close;
1516
- options;
1517
- type;
1518
- constructor() {
1519
- this.close = true;
1520
- this.options = {};
1521
- this.type = [];
1522
- }
1523
- load(data) {
1524
- if (isNull(data)) {
1525
- return;
1526
- }
1238
+ class Effect extends OptionLoader {
1239
+ close = true;
1240
+ options = {};
1241
+ type = [];
1242
+ doLoad(data) {
1527
1243
  const options = data.options;
1528
1244
  if (options !== undefined) {
1529
1245
  for (const effect in options) {
@@ -1533,128 +1249,62 @@
1533
1249
  }
1534
1250
  }
1535
1251
  }
1536
- if (data.close !== undefined) {
1537
- this.close = data.close;
1538
- }
1539
- if (data.type !== undefined) {
1540
- this.type = data.type;
1541
- }
1252
+ loadProperty(this, "close", data.close);
1253
+ loadProperty(this, "type", data.type);
1542
1254
  }
1543
1255
  }
1544
1256
 
1545
- class Fill {
1257
+ class Fill extends OptionLoader {
1546
1258
  color;
1547
- enable;
1548
- opacity;
1549
- constructor() {
1550
- this.enable = true;
1551
- this.opacity = 1;
1552
- }
1553
- load(data) {
1554
- if (isNull(data)) {
1555
- return;
1556
- }
1259
+ enable = true;
1260
+ opacity = 1;
1261
+ doLoad(data) {
1557
1262
  if (data.color !== undefined) {
1558
1263
  this.color = AnimatableColor.create(this.color, data.color);
1559
1264
  }
1560
- if (data.enable !== undefined) {
1561
- this.enable = data.enable;
1562
- }
1563
- if (data.opacity !== undefined) {
1564
- this.opacity = setRangeValue(data.opacity);
1565
- }
1265
+ loadProperty(this, "enable", data.enable);
1266
+ loadRangeProperty(this, "opacity", data.opacity);
1566
1267
  }
1567
1268
  }
1568
1269
 
1569
- class MoveAngle {
1570
- offset;
1571
- value;
1572
- constructor() {
1573
- this.offset = 0;
1574
- this.value = 90;
1575
- }
1576
- load(data) {
1577
- if (isNull(data)) {
1578
- return;
1579
- }
1580
- if (data.offset !== undefined) {
1581
- this.offset = setRangeValue(data.offset);
1582
- }
1583
- if (data.value !== undefined) {
1584
- this.value = setRangeValue(data.value);
1585
- }
1270
+ class MoveAngle extends OptionLoader {
1271
+ offset = 0;
1272
+ value = 90;
1273
+ doLoad(data) {
1274
+ loadRangeProperty(this, "offset", data.offset);
1275
+ loadRangeProperty(this, "value", data.value);
1586
1276
  }
1587
1277
  }
1588
1278
 
1589
- class MoveCenter {
1590
- mode;
1591
- radius;
1592
- x;
1593
- y;
1594
- constructor() {
1595
- this.x = 50;
1596
- this.y = 50;
1597
- this.mode = PixelMode.percent;
1598
- this.radius = 0;
1599
- }
1600
- load(data) {
1601
- if (isNull(data)) {
1602
- return;
1603
- }
1604
- if (data.x !== undefined) {
1605
- this.x = data.x;
1606
- }
1607
- if (data.y !== undefined) {
1608
- this.y = data.y;
1609
- }
1610
- if (data.mode !== undefined) {
1611
- this.mode = data.mode;
1612
- }
1613
- if (data.radius !== undefined) {
1614
- this.radius = data.radius;
1615
- }
1279
+ class MoveCenter extends OptionLoader {
1280
+ mode = PixelMode.percent;
1281
+ radius = 0;
1282
+ x = 50;
1283
+ y = 50;
1284
+ doLoad(data) {
1285
+ loadProperty(this, "x", data.x);
1286
+ loadProperty(this, "y", data.y);
1287
+ loadProperty(this, "mode", data.mode);
1288
+ loadProperty(this, "radius", data.radius);
1616
1289
  }
1617
1290
  }
1618
1291
 
1619
- class MoveGravity {
1620
- acceleration;
1621
- enable;
1622
- inverse;
1623
- maxSpeed;
1624
- constructor() {
1625
- this.acceleration = 9.81;
1626
- this.enable = false;
1627
- this.inverse = false;
1628
- this.maxSpeed = 50;
1629
- }
1630
- load(data) {
1631
- if (isNull(data)) {
1632
- return;
1633
- }
1634
- if (data.acceleration !== undefined) {
1635
- this.acceleration = setRangeValue(data.acceleration);
1636
- }
1637
- if (data.enable !== undefined) {
1638
- this.enable = data.enable;
1639
- }
1640
- if (data.inverse !== undefined) {
1641
- this.inverse = data.inverse;
1642
- }
1643
- if (data.maxSpeed !== undefined) {
1644
- this.maxSpeed = setRangeValue(data.maxSpeed);
1645
- }
1292
+ class MoveGravity extends OptionLoader {
1293
+ acceleration = 9.81;
1294
+ enable = false;
1295
+ inverse = false;
1296
+ maxSpeed = 50;
1297
+ doLoad(data) {
1298
+ loadRangeProperty(this, "acceleration", data.acceleration);
1299
+ loadProperty(this, "enable", data.enable);
1300
+ loadProperty(this, "inverse", data.inverse);
1301
+ loadRangeProperty(this, "maxSpeed", data.maxSpeed);
1646
1302
  }
1647
1303
  }
1648
1304
 
1649
- class ValueWithRandom {
1650
- value;
1651
- constructor() {
1652
- this.value = 0;
1653
- }
1654
- load(data) {
1655
- if (isNull(data)) {
1656
- return;
1657
- }
1305
+ class ValueWithRandom extends OptionLoader {
1306
+ value = 0;
1307
+ doLoad(data) {
1658
1308
  if (!isNull(data.value)) {
1659
1309
  this.value = setRangeValue(data.value);
1660
1310
  }
@@ -1662,51 +1312,25 @@
1662
1312
  }
1663
1313
  class AnimationValueWithRandom extends ValueWithRandom {
1664
1314
  animation = new AnimationOptions();
1665
- load(data) {
1666
- super.load(data);
1667
- if (isNull(data)) {
1668
- return;
1669
- }
1670
- const animation = data.animation;
1671
- if (animation !== undefined) {
1672
- this.animation.load(animation);
1673
- }
1315
+ doLoad(data) {
1316
+ super.doLoad(data);
1317
+ loadNestedProperty(this, "animation", data.animation);
1674
1318
  }
1675
1319
  }
1676
1320
  class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
1677
- animation;
1678
- constructor() {
1679
- super();
1680
- this.animation = new RangedAnimationOptions();
1681
- }
1682
- load(data) {
1683
- super.load(data);
1684
- }
1321
+ animation = new RangedAnimationOptions();
1685
1322
  }
1686
1323
 
1687
- class MovePath {
1688
- clamp;
1689
- delay;
1690
- enable;
1324
+ class MovePath extends OptionLoader {
1325
+ clamp = true;
1326
+ delay = new ValueWithRandom();
1327
+ enable = false;
1691
1328
  generator;
1692
- options;
1693
- constructor() {
1694
- this.clamp = true;
1695
- this.delay = new ValueWithRandom();
1696
- this.enable = false;
1697
- this.options = {};
1698
- }
1699
- load(data) {
1700
- if (isNull(data)) {
1701
- return;
1702
- }
1703
- if (data.clamp !== undefined) {
1704
- this.clamp = data.clamp;
1705
- }
1329
+ options = {};
1330
+ doLoad(data) {
1331
+ loadProperty(this, "clamp", data.clamp);
1706
1332
  this.delay.load(data.delay);
1707
- if (data.enable !== undefined) {
1708
- this.enable = data.enable;
1709
- }
1333
+ loadProperty(this, "enable", data.enable);
1710
1334
  this.generator = data.generator;
1711
1335
  if (data.options) {
1712
1336
  this.options = deepExtend(this.options, data.options);
@@ -1714,19 +1338,13 @@
1714
1338
  }
1715
1339
  }
1716
1340
 
1717
- class OutModes {
1341
+ class OutModes extends OptionLoader {
1718
1342
  bottom;
1719
- default;
1343
+ default = OutMode.out;
1720
1344
  left;
1721
1345
  right;
1722
1346
  top;
1723
- constructor() {
1724
- this.default = OutMode.out;
1725
- }
1726
- load(data) {
1727
- if (isNull(data)) {
1728
- return;
1729
- }
1347
+ doLoad(data) {
1730
1348
  if (data.default !== undefined) {
1731
1349
  this.default = data.default;
1732
1350
  }
@@ -1737,79 +1355,42 @@
1737
1355
  }
1738
1356
  }
1739
1357
 
1740
- class Spin {
1741
- acceleration;
1742
- enable;
1358
+ class Spin extends OptionLoader {
1359
+ acceleration = 0;
1360
+ enable = false;
1743
1361
  position;
1744
- constructor() {
1745
- this.acceleration = 0;
1746
- this.enable = false;
1747
- }
1748
- load(data) {
1749
- if (isNull(data)) {
1750
- return;
1751
- }
1752
- if (data.acceleration !== undefined) {
1753
- this.acceleration = setRangeValue(data.acceleration);
1754
- }
1755
- if (data.enable !== undefined) {
1756
- this.enable = data.enable;
1757
- }
1362
+ doLoad(data) {
1363
+ loadRangeProperty(this, "acceleration", data.acceleration);
1364
+ loadProperty(this, "enable", data.enable);
1758
1365
  if (data.position) {
1759
1366
  this.position = deepExtend({}, data.position);
1760
1367
  }
1761
1368
  }
1762
1369
  }
1763
1370
 
1764
- class Move {
1765
- angle;
1766
- center;
1767
- decay;
1768
- direction;
1769
- distance;
1770
- drift;
1771
- enable;
1772
- gravity;
1773
- outModes;
1774
- path;
1775
- random;
1776
- size;
1777
- speed;
1778
- spin;
1779
- straight;
1780
- vibrate;
1781
- warp;
1782
- constructor() {
1783
- this.angle = new MoveAngle();
1784
- this.center = new MoveCenter();
1785
- this.decay = 0;
1786
- this.distance = {};
1787
- this.direction = MoveDirection.none;
1788
- this.drift = 0;
1789
- this.enable = false;
1790
- this.gravity = new MoveGravity();
1791
- this.path = new MovePath();
1792
- this.outModes = new OutModes();
1793
- this.random = false;
1794
- this.size = false;
1795
- this.speed = 2;
1796
- this.spin = new Spin();
1797
- this.straight = false;
1798
- this.vibrate = false;
1799
- this.warp = false;
1800
- }
1801
- load(data) {
1802
- if (isNull(data)) {
1803
- return;
1804
- }
1371
+ class Move extends OptionLoader {
1372
+ angle = new MoveAngle();
1373
+ center = new MoveCenter();
1374
+ decay = 0;
1375
+ direction = MoveDirection.none;
1376
+ distance = {};
1377
+ drift = 0;
1378
+ enable = false;
1379
+ gravity = new MoveGravity();
1380
+ outModes = new OutModes();
1381
+ path = new MovePath();
1382
+ random = false;
1383
+ size = false;
1384
+ speed = 2;
1385
+ spin = new Spin();
1386
+ straight = false;
1387
+ vibrate = false;
1388
+ warp = false;
1389
+ doLoad(data) {
1805
1390
  this.angle.load(isNumber(data.angle) ? { value: data.angle } : data.angle);
1806
1391
  this.center.load(data.center);
1807
- if (data.decay !== undefined) {
1808
- this.decay = setRangeValue(data.decay);
1809
- }
1810
- if (data.direction !== undefined) {
1811
- this.direction = data.direction;
1812
- }
1392
+ loadRangeProperty(this, "decay", data.decay);
1393
+ loadProperty(this, "direction", data.direction);
1813
1394
  if (data.distance !== undefined) {
1814
1395
  this.distance = isNumber(data.distance)
1815
1396
  ? {
@@ -1818,12 +1399,8 @@
1818
1399
  }
1819
1400
  : { ...data.distance };
1820
1401
  }
1821
- if (data.drift !== undefined) {
1822
- this.drift = setRangeValue(data.drift);
1823
- }
1824
- if (data.enable !== undefined) {
1825
- this.enable = data.enable;
1826
- }
1402
+ loadRangeProperty(this, "drift", data.drift);
1403
+ loadProperty(this, "enable", data.enable);
1827
1404
  this.gravity.load(data.gravity);
1828
1405
  const outModes = data.outModes;
1829
1406
  if (outModes !== undefined) {
@@ -1837,177 +1414,91 @@
1837
1414
  }
1838
1415
  }
1839
1416
  this.path.load(data.path);
1840
- if (data.random !== undefined) {
1841
- this.random = data.random;
1842
- }
1843
- if (data.size !== undefined) {
1844
- this.size = data.size;
1845
- }
1846
- if (data.speed !== undefined) {
1847
- this.speed = setRangeValue(data.speed);
1848
- }
1417
+ loadProperty(this, "random", data.random);
1418
+ loadProperty(this, "size", data.size);
1419
+ loadRangeProperty(this, "speed", data.speed);
1849
1420
  this.spin.load(data.spin);
1850
- if (data.straight !== undefined) {
1851
- this.straight = data.straight;
1852
- }
1853
- if (data.vibrate !== undefined) {
1854
- this.vibrate = data.vibrate;
1855
- }
1856
- if (data.warp !== undefined) {
1857
- this.warp = data.warp;
1858
- }
1421
+ loadProperty(this, "straight", data.straight);
1422
+ loadProperty(this, "vibrate", data.vibrate);
1423
+ loadProperty(this, "warp", data.warp);
1859
1424
  }
1860
1425
  }
1861
1426
 
1862
- class Stroke {
1427
+ class Stroke extends OptionLoader {
1863
1428
  color;
1864
1429
  opacity;
1865
- width;
1866
- constructor() {
1867
- this.width = 0;
1868
- }
1869
- load(data) {
1870
- if (isNull(data)) {
1871
- return;
1872
- }
1430
+ width = 0;
1431
+ doLoad(data) {
1873
1432
  if (data.color !== undefined) {
1874
1433
  this.color = AnimatableColor.create(this.color, data.color);
1875
1434
  }
1876
- if (data.width !== undefined) {
1877
- this.width = setRangeValue(data.width);
1878
- }
1879
- if (data.opacity !== undefined) {
1880
- this.opacity = setRangeValue(data.opacity);
1881
- }
1435
+ loadRangeProperty(this, "width", data.width);
1436
+ loadRangeProperty(this, "opacity", data.opacity);
1882
1437
  }
1883
1438
  }
1884
1439
 
1885
- class Paint {
1440
+ class Paint extends OptionLoader {
1886
1441
  color;
1887
1442
  fill;
1888
1443
  stroke;
1889
- load(data) {
1890
- if (isNull(data)) {
1891
- return;
1892
- }
1444
+ doLoad(data) {
1893
1445
  if (data.color !== undefined) {
1894
1446
  this.color = AnimatableColor.create(this.color, data.color);
1895
1447
  }
1896
- if (data.fill !== undefined) {
1897
- this.fill ??= new Fill();
1898
- this.fill.load(data.fill);
1899
- }
1900
- if (data.stroke !== undefined) {
1901
- this.stroke ??= new Stroke();
1902
- this.stroke.load(data.stroke);
1903
- }
1448
+ loadLazyProperty(this, "fill", data.fill, () => new Fill());
1449
+ loadLazyProperty(this, "stroke", data.stroke, () => new Stroke());
1904
1450
  }
1905
1451
  }
1906
1452
 
1907
1453
  class ParticlesBounceFactor extends ValueWithRandom {
1908
- constructor() {
1909
- super();
1910
- this.value = 1;
1911
- }
1454
+ value = 1;
1912
1455
  }
1913
1456
 
1914
- class ParticlesBounce {
1915
- horizontal;
1916
- vertical;
1917
- constructor() {
1918
- this.horizontal = new ParticlesBounceFactor();
1919
- this.vertical = new ParticlesBounceFactor();
1920
- }
1921
- load(data) {
1922
- if (isNull(data)) {
1923
- return;
1924
- }
1457
+ class ParticlesBounce extends OptionLoader {
1458
+ horizontal = new ParticlesBounceFactor();
1459
+ vertical = new ParticlesBounceFactor();
1460
+ doLoad(data) {
1925
1461
  this.horizontal.load(data.horizontal);
1926
1462
  this.vertical.load(data.vertical);
1927
1463
  }
1928
1464
  }
1929
1465
 
1930
- class ParticlesDensity {
1931
- enable;
1932
- height;
1933
- width;
1934
- constructor() {
1935
- this.enable = false;
1936
- this.width = 1920;
1937
- this.height = 1080;
1938
- }
1939
- load(data) {
1940
- if (isNull(data)) {
1941
- return;
1942
- }
1943
- if (data.enable !== undefined) {
1944
- this.enable = data.enable;
1945
- }
1946
- const width = data.width;
1947
- if (width !== undefined) {
1948
- this.width = width;
1949
- }
1950
- const height = data.height;
1951
- if (height !== undefined) {
1952
- this.height = height;
1953
- }
1466
+ class ParticlesDensity extends OptionLoader {
1467
+ enable = false;
1468
+ height = 1080;
1469
+ width = 1920;
1470
+ doLoad(data) {
1471
+ loadProperty(this, "enable", data.enable);
1472
+ loadProperty(this, "width", data.width);
1473
+ loadProperty(this, "height", data.height);
1954
1474
  }
1955
1475
  }
1956
1476
 
1957
- class ParticlesNumberLimit {
1958
- mode;
1959
- value;
1960
- constructor() {
1961
- this.mode = LimitMode.delete;
1962
- this.value = 0;
1963
- }
1964
- load(data) {
1965
- if (isNull(data)) {
1966
- return;
1967
- }
1968
- if (data.mode !== undefined) {
1969
- this.mode = data.mode;
1970
- }
1971
- if (data.value !== undefined) {
1972
- this.value = data.value;
1973
- }
1477
+ class ParticlesNumberLimit extends OptionLoader {
1478
+ mode = LimitMode.delete;
1479
+ value = 0;
1480
+ doLoad(data) {
1481
+ loadProperty(this, "mode", data.mode);
1482
+ loadProperty(this, "value", data.value);
1974
1483
  }
1975
1484
  }
1976
1485
 
1977
- class ParticlesNumber {
1978
- density;
1979
- limit;
1980
- value;
1981
- constructor() {
1982
- this.density = new ParticlesDensity();
1983
- this.limit = new ParticlesNumberLimit();
1984
- this.value = 0;
1985
- }
1986
- load(data) {
1987
- if (isNull(data)) {
1988
- return;
1989
- }
1486
+ class ParticlesNumber extends OptionLoader {
1487
+ density = new ParticlesDensity();
1488
+ limit = new ParticlesNumberLimit();
1489
+ value = 0;
1490
+ doLoad(data) {
1990
1491
  this.density.load(data.density);
1991
1492
  this.limit.load(data.limit);
1992
- if (data.value !== undefined) {
1993
- this.value = data.value;
1994
- }
1493
+ loadProperty(this, "value", data.value);
1995
1494
  }
1996
1495
  }
1997
1496
 
1998
- class Shape {
1999
- close;
2000
- options;
2001
- type;
2002
- constructor() {
2003
- this.close = true;
2004
- this.options = {};
2005
- this.type = "circle";
2006
- }
2007
- load(data) {
2008
- if (isNull(data)) {
2009
- return;
2010
- }
1497
+ class Shape extends OptionLoader {
1498
+ close = true;
1499
+ options = {};
1500
+ type = "circle";
1501
+ doLoad(data) {
2011
1502
  const options = data.options;
2012
1503
  if (options !== undefined) {
2013
1504
  for (const shape in options) {
@@ -2017,76 +1508,47 @@
2017
1508
  }
2018
1509
  }
2019
1510
  }
2020
- if (data.close !== undefined) {
2021
- this.close = data.close;
2022
- }
2023
- if (data.type !== undefined) {
2024
- this.type = data.type;
2025
- }
1511
+ loadProperty(this, "close", data.close);
1512
+ loadProperty(this, "type", data.type);
2026
1513
  }
2027
1514
  }
2028
1515
 
2029
1516
  class ZIndex extends ValueWithRandom {
2030
- opacityRate;
2031
- sizeRate;
2032
- velocityRate;
2033
- constructor() {
2034
- super();
2035
- this.opacityRate = 1;
2036
- this.sizeRate = 1;
2037
- this.velocityRate = 1;
2038
- }
2039
- load(data) {
2040
- super.load(data);
2041
- if (isNull(data)) {
2042
- return;
2043
- }
2044
- if (data.opacityRate !== undefined) {
2045
- this.opacityRate = data.opacityRate;
2046
- }
2047
- if (data.sizeRate !== undefined) {
2048
- this.sizeRate = data.sizeRate;
2049
- }
2050
- if (data.velocityRate !== undefined) {
2051
- this.velocityRate = data.velocityRate;
2052
- }
2053
- }
2054
- }
2055
-
2056
- class ParticlesOptions {
2057
- bounce;
2058
- effect;
2059
- groups;
2060
- move;
2061
- number;
1517
+ opacityRate = 1;
1518
+ sizeRate = 1;
1519
+ velocityRate = 1;
1520
+ doLoad(data) {
1521
+ super.doLoad(data);
1522
+ loadProperty(this, "opacityRate", data.opacityRate);
1523
+ loadProperty(this, "sizeRate", data.sizeRate);
1524
+ loadProperty(this, "velocityRate", data.velocityRate);
1525
+ }
1526
+ }
1527
+
1528
+ class ParticlesOptions extends OptionLoader {
1529
+ bounce = new ParticlesBounce();
1530
+ effect = new Effect();
1531
+ groups = {};
1532
+ move = new Move();
1533
+ number = new ParticlesNumber();
2062
1534
  paint;
2063
1535
  palette;
2064
- reduceDuplicates;
2065
- shape;
2066
- zIndex;
1536
+ reduceDuplicates = false;
1537
+ shape = new Shape();
1538
+ zIndex = new ZIndex();
2067
1539
  #container;
2068
1540
  #pluginManager;
2069
1541
  constructor(pluginManager, container) {
1542
+ super();
2070
1543
  this.#pluginManager = pluginManager;
2071
1544
  this.#container = container;
2072
- this.bounce = new ParticlesBounce();
2073
- this.effect = new Effect();
2074
- this.groups = {};
2075
- this.move = new Move();
2076
- this.number = new ParticlesNumber();
2077
1545
  this.paint = new Paint();
2078
1546
  this.paint.color = new AnimatableColor();
2079
1547
  this.paint.color.value = "#fff";
2080
1548
  this.paint.fill = new Fill();
2081
1549
  this.paint.fill.enable = true;
2082
- this.reduceDuplicates = false;
2083
- this.shape = new Shape();
2084
- this.zIndex = new ZIndex();
2085
1550
  }
2086
- load(data) {
2087
- if (isNull(data)) {
2088
- return;
2089
- }
1551
+ doLoad(data) {
2090
1552
  if (data.palette) {
2091
1553
  this.palette = data.palette;
2092
1554
  this.#importPalette(this.palette);
@@ -2144,7 +1606,7 @@
2144
1606
  }
2145
1607
  }
2146
1608
  }
2147
- #importPalette = (palette) => {
1609
+ #importPalette(palette) {
2148
1610
  const paletteData = this.#pluginManager.getPalette(palette);
2149
1611
  if (!paletteData) {
2150
1612
  return;
@@ -2188,69 +1650,49 @@
2188
1650
  mode: paletteData.blendMode,
2189
1651
  },
2190
1652
  });
2191
- };
2192
- }
2193
-
2194
- function loadOptions(options, ...sourceOptionsArr) {
2195
- for (const sourceOptions of sourceOptionsArr) {
2196
- options.load(sourceOptions);
2197
1653
  }
2198
1654
  }
1655
+
2199
1656
  function loadParticlesOptions(pluginManager, container, ...sourceOptionsArr) {
2200
1657
  const options = new ParticlesOptions(pluginManager, container);
2201
1658
  loadOptions(options, ...sourceOptionsArr);
2202
1659
  return options;
2203
1660
  }
2204
1661
 
2205
- class Options {
2206
- autoPlay;
1662
+ class Options extends OptionLoader {
1663
+ autoPlay = true;
2207
1664
  background;
2208
- clear;
2209
- defaultThemes;
2210
- delay;
2211
- detectRetina;
2212
- duration;
2213
- fpsLimit;
1665
+ clear = true;
1666
+ defaultThemes = {};
1667
+ delay = 0;
1668
+ detectRetina = true;
1669
+ duration = 0;
1670
+ fpsLimit = 120;
2214
1671
  fullScreen;
2215
- hdr;
1672
+ hdr = true;
2216
1673
  key;
2217
1674
  name;
2218
1675
  palette;
2219
1676
  particles;
2220
- pauseOnBlur;
2221
- pauseOnOutsideViewport;
1677
+ pauseOnBlur = true;
1678
+ pauseOnOutsideViewport = true;
2222
1679
  preset;
2223
1680
  resize;
2224
- smooth;
2225
- style;
2226
- zLayers;
1681
+ smooth = false;
1682
+ style = {};
1683
+ zLayers = 100;
2227
1684
  #container;
2228
1685
  #pluginManager;
2229
1686
  constructor(pluginManager, container) {
1687
+ super();
2230
1688
  this.#pluginManager = pluginManager;
2231
1689
  this.#container = container;
2232
- this.autoPlay = true;
2233
1690
  this.background = new Background();
2234
- this.clear = true;
2235
- this.defaultThemes = {};
2236
- this.delay = 0;
2237
1691
  this.fullScreen = new FullScreen();
2238
- this.detectRetina = true;
2239
- this.duration = 0;
2240
- this.fpsLimit = 120;
2241
- this.hdr = true;
2242
1692
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
2243
- this.pauseOnBlur = true;
2244
- this.pauseOnOutsideViewport = true;
2245
1693
  this.resize = new ResizeEvent();
2246
- this.smooth = false;
2247
- this.style = {};
2248
- this.zLayers = 100;
2249
1694
  }
2250
- load(data) {
2251
- if (isNull(data)) {
2252
- return;
2253
- }
1695
+ doLoad(data) {
2254
1696
  if (data.preset !== undefined) {
2255
1697
  this.preset = data.preset;
2256
1698
  executeOnSingleOrMultiple(this.preset, preset => {
@@ -2261,44 +1703,18 @@
2261
1703
  this.palette = data.palette;
2262
1704
  this.#importPalette(this.palette);
2263
1705
  }
2264
- if (data.autoPlay !== undefined) {
2265
- this.autoPlay = data.autoPlay;
2266
- }
2267
- if (data.clear !== undefined) {
2268
- this.clear = data.clear;
2269
- }
2270
- if (data.key !== undefined) {
2271
- this.key = data.key;
2272
- }
2273
- if (data.name !== undefined) {
2274
- this.name = data.name;
2275
- }
2276
- if (data.delay !== undefined) {
2277
- this.delay = setRangeValue(data.delay);
2278
- }
2279
- const detectRetina = data.detectRetina;
2280
- if (detectRetina !== undefined) {
2281
- this.detectRetina = detectRetina;
2282
- }
2283
- if (data.duration !== undefined) {
2284
- this.duration = setRangeValue(data.duration);
2285
- }
2286
- const fpsLimit = data.fpsLimit;
2287
- if (fpsLimit !== undefined) {
2288
- this.fpsLimit = fpsLimit;
2289
- }
2290
- if (data.hdr !== undefined) {
2291
- this.hdr = data.hdr;
2292
- }
2293
- if (data.pauseOnBlur !== undefined) {
2294
- this.pauseOnBlur = data.pauseOnBlur;
2295
- }
2296
- if (data.pauseOnOutsideViewport !== undefined) {
2297
- this.pauseOnOutsideViewport = data.pauseOnOutsideViewport;
2298
- }
2299
- if (data.zLayers !== undefined) {
2300
- this.zLayers = data.zLayers;
2301
- }
1706
+ loadProperty(this, "autoPlay", data.autoPlay);
1707
+ loadProperty(this, "clear", data.clear);
1708
+ loadProperty(this, "key", data.key);
1709
+ loadProperty(this, "name", data.name);
1710
+ loadRangeProperty(this, "delay", data.delay);
1711
+ loadProperty(this, "detectRetina", data.detectRetina);
1712
+ loadRangeProperty(this, "duration", data.duration);
1713
+ loadProperty(this, "fpsLimit", data.fpsLimit);
1714
+ loadProperty(this, "hdr", data.hdr);
1715
+ loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1716
+ loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1717
+ loadProperty(this, "zLayers", data.zLayers);
2302
1718
  this.background.load(data.background);
2303
1719
  const fullScreen = data.fullScreen;
2304
1720
  if (isBoolean(fullScreen)) {
@@ -2310,14 +1726,12 @@
2310
1726
  this.particles.load(data.particles);
2311
1727
  this.resize.load(data.resize);
2312
1728
  this.style = deepExtend(this.style, data.style);
2313
- if (data.smooth !== undefined) {
2314
- this.smooth = data.smooth;
2315
- }
1729
+ loadProperty(this, "smooth", data.smooth);
2316
1730
  this.#pluginManager.plugins.forEach(plugin => {
2317
1731
  plugin.loadOptions(this.#container, this, data);
2318
1732
  });
2319
1733
  }
2320
- #importPalette = palette => {
1734
+ #importPalette(palette) {
2321
1735
  const paletteData = this.#pluginManager.getPalette(palette);
2322
1736
  if (!paletteData) {
2323
1737
  return;
@@ -2334,143 +1748,19 @@
2334
1748
  palette,
2335
1749
  },
2336
1750
  });
2337
- };
2338
- #importPreset = preset => {
2339
- this.load(this.#pluginManager.getPreset(preset));
2340
- };
2341
- }
2342
-
2343
- function paintBase(context, dimension, baseColor) {
2344
- context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
2345
- context.fillRect(originPoint.x, originPoint.y, dimension.width, dimension.height);
2346
- }
2347
- function paintImage(context, dimension, image, opacity) {
2348
- if (!image) {
2349
- return;
2350
- }
2351
- const prevAlpha = context.globalAlpha;
2352
- context.globalAlpha = opacity;
2353
- context.drawImage(image, originPoint.x, originPoint.y, dimension.width, dimension.height);
2354
- context.globalAlpha = prevAlpha;
2355
- }
2356
- function clear(context, dimension) {
2357
- context.clearRect(originPoint.x, originPoint.y, dimension.width, dimension.height);
2358
- }
2359
- function drawParticle(data) {
2360
- const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = defaultZoom, drawPosition = {
2361
- x: pos.x,
2362
- y: pos.y,
2363
- };
2364
- context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
2365
- if (colorStyles.fill) {
2366
- context.fillStyle = colorStyles.fill;
2367
- }
2368
- const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
2369
- context.lineWidth = strokeWidth;
2370
- if (colorStyles.stroke) {
2371
- context.strokeStyle = colorStyles.stroke;
2372
- }
2373
- const drawData = {
2374
- context,
2375
- particle,
2376
- radius,
2377
- drawRadius: radius * drawScale,
2378
- opacity,
2379
- delta,
2380
- pixelRatio: container.retina.pixelRatio,
2381
- fill: fillEnabled,
2382
- stroke: strokeWidth > minStrokeWidth,
2383
- transformData,
2384
- position: { ...pos },
2385
- drawPosition,
2386
- drawScale,
2387
- };
2388
- for (const plugin of container.plugins) {
2389
- plugin.drawParticleTransform?.(drawData);
2390
- }
2391
- const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
2392
- drawBeforeEffect(effect, drawData);
2393
- drawShapeBeforeDraw(shape, drawData);
2394
- drawShape(shape, drawData);
2395
- drawShapeAfterDraw(shape, drawData);
2396
- drawAfterEffect(effect, drawData);
2397
- context.resetTransform();
2398
- }
2399
- function drawAfterEffect(drawer, data) {
2400
- if (!drawer?.drawAfter) {
2401
- return;
2402
- }
2403
- const { particle } = data;
2404
- if (!particle.effect) {
2405
- return;
2406
- }
2407
- drawer.drawAfter(data);
2408
- }
2409
- function drawBeforeEffect(drawer, data) {
2410
- if (!drawer?.drawBefore) {
2411
- return;
2412
- }
2413
- const { particle } = data;
2414
- if (!particle.effect) {
2415
- return;
2416
- }
2417
- drawer.drawBefore(data);
2418
- }
2419
- function drawShape(drawer, data) {
2420
- if (!drawer) {
2421
- return;
2422
- }
2423
- const { context, fill, particle, stroke } = data;
2424
- if (!particle.shape) {
2425
- return;
2426
- }
2427
- context.beginPath();
2428
- drawer.draw(data);
2429
- if (particle.shapeClose) {
2430
- context.closePath();
2431
- }
2432
- if (fill) {
2433
- context.fill();
2434
- }
2435
- if (stroke) {
2436
- context.stroke();
2437
- }
2438
- }
2439
- function drawShapeAfterDraw(drawer, data) {
2440
- if (!drawer?.afterDraw) {
2441
- return;
2442
- }
2443
- const { particle } = data;
2444
- if (!particle.shape) {
2445
- return;
2446
- }
2447
- drawer.afterDraw(data);
2448
- }
2449
- function drawShapeBeforeDraw(drawer, data) {
2450
- if (!drawer?.beforeDraw) {
2451
- return;
2452
1751
  }
2453
- const { particle } = data;
2454
- if (!particle.shape) {
2455
- return;
2456
- }
2457
- drawer.beforeDraw(data);
2458
- }
2459
- function drawParticlePlugin(context, plugin, particle, delta) {
2460
- if (!plugin.drawParticle) {
2461
- return;
1752
+ #importPreset(preset) {
1753
+ this.load(this.#pluginManager.getPreset(preset));
2462
1754
  }
2463
- plugin.drawParticle(context, particle, delta);
2464
1755
  }
2465
1756
 
2466
- const styleCache = new Map(), maxCacheSize = 1000, firstIndex = 0, rgbFixedPrecision = 2, hslFixedPrecision = 2;
1757
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
2467
1758
  function getCachedStyle(key, generator) {
2468
1759
  let cached = styleCache.get(key);
2469
1760
  if (!cached) {
2470
1761
  cached = generator();
2471
- if (styleCache.size >= maxCacheSize) {
2472
- const keysToDelete = [...styleCache.keys()].slice(firstIndex, maxCacheSize * half);
2473
- keysToDelete.forEach(k => styleCache.delete(k));
1762
+ if (styleCache.size > maxStyleCacheSize) {
1763
+ styleCache.clear();
2474
1764
  }
2475
1765
  styleCache.set(key, cached);
2476
1766
  }
@@ -2573,34 +1863,35 @@
2573
1863
  function stringToRgb(pluginManager, input) {
2574
1864
  return stringToRgba(pluginManager, input);
2575
1865
  }
1866
+ function hslChannel(temp1, temp2, temp3) {
1867
+ const temp3Min = 0, temp3Max = 1;
1868
+ if (temp3 < temp3Min) {
1869
+ temp3++;
1870
+ }
1871
+ if (temp3 > temp3Max) {
1872
+ temp3--;
1873
+ }
1874
+ if (temp3 * sextuple < temp3Max) {
1875
+ return temp1 + (temp2 - temp1) * sextuple * temp3;
1876
+ }
1877
+ if (temp3 * double < temp3Max) {
1878
+ return temp2;
1879
+ }
1880
+ if (temp3 * triple < temp3Max * double) {
1881
+ const temp3Offset = double / triple;
1882
+ return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
1883
+ }
1884
+ return temp1;
1885
+ }
2576
1886
  function hslToRgb(hsl) {
2577
1887
  const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
2578
1888
  if (s === sMin) {
2579
1889
  const grayscaleValue = Math.round(lNormalized * rgbMax);
2580
1890
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
2581
1891
  }
2582
- const channel = (temp1, temp2, temp3) => {
2583
- const temp3Min = 0, temp3Max = 1;
2584
- if (temp3 < temp3Min) {
2585
- temp3++;
2586
- }
2587
- if (temp3 > temp3Max) {
2588
- temp3--;
2589
- }
2590
- if (temp3 * sextuple < temp3Max) {
2591
- return temp1 + (temp2 - temp1) * sextuple * temp3;
2592
- }
2593
- if (temp3 * double < temp3Max) {
2594
- return temp2;
2595
- }
2596
- if (temp3 * triple < temp3Max * double) {
2597
- const temp3Offset = double / triple;
2598
- return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
2599
- }
2600
- return temp1;
2601
- }, temp1 = lNormalized < half
1892
+ const temp1 = lNormalized < half
2602
1893
  ? lNormalized * (sNormalizedOffset + sNormalized)
2603
- : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * channel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * channel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * channel(temp2, temp1, hNormalized - phaseThird));
1894
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
2604
1895
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
2605
1896
  }
2606
1897
  function hslaToRgba(hsla) {
@@ -2613,7 +1904,7 @@
2613
1904
  };
2614
1905
  }
2615
1906
  function getRandomRgbColor(min) {
2616
- const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity$1, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1907
+ const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
2617
1908
  return {
2618
1909
  b: getRgbInRangeValue(),
2619
1910
  g: getRgbInRangeValue(),
@@ -2624,21 +1915,18 @@
2624
1915
  const op = opacity ?? defaultOpacity$1, key = `rgb-${color.r.toFixed(rgbFixedPrecision)}-${color.g.toFixed(rgbFixedPrecision)}-${color.b.toFixed(rgbFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2625
1916
  return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2626
1917
  }
2627
- function getHdrStyleFromRgb(color, opacity) {
2628
- return `color(display-p3 ${(color.r / rgbMax).toString()} ${(color.g / rgbMax).toString()} ${(color.b / rgbMax).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
1918
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1919
+ const headroom = peakNits / sdrReferenceWhiteNits;
1920
+ return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2629
1921
  }
2630
1922
  function getSdrStyleFromRgb(color, opacity) {
2631
1923
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
2632
1924
  }
2633
1925
  function getStyleFromHsl(color, hdr, opacity) {
2634
1926
  const op = opacity ?? defaultOpacity$1, key = `hsl-${color.h.toFixed(hslFixedPrecision)}-${color.s.toFixed(hslFixedPrecision)}-${color.l.toFixed(hslFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2635
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromHsl(color, opacity) : getSdrStyleFromHsl(color, opacity)));
2636
- }
2637
- function getHdrStyleFromHsl(color, opacity) {
2638
- return getHdrStyleFromRgb(hslToRgb(color), opacity);
2639
- }
2640
- function getSdrStyleFromHsl(color, opacity) {
2641
- return `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${(opacity ?? defaultOpacity$1).toString()})`;
1927
+ return getCachedStyle(key, () => hdr
1928
+ ? getStyleFromRgb(hslToRgb(color), true, opacity)
1929
+ : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
2642
1930
  }
2643
1931
  function getHslFromAnimation(animation) {
2644
1932
  return animation === undefined
@@ -2760,22 +2048,14 @@
2760
2048
  const tsParticles = initEngine();
2761
2049
 
2762
2050
  class Blend {
2763
- enable;
2764
- mode;
2765
- constructor() {
2766
- this.mode = "destination-out";
2767
- this.enable = false;
2768
- }
2051
+ enable = false;
2052
+ mode = "destination-out";
2769
2053
  load(data) {
2770
2054
  if (isNull(data)) {
2771
2055
  return;
2772
2056
  }
2773
- if (data.mode !== undefined) {
2774
- this.mode = data.mode;
2775
- }
2776
- if (data.enable !== undefined) {
2777
- this.enable = data.enable;
2778
- }
2057
+ loadProperty(this, "mode", data.mode);
2058
+ loadProperty(this, "enable", data.enable);
2779
2059
  }
2780
2060
  }
2781
2061
 
@@ -2805,7 +2085,7 @@
2805
2085
  }
2806
2086
 
2807
2087
  async function loadBlendPlugin(engine) {
2808
- engine.checkVersion("4.1.2");
2088
+ engine.checkVersion("4.2.0");
2809
2089
  await engine.pluginManager.register(e => {
2810
2090
  e.pluginManager.addPlugin(new BlendPlugin());
2811
2091
  });
@@ -2842,7 +2122,7 @@
2842
2122
  }
2843
2123
 
2844
2124
  async function loadCircleShape(engine) {
2845
- engine.checkVersion("4.1.2");
2125
+ engine.checkVersion("4.2.0");
2846
2126
  await engine.pluginManager.register(e => {
2847
2127
  e.pluginManager.addShape(["circle"], () => {
2848
2128
  return Promise.resolve(new CircleDrawer());
@@ -2890,7 +2170,7 @@
2890
2170
  }
2891
2171
 
2892
2172
  async function loadHexColorPlugin(engine) {
2893
- engine.checkVersion("4.1.2");
2173
+ engine.checkVersion("4.2.0");
2894
2174
  await engine.pluginManager.register(e => {
2895
2175
  e.pluginManager.addColorManager("hex", new HexColorManager());
2896
2176
  });
@@ -2943,7 +2223,7 @@
2943
2223
  }
2944
2224
 
2945
2225
  async function loadHslColorPlugin(engine) {
2946
- engine.checkVersion("4.1.2");
2226
+ engine.checkVersion("4.2.0");
2947
2227
  await engine.pluginManager.register(e => {
2948
2228
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2949
2229
  });
@@ -2967,7 +2247,7 @@
2967
2247
  }
2968
2248
 
2969
2249
  async function loadMovePlugin(engine) {
2970
- engine.checkVersion("4.1.2");
2250
+ engine.checkVersion("4.2.0");
2971
2251
  await engine.pluginManager.register(e => {
2972
2252
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2973
2253
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2985,31 +2265,137 @@
2985
2265
  });
2986
2266
  }
2987
2267
 
2988
- class OpacityAnimation extends RangedAnimationOptions {
2989
- destroy;
2990
- constructor() {
2991
- super();
2992
- this.destroy = DestroyType.none;
2993
- this.speed = 2;
2268
+ function checkDestroy(particle, destroyType, value, minValue, maxValue) {
2269
+ switch (destroyType) {
2270
+ case DestroyType.max:
2271
+ if (value >= maxValue) {
2272
+ particle.destroy();
2273
+ }
2274
+ break;
2275
+ case DestroyType.min:
2276
+ if (value <= minValue) {
2277
+ particle.destroy();
2278
+ }
2279
+ break;
2280
+ }
2281
+ }
2282
+ function initParticleNumericAnimationValue(options, pxRatio) {
2283
+ const valueRange = options.value, animationOptions = options.animation, res = {
2284
+ delayTime: getRangeValue(animationOptions.delay) * millisecondsToSeconds,
2285
+ enable: animationOptions.enable,
2286
+ value: getRangeValue(options.value) * pxRatio,
2287
+ max: getRangeMax(valueRange) * pxRatio,
2288
+ min: getRangeMin(valueRange) * pxRatio,
2289
+ loops: 0,
2290
+ maxLoops: getRangeValue(animationOptions.count),
2291
+ time: 0,
2292
+ }, decayOffset = 1;
2293
+ if (animationOptions.enable) {
2294
+ res.decay = decayOffset - getRangeValue(animationOptions.decay);
2295
+ switch (animationOptions.mode) {
2296
+ case AnimationMode.increase:
2297
+ res.status = AnimationStatus.increasing;
2298
+ break;
2299
+ case AnimationMode.decrease:
2300
+ res.status = AnimationStatus.decreasing;
2301
+ break;
2302
+ case AnimationMode.random:
2303
+ res.status = getRandom() >= half ? AnimationStatus.increasing : AnimationStatus.decreasing;
2304
+ break;
2305
+ }
2306
+ const autoStatus = animationOptions.mode === AnimationMode.auto;
2307
+ switch (animationOptions.startValue) {
2308
+ case StartValueType.min:
2309
+ res.value = res.min;
2310
+ if (autoStatus) {
2311
+ res.status = AnimationStatus.increasing;
2312
+ }
2313
+ break;
2314
+ case StartValueType.max:
2315
+ res.value = res.max;
2316
+ if (autoStatus) {
2317
+ res.status = AnimationStatus.decreasing;
2318
+ }
2319
+ break;
2320
+ case StartValueType.random:
2321
+ default:
2322
+ res.value = randomInRangeValue(res);
2323
+ if (autoStatus) {
2324
+ res.status = getRandom() >= half ? AnimationStatus.increasing : AnimationStatus.decreasing;
2325
+ }
2326
+ break;
2327
+ }
2328
+ }
2329
+ res.initialValue = res.value;
2330
+ return res;
2331
+ }
2332
+ function updateAnimation(particle, data, changeDirection, destroyType, delta) {
2333
+ const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minDecay = 1;
2334
+ if (particle.destroyed ||
2335
+ !data.enable ||
2336
+ ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
2337
+ return;
2338
+ }
2339
+ const velocity = (data.velocity ?? minVelocity) * delta.factor, minValue = data.min, maxValue = data.max, decay = data.decay ?? minDecay;
2340
+ data.time ??= 0;
2341
+ const delayTime = data.delayTime ?? minDelay;
2342
+ if (delayTime > minDelay && data.time < delayTime) {
2343
+ data.time += delta.value;
2344
+ if (data.time < delayTime) {
2345
+ return;
2346
+ }
2347
+ }
2348
+ switch (data.status) {
2349
+ case AnimationStatus.increasing:
2350
+ data.value += velocity;
2351
+ break;
2352
+ case AnimationStatus.decreasing:
2353
+ data.value -= velocity;
2354
+ break;
2355
+ }
2356
+ if (data.velocity && decay !== identity) {
2357
+ data.velocity *= decay;
2358
+ }
2359
+ switch (data.status) {
2360
+ case AnimationStatus.increasing:
2361
+ if (data.value >= maxValue) {
2362
+ {
2363
+ data.status = AnimationStatus.decreasing;
2364
+ }
2365
+ data.loops ??= minLoops;
2366
+ data.loops++;
2367
+ }
2368
+ break;
2369
+ case AnimationStatus.decreasing:
2370
+ if (data.value <= minValue) {
2371
+ {
2372
+ data.status = AnimationStatus.increasing;
2373
+ }
2374
+ data.loops ??= minLoops;
2375
+ data.loops++;
2376
+ }
2377
+ break;
2994
2378
  }
2379
+ checkDestroy(particle, destroyType, data.value, minValue, maxValue);
2380
+ if (!particle.destroyed) {
2381
+ data.value = clamp(data.value, minValue, maxValue);
2382
+ }
2383
+ }
2384
+
2385
+ class OpacityAnimation extends RangedAnimationOptions {
2386
+ destroy = DestroyType.none;
2995
2387
  load(data) {
2996
2388
  super.load(data);
2997
2389
  if (isNull(data)) {
2998
2390
  return;
2999
2391
  }
3000
- if (data.destroy !== undefined) {
3001
- this.destroy = data.destroy;
3002
- }
2392
+ loadProperty(this, "destroy", data.destroy);
3003
2393
  }
3004
2394
  }
3005
2395
 
3006
2396
  class Opacity extends RangedAnimationValueWithRandom {
3007
- animation;
3008
- constructor() {
3009
- super();
3010
- this.animation = new OpacityAnimation();
3011
- this.value = 1;
3012
- }
2397
+ animation = new OpacityAnimation();
2398
+ value = 1;
3013
2399
  load(data) {
3014
2400
  if (isNull(data)) {
3015
2401
  return;
@@ -3053,10 +2439,7 @@
3053
2439
  (particle.opacity.loops ?? none) < (particle.opacity.maxLoops ?? none))));
3054
2440
  }
3055
2441
  loadOptions(options, ...sources) {
3056
- options.opacity ??= new Opacity();
3057
- for (const source of sources) {
3058
- options.opacity.load(source?.opacity);
3059
- }
2442
+ loadOptionProperty(options, "opacity", Opacity, ...sources);
3060
2443
  }
3061
2444
  reset(particle) {
3062
2445
  if (!particle.opacity) {
@@ -3074,7 +2457,7 @@
3074
2457
  }
3075
2458
 
3076
2459
  async function loadOpacityUpdater(engine) {
3077
- engine.checkVersion("4.1.2");
2460
+ engine.checkVersion("4.2.0");
3078
2461
  await engine.pluginManager.register(e => {
3079
2462
  e.pluginManager.addParticleUpdater("opacity", container => {
3080
2463
  return Promise.resolve(new OpacityUpdater(container));
@@ -3082,7 +2465,7 @@
3082
2465
  });
3083
2466
  }
3084
2467
 
3085
- const minVelocity$4 = 0, boundsMin = 0;
2468
+ const boundsMin = 0;
3086
2469
  function bounceHorizontal(data) {
3087
2470
  if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
3088
2471
  (data.direction !== OutModeDirection.left && data.direction !== OutModeDirection.right)) {
@@ -3097,8 +2480,8 @@
3097
2480
  const velocity = data.particle.velocity.x;
3098
2481
  let bounced = false;
3099
2482
  if (data.outOfCanvas &&
3100
- ((data.direction === OutModeDirection.right && velocity > minVelocity$4) ||
3101
- (data.direction === OutModeDirection.left && velocity < minVelocity$4))) {
2483
+ ((data.direction === OutModeDirection.right && velocity > minVelocity) ||
2484
+ (data.direction === OutModeDirection.left && velocity < minVelocity))) {
3102
2485
  const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
3103
2486
  data.particle.velocity.x *= -newVelocity;
3104
2487
  bounced = true;
@@ -3131,8 +2514,8 @@
3131
2514
  const velocity = data.particle.velocity.y;
3132
2515
  let bounced = false;
3133
2516
  if (data.outOfCanvas &&
3134
- ((data.direction === OutModeDirection.bottom && velocity > minVelocity$4) ||
3135
- (data.direction === OutModeDirection.top && velocity < minVelocity$4))) {
2517
+ ((data.direction === OutModeDirection.bottom && velocity > minVelocity) ||
2518
+ (data.direction === OutModeDirection.top && velocity < minVelocity))) {
3136
2519
  const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
3137
2520
  data.particle.velocity.y *= -newVelocity;
3138
2521
  bounced = true;
@@ -3185,7 +2568,6 @@
3185
2568
  }
3186
2569
  }
3187
2570
 
3188
- const minVelocity$3 = 0;
3189
2571
  class DestroyOutMode {
3190
2572
  modes;
3191
2573
  constructor(_container) {
@@ -3204,10 +2586,10 @@
3204
2586
  break;
3205
2587
  case ParticleOutType.inside: {
3206
2588
  const { dx, dy } = getDistances(particle.position, particle.moveCenter), { x: vx, y: vy } = particle.velocity;
3207
- if ((vx < minVelocity$3 && dx > particle.moveCenter.radius) ||
3208
- (vy < minVelocity$3 && dy > particle.moveCenter.radius) ||
3209
- (vx >= minVelocity$3 && dx < -particle.moveCenter.radius) ||
3210
- (vy >= minVelocity$3 && dy < -particle.moveCenter.radius)) {
2589
+ if ((vx < minVelocity && dx > particle.moveCenter.radius) ||
2590
+ (vy < minVelocity && dy > particle.moveCenter.radius) ||
2591
+ (vx >= minVelocity && dx < -particle.moveCenter.radius) ||
2592
+ (vy >= minVelocity && dy < -particle.moveCenter.radius)) {
3211
2593
  return;
3212
2594
  }
3213
2595
  break;
@@ -3217,7 +2599,6 @@
3217
2599
  }
3218
2600
  }
3219
2601
 
3220
- const minVelocity$2 = 0;
3221
2602
  class NoneOutMode {
3222
2603
  modes;
3223
2604
  #container;
@@ -3237,10 +2618,10 @@
3237
2618
  }
3238
2619
  const gravityOptions = particle.options.move.gravity, container = this.#container, canvasSize = container.canvas.size, pRadius = particle.getRadius();
3239
2620
  if (!gravityOptions.enable) {
3240
- if ((particle.velocity.y > minVelocity$2 && particle.position.y <= canvasSize.height + pRadius) ||
3241
- (particle.velocity.y < minVelocity$2 && particle.position.y >= -pRadius) ||
3242
- (particle.velocity.x > minVelocity$2 && particle.position.x <= canvasSize.width + pRadius) ||
3243
- (particle.velocity.x < minVelocity$2 && particle.position.x >= -pRadius)) {
2621
+ if ((particle.velocity.y > minVelocity && particle.position.y <= canvasSize.height + pRadius) ||
2622
+ (particle.velocity.y < minVelocity && particle.position.y >= -pRadius) ||
2623
+ (particle.velocity.x > minVelocity && particle.position.x <= canvasSize.width + pRadius) ||
2624
+ (particle.velocity.x < minVelocity && particle.position.x >= -pRadius)) {
3244
2625
  return;
3245
2626
  }
3246
2627
  if (!isPointInside(particle.position, container.canvas.size, originPoint, pRadius, direction)) {
@@ -3259,7 +2640,7 @@
3259
2640
  }
3260
2641
  }
3261
2642
 
3262
- const minVelocity$1 = 0, minDistance = 0, updateVector = Vector.origin;
2643
+ const updateVector = Vector.origin;
3263
2644
  class OutOutMode {
3264
2645
  modes;
3265
2646
  #container;
@@ -3280,10 +2661,10 @@
3280
2661
  updateVector.angle = particle.velocity.angle + Math.PI;
3281
2662
  updateVector.addTo(particle.moveCenter);
3282
2663
  const { dx, dy } = getDistances(particle.position, updateVector);
3283
- if ((vx <= minVelocity$1 && dx >= minDistance) ||
3284
- (vy <= minVelocity$1 && dy >= minDistance) ||
3285
- (vx >= minVelocity$1 && dx <= minDistance) ||
3286
- (vy >= minVelocity$1 && dy <= minDistance)) {
2664
+ if ((vx <= minVelocity && dx >= minDistance) ||
2665
+ (vy <= minVelocity && dy >= minDistance) ||
2666
+ (vx >= minVelocity && dx <= minDistance) ||
2667
+ (vy >= minVelocity && dy <= minDistance)) {
3287
2668
  return;
3288
2669
  }
3289
2670
  particle.position.x = Math.floor(randomInRangeValue({
@@ -3407,21 +2788,21 @@
3407
2788
  this.#updateOutMode(particle, delta, outModes.right ?? outModes.default, OutModeDirection.right);
3408
2789
  this.#updateOutMode(particle, delta, outModes.top ?? outModes.default, OutModeDirection.top);
3409
2790
  }
3410
- #addUpdaterIfMissing = (particle, outMode, getUpdater) => {
2791
+ #addUpdaterIfMissing(particle, outMode, getUpdater) {
3411
2792
  const outModes = particle.options.move.outModes;
3412
2793
  if (!this.updaters.has(outMode) && checkOutMode(outModes, outMode)) {
3413
2794
  this.updaters.set(outMode, getUpdater(this.#container));
3414
2795
  }
3415
- };
3416
- #updateOutMode = (particle, delta, outMode, direction) => {
2796
+ }
2797
+ #updateOutMode(particle, delta, outMode, direction) {
3417
2798
  for (const updater of this.updaters.values()) {
3418
2799
  updater.update(particle, direction, delta, outMode);
3419
2800
  }
3420
- };
2801
+ }
3421
2802
  }
3422
2803
 
3423
2804
  async function loadOutModesUpdater(engine) {
3424
- engine.checkVersion("4.1.2");
2805
+ engine.checkVersion("4.2.0");
3425
2806
  await engine.pluginManager.register(e => {
3426
2807
  e.pluginManager.addParticleUpdater("outModes", container => {
3427
2808
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3492,7 +2873,7 @@
3492
2873
  }
3493
2874
 
3494
2875
  async function loadPaintUpdater(engine) {
3495
- engine.checkVersion("4.1.2");
2876
+ engine.checkVersion("4.2.0");
3496
2877
  await engine.pluginManager.register(e => {
3497
2878
  e.pluginManager.addParticleUpdater("paint", container => {
3498
2879
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3547,37 +2928,26 @@
3547
2928
  }
3548
2929
 
3549
2930
  async function loadRgbColorPlugin(engine) {
3550
- engine.checkVersion("4.1.2");
2931
+ engine.checkVersion("4.2.0");
3551
2932
  await engine.pluginManager.register(e => {
3552
2933
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3553
2934
  });
3554
2935
  }
3555
2936
 
3556
2937
  class SizeAnimation extends RangedAnimationOptions {
3557
- destroy;
3558
- constructor() {
3559
- super();
3560
- this.destroy = DestroyType.none;
3561
- this.speed = 5;
3562
- }
2938
+ destroy = DestroyType.none;
3563
2939
  load(data) {
3564
2940
  super.load(data);
3565
2941
  if (isNull(data)) {
3566
2942
  return;
3567
2943
  }
3568
- if (data.destroy !== undefined) {
3569
- this.destroy = data.destroy;
3570
- }
2944
+ loadProperty(this, "destroy", data.destroy);
3571
2945
  }
3572
2946
  }
3573
2947
 
3574
- class Size extends RangedAnimationValueWithRandom {
3575
- animation;
3576
- constructor() {
3577
- super();
3578
- this.animation = new SizeAnimation();
3579
- this.value = 3;
3580
- }
2948
+ class Size extends RangedAnimationValueWithRandom {
2949
+ animation = new SizeAnimation();
2950
+ value = 3;
3581
2951
  load(data) {
3582
2952
  super.load(data);
3583
2953
  if (isNull(data)) {
@@ -3620,10 +2990,7 @@
3620
2990
  (particle.size.loops ?? minLoops) < (particle.size.maxLoops ?? minLoops))));
3621
2991
  }
3622
2992
  loadOptions(options, ...sources) {
3623
- options.size ??= new Size();
3624
- for (const source of sources) {
3625
- options.size.load(source?.size);
3626
- }
2993
+ loadOptionProperty(options, "size", Size, ...sources);
3627
2994
  }
3628
2995
  preInit(particle) {
3629
2996
  const pxRatio = this.#container.retina.pixelRatio, options = particle.options, sizeOptions = options.size;
@@ -3646,7 +3013,7 @@
3646
3013
  }
3647
3014
 
3648
3015
  async function loadSizeUpdater(engine) {
3649
- engine.checkVersion("4.1.2");
3016
+ engine.checkVersion("4.2.0");
3650
3017
  await engine.pluginManager.register(e => {
3651
3018
  e.pluginManager.addParticleUpdater("size", container => {
3652
3019
  return Promise.resolve(new SizeUpdater(container));
@@ -3655,7 +3022,7 @@
3655
3022
  }
3656
3023
 
3657
3024
  async function loadBasic(engine) {
3658
- engine.checkVersion("4.1.2");
3025
+ engine.checkVersion("4.2.0");
3659
3026
  await engine.pluginManager.register(async (e) => {
3660
3027
  await Promise.all([
3661
3028
  loadBlendPlugin(e),
@@ -3676,78 +3043,46 @@
3676
3043
  count;
3677
3044
  delay;
3678
3045
  duration;
3679
- wait;
3680
- constructor() {
3681
- this.wait = false;
3682
- }
3046
+ wait = false;
3683
3047
  load(data) {
3684
3048
  if (isNull(data)) {
3685
3049
  return;
3686
3050
  }
3687
- if (data.count !== undefined) {
3688
- this.count = data.count;
3689
- }
3690
- if (data.delay !== undefined) {
3691
- this.delay = setRangeValue(data.delay);
3692
- }
3693
- if (data.duration !== undefined) {
3694
- this.duration = setRangeValue(data.duration);
3695
- }
3696
- if (data.wait !== undefined) {
3697
- this.wait = data.wait;
3698
- }
3051
+ loadProperty(this, "count", data.count);
3052
+ loadRangeProperty(this, "delay", data.delay);
3053
+ loadRangeProperty(this, "duration", data.duration);
3054
+ loadProperty(this, "wait", data.wait);
3699
3055
  }
3700
3056
  }
3701
3057
 
3702
3058
  class EmitterRate {
3703
- delay;
3704
- quantity;
3705
- constructor() {
3706
- this.quantity = 1;
3707
- this.delay = 0.1;
3708
- }
3059
+ delay = 0.1;
3060
+ quantity = 1;
3709
3061
  load(data) {
3710
3062
  if (isNull(data)) {
3711
3063
  return;
3712
3064
  }
3713
- if (data.quantity !== undefined) {
3714
- this.quantity = setRangeValue(data.quantity);
3715
- }
3716
- if (data.delay !== undefined) {
3717
- this.delay = setRangeValue(data.delay);
3718
- }
3065
+ loadRangeProperty(this, "quantity", data.quantity);
3066
+ loadRangeProperty(this, "delay", data.delay);
3719
3067
  }
3720
3068
  }
3721
3069
 
3722
3070
  class EmitterShapeReplace {
3723
- color;
3724
- opacity;
3725
- constructor() {
3726
- this.color = false;
3727
- this.opacity = false;
3728
- }
3071
+ color = false;
3072
+ opacity = false;
3729
3073
  load(data) {
3730
3074
  if (isNull(data)) {
3731
3075
  return;
3732
3076
  }
3733
- if (data.color !== undefined) {
3734
- this.color = data.color;
3735
- }
3736
- if (data.opacity !== undefined) {
3737
- this.opacity = data.opacity;
3738
- }
3077
+ loadProperty(this, "color", data.color);
3078
+ loadProperty(this, "opacity", data.opacity);
3739
3079
  }
3740
3080
  }
3741
3081
 
3742
3082
  class EmitterShape {
3743
- options;
3744
- replace;
3745
- type;
3746
- constructor() {
3747
- this.options = {};
3748
- this.replace = new EmitterShapeReplace();
3749
- this.type = "square";
3750
- }
3083
+ options = {};
3084
+ replace = new EmitterShapeReplace();
3085
+ type = "square";
3751
3086
  load(data) {
3752
3087
  if (isNull(data)) {
3753
3088
  return;
@@ -3756,34 +3091,21 @@
3756
3091
  this.options = deepExtend({}, data.options ?? {});
3757
3092
  }
3758
3093
  this.replace.load(data.replace);
3759
- if (data.type !== undefined) {
3760
- this.type = data.type;
3761
- }
3094
+ loadProperty(this, "type", data.type);
3762
3095
  }
3763
3096
  }
3764
3097
 
3765
3098
  class EmitterSize {
3766
- height;
3767
- mode;
3768
- width;
3769
- constructor() {
3770
- this.mode = PixelMode.percent;
3771
- this.height = 0;
3772
- this.width = 0;
3773
- }
3099
+ height = 0;
3100
+ mode = PixelMode.percent;
3101
+ width = 0;
3774
3102
  load(data) {
3775
3103
  if (isNull(data)) {
3776
3104
  return;
3777
3105
  }
3778
- if (data.mode !== undefined) {
3779
- this.mode = data.mode;
3780
- }
3781
- if (data.height !== undefined) {
3782
- this.height = data.height;
3783
- }
3784
- if (data.width !== undefined) {
3785
- this.width = data.width;
3786
- }
3106
+ loadProperty(this, "mode", data.mode);
3107
+ loadProperty(this, "height", data.height);
3108
+ loadProperty(this, "width", data.width);
3787
3109
  }
3788
3110
  }
3789
3111
 
@@ -3806,50 +3128,35 @@
3806
3128
  }
3807
3129
 
3808
3130
  class Emitter {
3809
- autoPlay;
3131
+ autoPlay = true;
3810
3132
  direction;
3811
3133
  domId;
3812
- fill;
3813
- life;
3134
+ fill = true;
3135
+ life = new EmitterLife();
3814
3136
  name;
3815
3137
  particles;
3816
3138
  position;
3817
- rate;
3818
- shape;
3139
+ rate = new EmitterRate();
3140
+ shape = new EmitterShape();
3819
3141
  size;
3820
- spawn;
3142
+ spawn = new EmitterSpawn();
3821
3143
  spawnFillColor;
3822
3144
  spawnStrokeColor;
3823
- startCount;
3824
- constructor() {
3825
- this.autoPlay = true;
3826
- this.fill = true;
3827
- this.life = new EmitterLife();
3828
- this.rate = new EmitterRate();
3829
- this.shape = new EmitterShape();
3830
- this.spawn = new EmitterSpawn();
3831
- this.startCount = 0;
3832
- }
3145
+ startCount = 0;
3833
3146
  load(data) {
3834
3147
  if (isNull(data)) {
3835
3148
  return;
3836
3149
  }
3837
- if (data.autoPlay !== undefined) {
3838
- this.autoPlay = data.autoPlay;
3839
- }
3150
+ loadProperty(this, "autoPlay", data.autoPlay);
3840
3151
  if (data.size !== undefined) {
3841
3152
  this.size ??= new EmitterSize();
3842
3153
  this.size.load(data.size);
3843
3154
  }
3844
- if (data.direction !== undefined) {
3845
- this.direction = data.direction;
3846
- }
3847
- this.domId = data.domId;
3848
- if (data.fill !== undefined) {
3849
- this.fill = data.fill;
3850
- }
3155
+ loadProperty(this, "direction", data.direction);
3156
+ loadProperty(this, "domId", data.domId);
3157
+ loadProperty(this, "fill", data.fill);
3851
3158
  this.life.load(data.life);
3852
- this.name = data.name;
3159
+ loadProperty(this, "name", data.name);
3853
3160
  this.particles = executeOnSingleOrMultiple(data.particles, particles => {
3854
3161
  return deepExtend({}, particles);
3855
3162
  });
@@ -3873,9 +3180,7 @@
3873
3180
  this.spawnStrokeColor ??= new AnimatableColor();
3874
3181
  this.spawnStrokeColor.load(data.spawnStrokeColor);
3875
3182
  }
3876
- if (data.startCount !== undefined) {
3877
- this.startCount = data.startCount;
3878
- }
3183
+ loadProperty(this, "startCount", data.startCount);
3879
3184
  }
3880
3185
  }
3881
3186
 
@@ -3940,7 +3245,7 @@
3940
3245
  })(EmitterClickMode || (EmitterClickMode = {}));
3941
3246
 
3942
3247
  async function loadEmittersPluginSimple(engine) {
3943
- engine.checkVersion("4.1.2");
3248
+ engine.checkVersion("4.2.0");
3944
3249
  await engine.pluginManager.register(async (e) => {
3945
3250
  const instancesManager = await getEmittersInstancesManager(e);
3946
3251
  await addEmittersShapesManager(e);
@@ -4071,7 +3376,7 @@
4071
3376
  return;
4072
3377
  }
4073
3378
  this.draw(ctx => {
4074
- clear(ctx, this.#canvasManager.size);
3379
+ ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4075
3380
  });
4076
3381
  }
4077
3382
  clear() {
@@ -4133,7 +3438,7 @@
4133
3438
  plugin.drawParticleSetup?.(context, particle, delta);
4134
3439
  }
4135
3440
  this.#applyPreDrawUpdaters(context, particle, radius, opacity, colorStyles, transform);
4136
- drawParticle({
3441
+ this.#drawParticle({
4137
3442
  container,
4138
3443
  context,
4139
3444
  particle,
@@ -4152,7 +3457,7 @@
4152
3457
  drawParticlePlugins(particle, delta) {
4153
3458
  this.draw(ctx => {
4154
3459
  for (const plugin of this.#drawParticlePlugins) {
4155
- drawParticlePlugin(ctx, plugin, particle, delta);
3460
+ this.#drawParticlePlugin(ctx, plugin, particle, delta);
4156
3461
  }
4157
3462
  });
4158
3463
  }
@@ -4252,12 +3557,19 @@
4252
3557
  }
4253
3558
  paintBase(baseColor) {
4254
3559
  this.draw(ctx => {
4255
- paintBase(ctx, this.#canvasManager.size, baseColor);
3560
+ ctx.fillStyle = baseColor ?? "rgba(0,0,0,0)";
3561
+ ctx.fillRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4256
3562
  });
4257
3563
  }
4258
3564
  paintImage(image, opacity) {
4259
3565
  this.draw(ctx => {
4260
- paintImage(ctx, this.#canvasManager.size, image, opacity);
3566
+ if (!image) {
3567
+ return;
3568
+ }
3569
+ const prevAlpha = ctx.globalAlpha;
3570
+ ctx.globalAlpha = opacity;
3571
+ ctx.drawImage(image, originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
3572
+ ctx.globalAlpha = prevAlpha;
4261
3573
  });
4262
3574
  }
4263
3575
  setContext(context) {
@@ -4271,15 +3583,15 @@
4271
3583
  }
4272
3584
  stop() {
4273
3585
  this.draw(ctx => {
4274
- clear(ctx, this.#canvasManager.size);
3586
+ ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4275
3587
  });
4276
3588
  }
4277
- #applyPostDrawUpdaters = particle => {
3589
+ #applyPostDrawUpdaters(particle) {
4278
3590
  for (const updater of this.#postDrawUpdaters) {
4279
3591
  updater.afterDraw?.(particle);
4280
3592
  }
4281
- };
4282
- #applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
3593
+ }
3594
+ #applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform) {
4283
3595
  for (const updater of this.#preDrawUpdaters) {
4284
3596
  if (updater.getColorStyles) {
4285
3597
  const { fill, stroke } = updater.getColorStyles(particle, ctx, radius, zOpacity);
@@ -4298,8 +3610,114 @@
4298
3610
  }
4299
3611
  updater.beforeDraw?.(particle);
4300
3612
  }
4301
- };
4302
- #getPluginParticleColors = particle => {
3613
+ }
3614
+ #drawAfterEffect(drawer, data) {
3615
+ if (!drawer?.drawAfter) {
3616
+ return;
3617
+ }
3618
+ const { particle } = data;
3619
+ if (!particle.effect) {
3620
+ return;
3621
+ }
3622
+ drawer.drawAfter(data);
3623
+ }
3624
+ #drawBeforeEffect(drawer, data) {
3625
+ if (!drawer?.drawBefore) {
3626
+ return;
3627
+ }
3628
+ const { particle } = data;
3629
+ if (!particle.effect) {
3630
+ return;
3631
+ }
3632
+ drawer.drawBefore(data);
3633
+ }
3634
+ #drawParticle(data) {
3635
+ const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = defaultZoom, drawPosition = {
3636
+ x: pos.x,
3637
+ y: pos.y,
3638
+ };
3639
+ context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
3640
+ if (colorStyles.fill) {
3641
+ context.fillStyle = colorStyles.fill;
3642
+ }
3643
+ const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
3644
+ context.lineWidth = strokeWidth;
3645
+ if (colorStyles.stroke) {
3646
+ context.strokeStyle = colorStyles.stroke;
3647
+ }
3648
+ const drawData = {
3649
+ context,
3650
+ particle,
3651
+ radius,
3652
+ drawRadius: radius * drawScale,
3653
+ opacity,
3654
+ delta,
3655
+ pixelRatio: container.retina.pixelRatio,
3656
+ fill: fillEnabled,
3657
+ stroke: strokeWidth > minStrokeWidth,
3658
+ transformData,
3659
+ position: { ...pos },
3660
+ drawPosition,
3661
+ drawScale,
3662
+ };
3663
+ for (const plugin of container.plugins) {
3664
+ plugin.drawParticleTransform?.(drawData);
3665
+ }
3666
+ const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
3667
+ this.#drawBeforeEffect(effect, drawData);
3668
+ this.#drawShapeBeforeDraw(shape, drawData);
3669
+ this.#drawShape(shape, drawData);
3670
+ this.#drawShapeAfterDraw(shape, drawData);
3671
+ this.#drawAfterEffect(effect, drawData);
3672
+ context.resetTransform();
3673
+ }
3674
+ #drawParticlePlugin(context, plugin, particle, delta) {
3675
+ if (!plugin.drawParticle) {
3676
+ return;
3677
+ }
3678
+ plugin.drawParticle(context, particle, delta);
3679
+ }
3680
+ #drawShape(drawer, data) {
3681
+ if (!drawer) {
3682
+ return;
3683
+ }
3684
+ const { context, fill, particle, stroke } = data;
3685
+ if (!particle.shape) {
3686
+ return;
3687
+ }
3688
+ context.beginPath();
3689
+ drawer.draw(data);
3690
+ if (particle.shapeClose) {
3691
+ context.closePath();
3692
+ }
3693
+ if (fill) {
3694
+ context.fill();
3695
+ }
3696
+ if (stroke) {
3697
+ context.stroke();
3698
+ }
3699
+ }
3700
+ #drawShapeAfterDraw(drawer, data) {
3701
+ if (!drawer?.afterDraw) {
3702
+ return;
3703
+ }
3704
+ const { particle } = data;
3705
+ if (!particle.shape) {
3706
+ return;
3707
+ }
3708
+ drawer.afterDraw(data);
3709
+ }
3710
+ #drawShapeBeforeDraw(drawer, data) {
3711
+ if (!drawer?.beforeDraw) {
3712
+ return;
3713
+ }
3714
+ const { particle } = data;
3715
+ if (!particle.shape) {
3716
+ return;
3717
+ }
3718
+ drawer.beforeDraw(data);
3719
+ }
3720
+ #getPluginParticleColors(particle) {
4303
3721
  let fColor, sColor;
4304
3722
  for (const plugin of this.#colorPlugins) {
4305
3723
  if (!fColor && plugin.particleFillColor) {
@@ -4315,7 +3733,7 @@
4315
3733
  this.#reusablePluginColors[fColorIndex] = fColor;
4316
3734
  this.#reusablePluginColors[sColorIndex] = sColor;
4317
3735
  return this.#reusablePluginColors;
4318
- };
3736
+ }
4319
3737
  }
4320
3738
 
4321
3739
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4447,6 +3865,7 @@
4447
3865
  obs.observe(element, { attributes: true });
4448
3866
  });
4449
3867
  this.initPlugins();
3868
+ this.#initContext();
4450
3869
  this.render.init();
4451
3870
  }
4452
3871
  initBackground() {
@@ -4456,7 +3875,7 @@
4456
3875
  }
4457
3876
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4458
3877
  if (color) {
4459
- elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity);
3878
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4460
3879
  }
4461
3880
  else {
4462
3881
  elementStyle.backgroundColor = "";
@@ -4478,7 +3897,7 @@
4478
3897
  if (this.#generated && this.domElement) {
4479
3898
  this.domElement.remove();
4480
3899
  }
4481
- const container = this.#container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
3900
+ const domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4482
3901
  this.domElement = domCanvas;
4483
3902
  this.#generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4484
3903
  this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
@@ -4499,26 +3918,6 @@
4499
3918
  const pxRatio = this.#container.retina.pixelRatio, retinaSize = this.size;
4500
3919
  renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4501
3920
  renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4502
- const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4503
- this.render.setContextSettings({
4504
- alpha: true,
4505
- colorSpace: canSupportHdrQuery?.matches && container.hdr ? "display-p3" : "srgb",
4506
- desynchronized: true,
4507
- willReadFrequently: false,
4508
- });
4509
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4510
- this.#safeMutationObserver(obs => {
4511
- obs.disconnect();
4512
- });
4513
- container.retina.init();
4514
- this.initBackground();
4515
- this.#safeMutationObserver(obs => {
4516
- const element = this.domElement;
4517
- if (!element || !(element instanceof Node)) {
4518
- return;
4519
- }
4520
- obs.observe(element, { attributes: true });
4521
- });
4522
3921
  }
4523
3922
  resize() {
4524
3923
  const element = this.domElement;
@@ -4586,12 +3985,30 @@
4586
3985
  await container.refresh();
4587
3986
  }
4588
3987
  }
4589
- #applyResizePlugins = () => {
3988
+ #applyResizePlugins() {
4590
3989
  for (const plugin of this.#resizePlugins) {
4591
3990
  plugin.resize?.();
4592
3991
  }
4593
- };
4594
- #initStyle = () => {
3992
+ }
3993
+ #initContext() {
3994
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
3995
+ safeMatchMedia("(color-gamut: p3)")?.matches &&
3996
+ safeMatchMedia("(dynamic-range: high)")?.matches;
3997
+ this.render.setContextSettings({
3998
+ alpha: true,
3999
+ desynchronized: true,
4000
+ willReadFrequently: false,
4001
+ ...(canSupportHdr
4002
+ ? { colorSpace: "display-p3", colorType: "float16" }
4003
+ : { colorSpace: "srgb" }),
4004
+ });
4005
+ const renderCanvas = this.renderCanvas;
4006
+ if (!renderCanvas) {
4007
+ return;
4008
+ }
4009
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4010
+ }
4011
+ #initStyle() {
4595
4012
  const element = this.domElement, options = this.#container.actualOptions;
4596
4013
  if (!element) {
4597
4014
  return;
@@ -4612,8 +4029,8 @@
4612
4029
  }
4613
4030
  element.style.setProperty(key, value, "important");
4614
4031
  }
4615
- };
4616
- #repairStyle = () => {
4032
+ }
4033
+ #repairStyle() {
4617
4034
  const element = this.domElement;
4618
4035
  if (!element) {
4619
4036
  return;
@@ -4632,27 +4049,27 @@
4632
4049
  }
4633
4050
  observer.observe(element, { attributes: true });
4634
4051
  });
4635
- };
4636
- #resetOriginalStyle = () => {
4052
+ }
4053
+ #resetOriginalStyle() {
4637
4054
  const element = this.domElement, originalStyle = this.#originalStyle;
4638
4055
  if (!element || !originalStyle) {
4639
4056
  return;
4640
4057
  }
4641
4058
  setStyle(element, originalStyle, true);
4642
- };
4643
- #safeMutationObserver = callback => {
4059
+ }
4060
+ #safeMutationObserver(callback) {
4644
4061
  if (!this.#mutationObserver) {
4645
4062
  return;
4646
4063
  }
4647
4064
  callback(this.#mutationObserver);
4648
- };
4649
- #setFullScreenStyle = () => {
4065
+ }
4066
+ #setFullScreenStyle() {
4650
4067
  const element = this.domElement;
4651
4068
  if (!element) {
4652
4069
  return;
4653
4070
  }
4654
4071
  setStyle(element, getFullScreenStyle(this.#container.actualOptions.fullScreen.zIndex), true);
4655
- };
4072
+ }
4656
4073
  }
4657
4074
 
4658
4075
  class EventListeners {
@@ -4677,7 +4094,7 @@
4677
4094
  removeListeners() {
4678
4095
  this.#manageListeners(false);
4679
4096
  }
4680
- #handleVisibilityChange = () => {
4097
+ #handleVisibilityChange() {
4681
4098
  const container = this.#container, options = container.actualOptions;
4682
4099
  if (!options.pauseOnBlur) {
4683
4100
  return;
@@ -4695,8 +4112,8 @@
4695
4112
  container.draw(true);
4696
4113
  }
4697
4114
  }
4698
- };
4699
- #handleWindowResize = () => {
4115
+ }
4116
+ #handleWindowResize() {
4700
4117
  if (this.#resizeTimeout) {
4701
4118
  clearTimeout(this.#resizeTimeout);
4702
4119
  this.#resizeTimeout = undefined;
@@ -4706,13 +4123,13 @@
4706
4123
  await canvas.windowResize();
4707
4124
  };
4708
4125
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
4709
- };
4710
- #manageListeners = add => {
4126
+ }
4127
+ #manageListeners(add) {
4711
4128
  const handlers = this.#handlers;
4712
4129
  this.#manageResize(add);
4713
4130
  manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
4714
- };
4715
- #manageResize = add => {
4131
+ }
4132
+ #manageResize(add) {
4716
4133
  const handlers = this.#handlers, container = this.#container, options = container.actualOptions;
4717
4134
  if (!options.resize.enable) {
4718
4135
  return;
@@ -4739,7 +4156,7 @@
4739
4156
  });
4740
4157
  this.#resizeObserver.observe(canvasEl);
4741
4158
  }
4742
- };
4159
+ }
4743
4160
  }
4744
4161
 
4745
4162
  function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
@@ -4766,6 +4183,131 @@
4766
4183
  data.setCb(data.radius);
4767
4184
  }
4768
4185
  }
4186
+ function normalizeAngle(angle, modulus) {
4187
+ const normalized = angle % modulus;
4188
+ return normalized < defaultAngle ? normalized + modulus : normalized;
4189
+ }
4190
+ function initParticleState(particle, id, group) {
4191
+ particle.id = id;
4192
+ particle.group = group;
4193
+ particle.justWarped = false;
4194
+ particle.effectClose = true;
4195
+ particle.shapeClose = true;
4196
+ particle.pathRotation = false;
4197
+ particle.lastPathTime = 0;
4198
+ particle.destroyed = false;
4199
+ particle.unbreakable = false;
4200
+ particle.isRotating = false;
4201
+ particle.rotation = 0;
4202
+ particle.misplaced = false;
4203
+ particle.retina = {
4204
+ maxDistance: {},
4205
+ maxSpeed: 0,
4206
+ moveDrift: 0,
4207
+ moveSpeed: 0,
4208
+ sizeAnimationSpeed: 0,
4209
+ };
4210
+ particle.size = {
4211
+ value: 1,
4212
+ max: 1,
4213
+ min: 1,
4214
+ enable: false,
4215
+ };
4216
+ particle.outType = ParticleOutType.normal;
4217
+ particle.ignoresResizeRatio = true;
4218
+ }
4219
+ function resolveParticleOptions(particle, container, pluginManager, overrideOptions) {
4220
+ const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates;
4221
+ particle.effect = itemFromSingleOrMultiple(particlesOptions.effect.type, particle.id, reduceDuplicates);
4222
+ particle.shape = itemFromSingleOrMultiple(particlesOptions.shape.type, particle.id, reduceDuplicates);
4223
+ const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
4224
+ if (overrideOptions) {
4225
+ if (overrideOptions.effect) {
4226
+ const overrideEffectType = overrideOptions.effect.type;
4227
+ if (overrideEffectType && overrideEffectType !== particle.effect) {
4228
+ const effect = itemFromSingleOrMultiple(overrideEffectType, particle.id, reduceDuplicates);
4229
+ if (effect) {
4230
+ particle.effect = effect;
4231
+ }
4232
+ }
4233
+ effectOptions.load(overrideOptions.effect);
4234
+ }
4235
+ if (overrideOptions.shape) {
4236
+ const overrideShapeType = overrideOptions.shape.type;
4237
+ if (overrideShapeType && overrideShapeType !== particle.shape) {
4238
+ const shape = itemFromSingleOrMultiple(overrideShapeType, particle.id, reduceDuplicates);
4239
+ if (shape) {
4240
+ particle.shape = shape;
4241
+ }
4242
+ }
4243
+ shapeOptions.load(overrideOptions.shape);
4244
+ }
4245
+ }
4246
+ if (particle.effect === randomColorValue) {
4247
+ const availableEffects = [...container.effectDrawers.keys()];
4248
+ particle.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
4249
+ }
4250
+ if (particle.shape === randomColorValue) {
4251
+ const availableShapes = [...container.shapeDrawers.keys()];
4252
+ particle.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
4253
+ }
4254
+ particle.effectData = particle.effect
4255
+ ? loadEffectData(particle.effect, effectOptions, particle.id, reduceDuplicates)
4256
+ : undefined;
4257
+ particle.shapeData = particle.shape
4258
+ ? loadShapeData(particle.shape, shapeOptions, particle.id, reduceDuplicates)
4259
+ : undefined;
4260
+ particlesOptions.load(overrideOptions);
4261
+ const effectData = particle.effectData, shapeData = particle.shapeData;
4262
+ if (effectData) {
4263
+ particlesOptions.load(effectData.particles);
4264
+ }
4265
+ if (shapeData) {
4266
+ particlesOptions.load(shapeData.particles);
4267
+ }
4268
+ particle.effectClose = effectData?.close ?? particlesOptions.effect.close;
4269
+ particle.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
4270
+ return particlesOptions;
4271
+ }
4272
+ function initParticleDrawers(particle, container) {
4273
+ let effectDrawer, shapeDrawer;
4274
+ if (particle.effect) {
4275
+ effectDrawer = container.effectDrawers.get(particle.effect);
4276
+ }
4277
+ if (effectDrawer?.loadEffect) {
4278
+ effectDrawer.loadEffect(particle);
4279
+ }
4280
+ if (particle.shape) {
4281
+ shapeDrawer = container.shapeDrawers.get(particle.shape);
4282
+ }
4283
+ if (shapeDrawer?.loadShape) {
4284
+ shapeDrawer.loadShape(particle);
4285
+ }
4286
+ const sideCountFunc = shapeDrawer?.getSidesCount;
4287
+ if (sideCountFunc) {
4288
+ particle.sides = sideCountFunc(particle);
4289
+ }
4290
+ }
4291
+ function runUpdaterPreInit(updaters, particle) {
4292
+ for (const updater of updaters) {
4293
+ updater.preInit?.(particle);
4294
+ }
4295
+ }
4296
+ function runUpdaterInit(updaters, particle) {
4297
+ for (const updater of updaters) {
4298
+ updater.init(particle);
4299
+ }
4300
+ }
4301
+ function runDrawerInit(container, particle) {
4302
+ const shapeDrawer = particle.shape ? container.shapeDrawers.get(particle.shape) : undefined, effectDrawer = particle.effect ? container.effectDrawers.get(particle.effect) : undefined;
4303
+ effectDrawer?.particleInit?.(container, particle);
4304
+ shapeDrawer?.particleInit?.(container, particle);
4305
+ }
4306
+ function runParticleCreatedPlugins(container, particle) {
4307
+ for (const plugin of container.particleCreatedPlugins) {
4308
+ plugin.particleCreated?.(particle);
4309
+ }
4310
+ }
4769
4311
  class Particle {
4770
4312
  backColor;
4771
4313
  bubble;
@@ -4891,88 +4433,20 @@
4891
4433
  const rotateData = this.getRotateData(), rotating = this.isRotating;
4892
4434
  this.#cachedTransform.a = rotateData.cos * (externalTransform.a ?? defaultTransform.a);
4893
4435
  this.#cachedTransform.b = rotating
4894
- ? rotateData.sin * (externalTransform.b ?? identity$1)
4436
+ ? rotateData.sin * (externalTransform.b ?? identity)
4895
4437
  : (externalTransform.b ?? defaultTransform.b);
4896
4438
  this.#cachedTransform.c = rotating
4897
- ? -rotateData.sin * (externalTransform.c ?? identity$1)
4439
+ ? -rotateData.sin * (externalTransform.c ?? identity)
4898
4440
  : (externalTransform.c ?? defaultTransform.c);
4899
4441
  this.#cachedTransform.d = rotateData.cos * (externalTransform.d ?? defaultTransform.d);
4900
4442
  return this.#cachedTransform;
4901
4443
  }
4902
4444
  init(id, position, overrideOptions, group) {
4903
4445
  const container = this.#container;
4904
- this.id = id;
4905
- this.group = group;
4906
- this.justWarped = false;
4907
- this.effectClose = true;
4908
- this.shapeClose = true;
4909
- this.pathRotation = false;
4910
- this.lastPathTime = 0;
4911
- this.destroyed = false;
4912
- this.unbreakable = false;
4913
- this.isRotating = false;
4914
- this.rotation = 0;
4915
- this.misplaced = false;
4916
- this.retina = {
4917
- maxDistance: {},
4918
- maxSpeed: 0,
4919
- moveDrift: 0,
4920
- moveSpeed: 0,
4921
- sizeAnimationSpeed: 0,
4922
- };
4923
- this.size = {
4924
- value: 1,
4925
- max: 1,
4926
- min: 1,
4927
- enable: false,
4928
- };
4929
- this.outType = ParticleOutType.normal;
4930
- this.ignoresResizeRatio = true;
4931
- const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(this.#pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates, effectType = particlesOptions.effect.type, shapeType = particlesOptions.shape.type;
4932
- this.effect = itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
4933
- this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
4934
- const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
4935
- if (overrideOptions) {
4936
- if (overrideOptions.effect?.type && overrideOptions.effect.type !== this.effect) {
4937
- const overrideEffectType = overrideOptions.effect.type, effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
4938
- if (effect) {
4939
- this.effect = effect;
4940
- effectOptions.load(overrideOptions.effect);
4941
- }
4942
- }
4943
- if (overrideOptions.shape?.type && overrideOptions.shape.type !== this.shape) {
4944
- const overrideShapeType = overrideOptions.shape.type, shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
4945
- if (shape) {
4946
- this.shape = shape;
4947
- shapeOptions.load(overrideOptions.shape);
4948
- }
4949
- }
4950
- }
4951
- if (this.effect === randomColorValue) {
4952
- const availableEffects = [...this.#container.effectDrawers.keys()];
4953
- this.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
4954
- }
4955
- if (this.shape === randomColorValue) {
4956
- const availableShapes = [...this.#container.shapeDrawers.keys()];
4957
- this.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
4958
- }
4959
- this.effectData = this.effect ? loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates) : undefined;
4960
- this.shapeData = this.shape ? loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates) : undefined;
4961
- particlesOptions.load(overrideOptions);
4962
- const effectData = this.effectData, shapeData = this.shapeData;
4963
- if (effectData) {
4964
- particlesOptions.load(effectData.particles);
4965
- }
4966
- if (shapeData) {
4967
- particlesOptions.load(shapeData.particles);
4968
- }
4969
- this.effectClose = effectData?.close ?? particlesOptions.effect.close;
4970
- this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
4971
- this.options = particlesOptions;
4446
+ initParticleState(this, id, group);
4447
+ this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
4972
4448
  container.retina.initParticle(this);
4973
- for (const updater of container.particleUpdaters) {
4974
- updater.preInit?.(this);
4975
- }
4449
+ runUpdaterPreInit(container.particleUpdaters, this);
4976
4450
  this.bubble = {
4977
4451
  inRange: false,
4978
4452
  };
@@ -4985,32 +4459,11 @@
4985
4459
  this.velocity = this.initialVelocity.copy();
4986
4460
  this.zIndexFactor = this.position.z / container.zLayers;
4987
4461
  this.sides = 24;
4988
- let effectDrawer, shapeDrawer;
4989
- if (this.effect) {
4990
- effectDrawer = container.effectDrawers.get(this.effect);
4991
- }
4992
- if (effectDrawer?.loadEffect) {
4993
- effectDrawer.loadEffect(this);
4994
- }
4995
- if (this.shape) {
4996
- shapeDrawer = container.shapeDrawers.get(this.shape);
4997
- }
4998
- if (shapeDrawer?.loadShape) {
4999
- shapeDrawer.loadShape(this);
5000
- }
5001
- const sideCountFunc = shapeDrawer?.getSidesCount;
5002
- if (sideCountFunc) {
5003
- this.sides = sideCountFunc(this);
5004
- }
4462
+ initParticleDrawers(this, container);
5005
4463
  this.spawning = false;
5006
- for (const updater of container.particleUpdaters) {
5007
- updater.init(this);
5008
- }
5009
- effectDrawer?.particleInit?.(container, this);
5010
- shapeDrawer?.particleInit?.(container, this);
5011
- for (const plugin of container.particleCreatedPlugins) {
5012
- plugin.particleCreated?.(this);
5013
- }
4464
+ runUpdaterInit(container.particleUpdaters, this);
4465
+ runDrawerInit(container, this);
4466
+ runParticleCreatedPlugins(container, this);
5014
4467
  }
5015
4468
  isInsideCanvas(direction) {
5016
4469
  return this.#getInsideCanvasResult({ direction }).inside;
@@ -5024,15 +4477,15 @@
5024
4477
  }
5025
4478
  const angle = this.roll.angle;
5026
4479
  if (this.roll.horizontal && this.roll.vertical) {
5027
- const normalizedAngle = angle % doublePI, adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + doublePI : normalizedAngle;
4480
+ const adjustedAngle = normalizeAngle(angle, doublePI);
5028
4481
  return adjustedAngle >= Math.PI * half && adjustedAngle < Math.PI * triple * half;
5029
4482
  }
5030
4483
  if (this.roll.horizontal) {
5031
- const normalizedAngle = (angle + Math.PI * half) % (Math.PI * double), adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + Math.PI * double : normalizedAngle;
4484
+ const adjustedAngle = normalizeAngle(angle + Math.PI * half, doublePI);
5032
4485
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
5033
4486
  }
5034
4487
  if (this.roll.vertical) {
5035
- const normalizedAngle = angle % (Math.PI * double), adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + Math.PI * double : normalizedAngle;
4488
+ const adjustedAngle = normalizeAngle(angle, doublePI);
5036
4489
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
5037
4490
  }
5038
4491
  return false;
@@ -5045,10 +4498,10 @@
5045
4498
  updater.reset?.(this);
5046
4499
  }
5047
4500
  }
5048
- #calcPosition = (position, zIndex) => {
4501
+ #calcPosition(position, zIndex) {
5049
4502
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
5050
- const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size, abortController = new AbortController(), { signal } = abortController;
5051
- while (!signal.aborted) {
4503
+ const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
4504
+ for (;;) {
5052
4505
  for (const plugin of plugins) {
5053
4506
  const pluginPos = plugin.particlePosition?.(posVec, this);
5054
4507
  if (pluginPos) {
@@ -5076,9 +4529,8 @@
5076
4529
  tryCount += tryCountIncrement;
5077
4530
  posVec = undefined;
5078
4531
  }
5079
- return posVec;
5080
- };
5081
- #calculateVelocity = () => {
4532
+ }
4533
+ #calculateVelocity() {
5082
4534
  const moveOptions = this.options.move, baseVelocity = getParticleBaseVelocity(this.direction), res = baseVelocity.copy();
5083
4535
  if (moveOptions.direction === MoveDirection.inside || moveOptions.direction === MoveDirection.outside) {
5084
4536
  return res;
@@ -5094,8 +4546,8 @@
5094
4546
  res.length *= getRandom();
5095
4547
  }
5096
4548
  return res;
5097
- };
5098
- #fixHorizontal = (pos, radius, outMode) => {
4549
+ }
4550
+ #fixHorizontal(pos, radius, outMode) {
5099
4551
  fixOutMode({
5100
4552
  outMode,
5101
4553
  checkModes: [OutMode.bounce],
@@ -5104,8 +4556,8 @@
5104
4556
  setCb: (value) => (pos.x += value),
5105
4557
  radius,
5106
4558
  });
5107
- };
5108
- #fixVertical = (pos, radius, outMode) => {
4559
+ }
4560
+ #fixVertical(pos, radius, outMode) {
5109
4561
  fixOutMode({
5110
4562
  outMode,
5111
4563
  checkModes: [OutMode.bounce],
@@ -5114,8 +4566,8 @@
5114
4566
  setCb: (value) => (pos.y += value),
5115
4567
  radius,
5116
4568
  });
5117
- };
5118
- #getDefaultInsideCanvasResult = (direction, outMode) => {
4569
+ }
4570
+ #getDefaultInsideCanvasResult(direction, outMode) {
5119
4571
  const radius = this.getRadius(), canvasSize = this.#container.canvas.size, position = this.position, isBounce = outMode === OutMode.bounce;
5120
4572
  if (direction === OutModeDirection.bottom) {
5121
4573
  return {
@@ -5148,8 +4600,8 @@
5148
4600
  position.x <= canvasSize.width + radius,
5149
4601
  reason: "default",
5150
4602
  };
5151
- };
5152
- #getInsideCanvasCallbackData = (direction, outMode) => {
4603
+ }
4604
+ #getInsideCanvasCallbackData(direction, outMode) {
5153
4605
  return {
5154
4606
  canvasSize: this.#container.canvas.size,
5155
4607
  direction,
@@ -5157,8 +4609,8 @@
5157
4609
  particle: this,
5158
4610
  radius: this.getRadius(),
5159
4611
  };
5160
- };
5161
- #getInsideCanvasResult = (data) => {
4612
+ }
4613
+ #getInsideCanvasResult(data) {
5162
4614
  const defaultResult = this.#getDefaultInsideCanvasResult(data.direction, data.outMode), container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined, effectDrawer = this.effect ? container.effectDrawers.get(this.effect) : undefined, shapeCheck = shapeDrawer?.isInsideCanvas, effectCheck = effectDrawer?.isInsideCanvas;
5163
4615
  if (!shapeCheck && !effectCheck) {
5164
4616
  return defaultResult;
@@ -5173,8 +4625,8 @@
5173
4625
  };
5174
4626
  }
5175
4627
  return shapeResult ?? effectResult ?? defaultResult;
5176
- };
5177
- #getRollColor = color => {
4628
+ }
4629
+ #getRollColor(color) {
5178
4630
  if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
5179
4631
  return color;
5180
4632
  }
@@ -5188,8 +4640,8 @@
5188
4640
  return alterHsl(color, this.roll.alter.type, this.roll.alter.value);
5189
4641
  }
5190
4642
  return color;
5191
- };
5192
- #initPosition = position => {
4643
+ }
4644
+ #initPosition(position) {
5193
4645
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5194
4646
  if (!initialPosition) {
5195
4647
  throw new Error("a valid position cannot be found for particle");
@@ -5212,8 +4664,8 @@
5212
4664
  break;
5213
4665
  }
5214
4666
  this.offset = Vector.origin;
5215
- };
5216
- #normalizeInsideCanvasResult = (result, reason) => {
4667
+ }
4668
+ #normalizeInsideCanvasResult(result, reason) {
5217
4669
  if (typeof result === "boolean") {
5218
4670
  return {
5219
4671
  inside: result,
@@ -5225,7 +4677,7 @@
5225
4677
  margin: result.margin,
5226
4678
  reason: result.reason ?? reason,
5227
4679
  };
5228
- };
4680
+ }
5229
4681
  }
5230
4682
 
5231
4683
  class SpatialHashGrid {
@@ -5578,10 +5030,10 @@
5578
5030
  }
5579
5031
  this.#resizeFactor = undefined;
5580
5032
  }
5581
- #addToPool = (...particles) => {
5033
+ #addToPool(...particles) {
5582
5034
  this.#pool.push(...particles);
5583
- };
5584
- #applyDensity = (options, pluginsCount, group, groupOptions) => {
5035
+ }
5036
+ #applyDensity(options, pluginsCount, group, groupOptions) {
5585
5037
  const numberOptions = options.number;
5586
5038
  if (!numberOptions.density.enable) {
5587
5039
  if (group === undefined) {
@@ -5605,36 +5057,19 @@
5605
5057
  else if (particlesCount > particlesNumber) {
5606
5058
  this.removeQuantity(particlesCount - particlesNumber, group);
5607
5059
  }
5608
- };
5609
- #createBuckets = (zLayers) => {
5060
+ }
5061
+ #createBuckets(zLayers) {
5610
5062
  const bucketCount = Math.max(Math.floor(zLayers), one);
5611
5063
  return Array.from({ length: bucketCount }, () => []);
5612
- };
5613
- #getBucketIndex = (zIndex) => {
5064
+ }
5065
+ #getBucketIndex(zIndex) {
5614
5066
  const maxBucketIndex = this.#zBuckets.length - one;
5615
5067
  if (maxBucketIndex <= minIndex) {
5616
5068
  return minIndex;
5617
5069
  }
5618
5070
  return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
5619
- };
5620
- #getParticleInsertIndex = (bucket, particleId) => {
5621
- let start = minIndex, end = bucket.length;
5622
- while (start < end) {
5623
- const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
5624
- if (!middleParticle) {
5625
- end = middle;
5626
- continue;
5627
- }
5628
- if (middleParticle.id < particleId) {
5629
- start = middle + one;
5630
- }
5631
- else {
5632
- end = middle;
5633
- }
5634
- }
5635
- return start;
5636
- };
5637
- #initDensityFactor = densityOptions => {
5071
+ }
5072
+ #initDensityFactor(densityOptions) {
5638
5073
  const container = this.#container;
5639
5074
  if (!densityOptions.enable) {
5640
5075
  return defaultDensityFactor;
@@ -5644,16 +5079,16 @@
5644
5079
  return defaultDensityFactor;
5645
5080
  }
5646
5081
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5647
- };
5648
- #insertParticleIntoBucket = (particle) => {
5082
+ }
5083
+ #insertParticleIntoBucket(particle) {
5649
5084
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
5650
5085
  if (!bucket) {
5651
5086
  return;
5652
5087
  }
5653
- bucket.splice(this.#getParticleInsertIndex(bucket, particle.id), empty, particle);
5088
+ bucket.push(particle);
5654
5089
  this.#particleBuckets.set(particle.id, bucketIndex);
5655
- };
5656
- #removeParticle = (index, group, override) => {
5090
+ }
5091
+ #removeParticle(index, group, override) {
5657
5092
  const particle = this.#array[index];
5658
5093
  if (!particle) {
5659
5094
  return false;
@@ -5669,22 +5104,20 @@
5669
5104
  });
5670
5105
  this.#addToPool(particle);
5671
5106
  return true;
5672
- };
5673
- #removeParticleFromBucket = (particle) => {
5107
+ }
5108
+ #removeParticleFromBucket(particle) {
5674
5109
  const bucketIndex = this.#particleBuckets.get(particle.id) ?? this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
5675
5110
  if (!bucket) {
5676
5111
  this.#particleBuckets.delete(particle.id);
5677
5112
  return;
5678
5113
  }
5679
- const particleIndex = this.#getParticleInsertIndex(bucket, particle.id);
5680
- if (bucket[particleIndex]?.id !== particle.id) {
5681
- this.#particleBuckets.delete(particle.id);
5682
- return;
5114
+ const idx = bucket.findIndex(p => p.id === particle.id);
5115
+ if (idx >= minIndex) {
5116
+ bucket.splice(idx, deleteCount);
5683
5117
  }
5684
- bucket.splice(particleIndex, deleteCount);
5685
5118
  this.#particleBuckets.delete(particle.id);
5686
- };
5687
- #resetBuckets = (zLayers) => {
5119
+ }
5120
+ #resetBuckets(zLayers) {
5688
5121
  const bucketCount = Math.max(Math.floor(zLayers), one);
5689
5122
  if (this.#zBuckets.length !== bucketCount) {
5690
5123
  this.#zBuckets = this.#createBuckets(bucketCount);
@@ -5693,8 +5126,8 @@
5693
5126
  for (const bucket of this.#zBuckets) {
5694
5127
  bucket.length = minIndex;
5695
5128
  }
5696
- };
5697
- #updateParticleBucket = (particle) => {
5129
+ }
5130
+ #updateParticleBucket(particle) {
5698
5131
  const newBucketIndex = this.#getBucketIndex(particle.position.z), currentBucketIndex = this.#particleBuckets.get(particle.id);
5699
5132
  if (currentBucketIndex === undefined) {
5700
5133
  this.#insertParticleIntoBucket(particle);
@@ -5705,9 +5138,9 @@
5705
5138
  }
5706
5139
  const currentBucket = this.#zBuckets[currentBucketIndex];
5707
5140
  if (currentBucket) {
5708
- const particleIndex = this.#getParticleInsertIndex(currentBucket, particle.id);
5709
- if (currentBucket[particleIndex]?.id === particle.id) {
5710
- currentBucket.splice(particleIndex, deleteCount);
5141
+ const idx = currentBucket.findIndex(p => p.id === particle.id);
5142
+ if (idx >= minIndex) {
5143
+ currentBucket.splice(idx, deleteCount);
5711
5144
  }
5712
5145
  }
5713
5146
  const newBucket = this.#zBuckets[newBucketIndex];
@@ -5715,10 +5148,16 @@
5715
5148
  this.#particleBuckets.set(particle.id, newBucketIndex);
5716
5149
  return;
5717
5150
  }
5718
- newBucket.splice(this.#getParticleInsertIndex(newBucket, particle.id), empty, particle);
5151
+ newBucket.push(particle);
5152
+ if (newBucket.length >= double) {
5153
+ const prev = newBucket[newBucket.length - double];
5154
+ if (prev && particle.id < prev.id) {
5155
+ newBucket.sort((a, b) => a.id - b.id);
5156
+ }
5157
+ }
5719
5158
  this.#particleBuckets.set(particle.id, newBucketIndex);
5720
- };
5721
- #updateParticlesPhase1 = (delta) => {
5159
+ }
5160
+ #updateParticlesPhase1(delta) {
5722
5161
  const particlesToDelete = new Set(), resizeFactor = this.#resizeFactor;
5723
5162
  for (const particle of this.#array) {
5724
5163
  if (resizeFactor && !particle.ignoresResizeRatio) {
@@ -5744,8 +5183,8 @@
5744
5183
  this.grid.insert(particle);
5745
5184
  }
5746
5185
  return particlesToDelete;
5747
- };
5748
- #updateParticlesPhase2 = (delta, particlesToDelete) => {
5186
+ }
5187
+ #updateParticlesPhase2(delta, particlesToDelete) {
5749
5188
  for (const particle of this.#array) {
5750
5189
  if (particle.destroyed) {
5751
5190
  particlesToDelete.add(particle);
@@ -5761,7 +5200,7 @@
5761
5200
  }
5762
5201
  this.#updateParticleBucket(particle);
5763
5202
  }
5764
- };
5203
+ }
5765
5204
  }
5766
5205
 
5767
5206
  class Retina {
@@ -6123,7 +5562,7 @@
6123
5562
  }
6124
5563
  return refresh;
6125
5564
  }
6126
- #nextFrame = (timestamp) => {
5565
+ #nextFrame(timestamp) {
6127
5566
  try {
6128
5567
  if (!this.#smooth &&
6129
5568
  this.#lastFrameTime !== undefined &&
@@ -6151,7 +5590,7 @@
6151
5590
  catch (e) {
6152
5591
  getLogger().error("error in animation loop", e);
6153
5592
  }
6154
- };
5593
+ }
6155
5594
  }
6156
5595
 
6157
5596
  var Container$1 = /*#__PURE__*/Object.freeze({
@@ -6197,7 +5636,7 @@
6197
5636
  BlendPluginInstance: BlendPluginInstance
6198
5637
  });
6199
5638
 
6200
- const minVelocity = 0, identity = 1, moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
5639
+ const moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
6201
5640
  function applyDistance(particle) {
6202
5641
  const initialPosition = particle.initialPosition, { dx, dy } = getDistances(initialPosition, particle.position), dxFixed = Math.abs(dx), dyFixed = Math.abs(dy), { maxDistance } = particle.retina, hDistance = maxDistance.horizontal, vDistance = maxDistance.vertical;
6203
5642
  if (!hDistance && !vDistance) {
@@ -6643,7 +6082,13 @@
6643
6082
  this.#paused = !this.options.autoPlay;
6644
6083
  this.#particlesOptions = particlesOptions;
6645
6084
  this.#size = this.#calcSize();
6646
- this.size = getSize(this.#size, this.#container.canvas.size);
6085
+ this.size =
6086
+ this.#size.mode === PixelMode.percent
6087
+ ? {
6088
+ width: (this.#size.width / percentDenominator) * this.#container.canvas.size.width,
6089
+ height: (this.#size.height / percentDenominator) * this.#container.canvas.size.height,
6090
+ }
6091
+ : { width: this.#size.width, height: this.#size.height };
6647
6092
  this.#lifeCount = this.options.life.count ?? defaultLifeCount;
6648
6093
  this.#immortal = this.#lifeCount <= minLifeCount;
6649
6094
  if (this.options.domId) {
@@ -6714,7 +6159,13 @@
6714
6159
  ? initialPosition
6715
6160
  : this.#calcPosition();
6716
6161
  this.#size = this.#calcSize();
6717
- this.size = getSize(this.#size, container.canvas.size);
6162
+ this.size =
6163
+ this.#size.mode === PixelMode.percent
6164
+ ? {
6165
+ width: (this.#size.width / percentDenominator) * container.canvas.size.width,
6166
+ height: (this.#size.height / percentDenominator) * container.canvas.size.height,
6167
+ }
6168
+ : { width: this.#size.width, height: this.#size.height };
6718
6169
  this.#shape?.resize(this.position, this.size);
6719
6170
  }
6720
6171
  update(delta) {
@@ -6814,7 +6265,7 @@
6814
6265
  return size;
6815
6266
  })());
6816
6267
  }
6817
- #destroy = () => {
6268
+ #destroy() {
6818
6269
  this.#mutationObserver?.disconnect();
6819
6270
  this.#mutationObserver = undefined;
6820
6271
  this.#resizeObserver?.disconnect();
@@ -6823,7 +6274,7 @@
6823
6274
  this.#container.dispatchEvent("emitterDestroyed", {
6824
6275
  emitter: this,
6825
6276
  });
6826
- };
6277
+ }
6827
6278
  #emit() {
6828
6279
  if (this.#paused) {
6829
6280
  return;
@@ -6883,7 +6334,7 @@
6883
6334
  }
6884
6335
  }
6885
6336
  }
6886
- #prepareToDie = () => {
6337
+ #prepareToDie() {
6887
6338
  if (this.#paused) {
6888
6339
  return;
6889
6340
  }
@@ -6891,8 +6342,8 @@
6891
6342
  if ((this.#lifeCount > minLifeCount || this.#immortal) && duration !== undefined && duration > minDuration) {
6892
6343
  this.#duration = duration * millisecondsToSeconds;
6893
6344
  }
6894
- };
6895
- #setColorAnimation = (animation, initValue, maxValue, factor = defaultColorAnimationFactor) => {
6345
+ }
6346
+ #setColorAnimation(animation, initValue, maxValue, factor = defaultColorAnimationFactor) {
6896
6347
  const container = this.#container;
6897
6348
  if (!animation.enable) {
6898
6349
  return initValue;
@@ -6901,7 +6352,7 @@
6901
6352
  ? (delay * millisecondsToSeconds) / container.retina.reduceFactor
6902
6353
  : Infinity, colorSpeed = getRangeValue(animation.speed);
6903
6354
  return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
6904
- };
6355
+ }
6905
6356
  }
6906
6357
 
6907
6358
  var EmitterInstance$1 = /*#__PURE__*/Object.freeze({