@tsparticles/preset-fountain 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;
@@ -2184,73 +1646,53 @@
2184
1646
  this.load({
2185
1647
  paint: palettePaint,
2186
1648
  blend: {
2187
- enable: true,
2188
- mode: paletteData.blendMode,
2189
- },
2190
- });
2191
- };
2192
- }
2193
-
2194
- function loadOptions(options, ...sourceOptionsArr) {
2195
- for (const sourceOptions of sourceOptionsArr) {
2196
- options.load(sourceOptions);
1649
+ enable: true,
1650
+ mode: paletteData.blendMode,
1651
+ },
1652
+ });
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
1751
  }
2447
- drawer.afterDraw(data);
2448
- }
2449
- function drawShapeBeforeDraw(drawer, data) {
2450
- if (!drawer?.beforeDraw) {
2451
- return;
2452
- }
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
2948
  class Size extends RangedAnimationValueWithRandom {
3575
- animation;
3576
- constructor() {
3577
- super();
3578
- this.animation = new SizeAnimation();
3579
- this.value = 3;
3580
- }
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),
@@ -3681,18 +3048,10 @@
3681
3048
  if (isNull(data)) {
3682
3049
  return;
3683
3050
  }
3684
- if (data.bottom !== undefined) {
3685
- this.bottom = setRangeValue(data.bottom);
3686
- }
3687
- if (data.left !== undefined) {
3688
- this.left = setRangeValue(data.left);
3689
- }
3690
- if (data.right !== undefined) {
3691
- this.right = setRangeValue(data.right);
3692
- }
3693
- if (data.top !== undefined) {
3694
- this.top = setRangeValue(data.top);
3695
- }
3051
+ loadRangeProperty(this, "bottom", data.bottom);
3052
+ loadRangeProperty(this, "left", data.left);
3053
+ loadRangeProperty(this, "right", data.right);
3054
+ loadRangeProperty(this, "top", data.top);
3696
3055
  }
3697
3056
  }
3698
3057
 
@@ -3704,55 +3063,35 @@
3704
3063
  })(DestroyMode || (DestroyMode = {}));
3705
3064
 
3706
3065
  class Explode {
3707
- maxSizeFactor;
3708
- speed;
3709
- constructor() {
3710
- this.maxSizeFactor = 3;
3711
- this.speed = 2;
3712
- }
3066
+ maxSizeFactor = 3;
3067
+ speed = 2;
3713
3068
  load(data) {
3714
3069
  if (isNull(data)) {
3715
3070
  return;
3716
3071
  }
3717
- if (data.maxSizeFactor !== undefined) {
3718
- this.maxSizeFactor = data.maxSizeFactor;
3719
- }
3720
- if (data.speed !== undefined) {
3721
- this.speed = data.speed;
3722
- }
3072
+ loadProperty(this, "maxSizeFactor", data.maxSizeFactor);
3073
+ loadProperty(this, "speed", data.speed);
3723
3074
  }
3724
3075
  }
3725
3076
 
3726
3077
  class SplitFactor extends ValueWithRandom {
3727
- constructor() {
3728
- super();
3729
- this.value = 3;
3730
- }
3078
+ value = 3;
3731
3079
  }
3732
3080
 
3733
3081
  class SplitRate extends ValueWithRandom {
3734
- constructor() {
3735
- super();
3736
- this.value = { min: 4, max: 9 };
3737
- }
3082
+ value = { min: 4, max: 9 };
3738
3083
  }
3739
3084
 
3740
3085
  class Split {
3741
- count;
3742
- factor;
3086
+ count = 1;
3087
+ factor = new SplitFactor();
3743
3088
  fillColor;
3744
3089
  fillColorOffset;
3745
3090
  particles;
3746
- rate;
3747
- sizeOffset;
3091
+ rate = new SplitRate();
3092
+ sizeOffset = true;
3748
3093
  strokeColor;
3749
3094
  strokeColorOffset;
3750
- constructor() {
3751
- this.count = 1;
3752
- this.factor = new SplitFactor();
3753
- this.rate = new SplitRate();
3754
- this.sizeOffset = true;
3755
- }
3756
3095
  load(data) {
3757
3096
  if (isNull(data)) {
3758
3097
  return;
@@ -3763,17 +3102,13 @@
3763
3102
  if (data.strokeColor !== undefined) {
3764
3103
  this.strokeColor = OptionsColor.create(this.strokeColor, data.strokeColor);
3765
3104
  }
3766
- if (data.count !== undefined) {
3767
- this.count = data.count;
3768
- }
3105
+ loadProperty(this, "count", data.count);
3769
3106
  this.factor.load(data.factor);
3770
3107
  this.rate.load(data.rate);
3771
3108
  this.particles = executeOnSingleOrMultiple(data.particles, particles => {
3772
3109
  return deepExtend({}, particles);
3773
3110
  });
3774
- if (data.sizeOffset !== undefined) {
3775
- this.sizeOffset = data.sizeOffset;
3776
- }
3111
+ loadProperty(this, "sizeOffset", data.sizeOffset);
3777
3112
  if (data.fillColorOffset) {
3778
3113
  this.fillColorOffset = this.fillColorOffset ?? {};
3779
3114
  if (data.fillColorOffset.h !== undefined) {
@@ -3802,16 +3137,10 @@
3802
3137
  }
3803
3138
 
3804
3139
  class Destroy {
3805
- bounds;
3806
- explode;
3807
- mode;
3808
- split;
3809
- constructor() {
3810
- this.bounds = new DestroyBounds();
3811
- this.explode = new Explode();
3812
- this.mode = DestroyMode.none;
3813
- this.split = new Split();
3814
- }
3140
+ bounds = new DestroyBounds();
3141
+ explode = new Explode();
3142
+ mode = DestroyMode.none;
3143
+ split = new Split();
3815
3144
  load(data) {
3816
3145
  if (isNull(data)) {
3817
3146
  return;
@@ -3872,7 +3201,7 @@
3872
3201
  mode: PixelMode.precise,
3873
3202
  },
3874
3203
  });
3875
- const factor = identity$1 / getRangeValue(splitOptions.factor.value), sizeOptions = splitParticleOptions["size"];
3204
+ const factor = identity / getRangeValue(splitOptions.factor.value), sizeOptions = splitParticleOptions["size"];
3876
3205
  if (sizeOptions) {
3877
3206
  if (isNumber(sizeOptions.value)) {
3878
3207
  sizeOptions.value *= factor;
@@ -3959,10 +3288,7 @@
3959
3288
  return !destroyParticle.destroyed || !!destroyParticle.exploding;
3960
3289
  }
3961
3290
  loadOptions(options, ...sources) {
3962
- options.destroy ??= new Destroy();
3963
- for (const source of sources) {
3964
- options.destroy.load(source?.destroy);
3965
- }
3291
+ loadOptionProperty(options, "destroy", Destroy, ...sources);
3966
3292
  }
3967
3293
  particleDestroyed(particle, override) {
3968
3294
  if (override) {
@@ -4027,7 +3353,7 @@
4027
3353
  }
4028
3354
 
4029
3355
  async function loadDestroyUpdater(engine) {
4030
- engine.checkVersion("4.1.2");
3356
+ engine.checkVersion("4.2.0");
4031
3357
  await engine.pluginManager.register(e => {
4032
3358
  e.pluginManager.addParticleUpdater("destroy", container => {
4033
3359
  return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
@@ -4039,78 +3365,46 @@
4039
3365
  count;
4040
3366
  delay;
4041
3367
  duration;
4042
- wait;
4043
- constructor() {
4044
- this.wait = false;
4045
- }
3368
+ wait = false;
4046
3369
  load(data) {
4047
3370
  if (isNull(data)) {
4048
3371
  return;
4049
3372
  }
4050
- if (data.count !== undefined) {
4051
- this.count = data.count;
4052
- }
4053
- if (data.delay !== undefined) {
4054
- this.delay = setRangeValue(data.delay);
4055
- }
4056
- if (data.duration !== undefined) {
4057
- this.duration = setRangeValue(data.duration);
4058
- }
4059
- if (data.wait !== undefined) {
4060
- this.wait = data.wait;
4061
- }
3373
+ loadProperty(this, "count", data.count);
3374
+ loadRangeProperty(this, "delay", data.delay);
3375
+ loadRangeProperty(this, "duration", data.duration);
3376
+ loadProperty(this, "wait", data.wait);
4062
3377
  }
4063
3378
  }
4064
3379
 
4065
- class EmitterRate {
4066
- delay;
4067
- quantity;
4068
- constructor() {
4069
- this.quantity = 1;
4070
- this.delay = 0.1;
4071
- }
3380
+ class EmitterRate {
3381
+ delay = 0.1;
3382
+ quantity = 1;
4072
3383
  load(data) {
4073
3384
  if (isNull(data)) {
4074
3385
  return;
4075
3386
  }
4076
- if (data.quantity !== undefined) {
4077
- this.quantity = setRangeValue(data.quantity);
4078
- }
4079
- if (data.delay !== undefined) {
4080
- this.delay = setRangeValue(data.delay);
4081
- }
3387
+ loadRangeProperty(this, "quantity", data.quantity);
3388
+ loadRangeProperty(this, "delay", data.delay);
4082
3389
  }
4083
3390
  }
4084
3391
 
4085
3392
  class EmitterShapeReplace {
4086
- color;
4087
- opacity;
4088
- constructor() {
4089
- this.color = false;
4090
- this.opacity = false;
4091
- }
3393
+ color = false;
3394
+ opacity = false;
4092
3395
  load(data) {
4093
3396
  if (isNull(data)) {
4094
3397
  return;
4095
3398
  }
4096
- if (data.color !== undefined) {
4097
- this.color = data.color;
4098
- }
4099
- if (data.opacity !== undefined) {
4100
- this.opacity = data.opacity;
4101
- }
3399
+ loadProperty(this, "color", data.color);
3400
+ loadProperty(this, "opacity", data.opacity);
4102
3401
  }
4103
3402
  }
4104
3403
 
4105
3404
  class EmitterShape {
4106
- options;
4107
- replace;
4108
- type;
4109
- constructor() {
4110
- this.options = {};
4111
- this.replace = new EmitterShapeReplace();
4112
- this.type = "square";
4113
- }
3405
+ options = {};
3406
+ replace = new EmitterShapeReplace();
3407
+ type = "square";
4114
3408
  load(data) {
4115
3409
  if (isNull(data)) {
4116
3410
  return;
@@ -4119,34 +3413,21 @@
4119
3413
  this.options = deepExtend({}, data.options ?? {});
4120
3414
  }
4121
3415
  this.replace.load(data.replace);
4122
- if (data.type !== undefined) {
4123
- this.type = data.type;
4124
- }
3416
+ loadProperty(this, "type", data.type);
4125
3417
  }
4126
3418
  }
4127
3419
 
4128
3420
  class EmitterSize {
4129
- height;
4130
- mode;
4131
- width;
4132
- constructor() {
4133
- this.mode = PixelMode.percent;
4134
- this.height = 0;
4135
- this.width = 0;
4136
- }
3421
+ height = 0;
3422
+ mode = PixelMode.percent;
3423
+ width = 0;
4137
3424
  load(data) {
4138
3425
  if (isNull(data)) {
4139
3426
  return;
4140
3427
  }
4141
- if (data.mode !== undefined) {
4142
- this.mode = data.mode;
4143
- }
4144
- if (data.height !== undefined) {
4145
- this.height = data.height;
4146
- }
4147
- if (data.width !== undefined) {
4148
- this.width = data.width;
4149
- }
3428
+ loadProperty(this, "mode", data.mode);
3429
+ loadProperty(this, "height", data.height);
3430
+ loadProperty(this, "width", data.width);
4150
3431
  }
4151
3432
  }
4152
3433
 
@@ -4169,50 +3450,35 @@
4169
3450
  }
4170
3451
 
4171
3452
  class Emitter {
4172
- autoPlay;
3453
+ autoPlay = true;
4173
3454
  direction;
4174
3455
  domId;
4175
- fill;
4176
- life;
3456
+ fill = true;
3457
+ life = new EmitterLife();
4177
3458
  name;
4178
3459
  particles;
4179
3460
  position;
4180
- rate;
4181
- shape;
3461
+ rate = new EmitterRate();
3462
+ shape = new EmitterShape();
4182
3463
  size;
4183
- spawn;
3464
+ spawn = new EmitterSpawn();
4184
3465
  spawnFillColor;
4185
3466
  spawnStrokeColor;
4186
- startCount;
4187
- constructor() {
4188
- this.autoPlay = true;
4189
- this.fill = true;
4190
- this.life = new EmitterLife();
4191
- this.rate = new EmitterRate();
4192
- this.shape = new EmitterShape();
4193
- this.spawn = new EmitterSpawn();
4194
- this.startCount = 0;
4195
- }
3467
+ startCount = 0;
4196
3468
  load(data) {
4197
3469
  if (isNull(data)) {
4198
3470
  return;
4199
3471
  }
4200
- if (data.autoPlay !== undefined) {
4201
- this.autoPlay = data.autoPlay;
4202
- }
3472
+ loadProperty(this, "autoPlay", data.autoPlay);
4203
3473
  if (data.size !== undefined) {
4204
3474
  this.size ??= new EmitterSize();
4205
3475
  this.size.load(data.size);
4206
3476
  }
4207
- if (data.direction !== undefined) {
4208
- this.direction = data.direction;
4209
- }
4210
- this.domId = data.domId;
4211
- if (data.fill !== undefined) {
4212
- this.fill = data.fill;
4213
- }
3477
+ loadProperty(this, "direction", data.direction);
3478
+ loadProperty(this, "domId", data.domId);
3479
+ loadProperty(this, "fill", data.fill);
4214
3480
  this.life.load(data.life);
4215
- this.name = data.name;
3481
+ loadProperty(this, "name", data.name);
4216
3482
  this.particles = executeOnSingleOrMultiple(data.particles, particles => {
4217
3483
  return deepExtend({}, particles);
4218
3484
  });
@@ -4236,9 +3502,7 @@
4236
3502
  this.spawnStrokeColor ??= new AnimatableColor();
4237
3503
  this.spawnStrokeColor.load(data.spawnStrokeColor);
4238
3504
  }
4239
- if (data.startCount !== undefined) {
4240
- this.startCount = data.startCount;
4241
- }
3505
+ loadProperty(this, "startCount", data.startCount);
4242
3506
  }
4243
3507
  }
4244
3508
 
@@ -4303,7 +3567,7 @@
4303
3567
  })(EmitterClickMode || (EmitterClickMode = {}));
4304
3568
 
4305
3569
  async function loadEmittersPluginSimple(engine) {
4306
- engine.checkVersion("4.1.2");
3570
+ engine.checkVersion("4.2.0");
4307
3571
  await engine.pluginManager.register(async (e) => {
4308
3572
  const instancesManager = await getEmittersInstancesManager(e);
4309
3573
  await addEmittersShapesManager(e);
@@ -4321,34 +3585,23 @@
4321
3585
  if (data.color !== undefined) {
4322
3586
  this.color = OptionsColor.create(this.color, data.color);
4323
3587
  }
4324
- if (data.image !== undefined) {
4325
- this.image = data.image;
4326
- }
3588
+ loadProperty(this, "image", data.image);
4327
3589
  }
4328
3590
  }
4329
3591
 
4330
3592
  class Trail {
4331
- enable;
4332
- fill;
4333
- length;
4334
- constructor() {
4335
- this.enable = false;
4336
- this.length = 10;
4337
- this.fill = new TrailFill();
4338
- }
3593
+ enable = false;
3594
+ fill = new TrailFill();
3595
+ length = 10;
4339
3596
  load(data) {
4340
3597
  if (isNull(data)) {
4341
3598
  return;
4342
3599
  }
4343
- if (data.enable !== undefined) {
4344
- this.enable = data.enable;
4345
- }
3600
+ loadProperty(this, "enable", data.enable);
4346
3601
  if (data.fill !== undefined) {
4347
3602
  this.fill.load(data.fill);
4348
3603
  }
4349
- if (data.length !== undefined) {
4350
- this.length = data.length;
4351
- }
3604
+ loadProperty(this, "length", data.length);
4352
3605
  }
4353
3606
  }
4354
3607
 
@@ -4378,7 +3631,7 @@
4378
3631
  }
4379
3632
 
4380
3633
  async function loadTrailPlugin(engine) {
4381
- engine.checkVersion("4.1.2");
3634
+ engine.checkVersion("4.2.0");
4382
3635
  await engine.pluginManager.register(e => {
4383
3636
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
4384
3637
  });
@@ -4553,7 +3806,7 @@
4553
3806
  return;
4554
3807
  }
4555
3808
  this.draw(ctx => {
4556
- clear(ctx, this.#canvasManager.size);
3809
+ ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4557
3810
  });
4558
3811
  }
4559
3812
  clear() {
@@ -4615,7 +3868,7 @@
4615
3868
  plugin.drawParticleSetup?.(context, particle, delta);
4616
3869
  }
4617
3870
  this.#applyPreDrawUpdaters(context, particle, radius, opacity, colorStyles, transform);
4618
- drawParticle({
3871
+ this.#drawParticle({
4619
3872
  container,
4620
3873
  context,
4621
3874
  particle,
@@ -4634,7 +3887,7 @@
4634
3887
  drawParticlePlugins(particle, delta) {
4635
3888
  this.draw(ctx => {
4636
3889
  for (const plugin of this.#drawParticlePlugins) {
4637
- drawParticlePlugin(ctx, plugin, particle, delta);
3890
+ this.#drawParticlePlugin(ctx, plugin, particle, delta);
4638
3891
  }
4639
3892
  });
4640
3893
  }
@@ -4734,12 +3987,19 @@
4734
3987
  }
4735
3988
  paintBase(baseColor) {
4736
3989
  this.draw(ctx => {
4737
- paintBase(ctx, this.#canvasManager.size, baseColor);
3990
+ ctx.fillStyle = baseColor ?? "rgba(0,0,0,0)";
3991
+ ctx.fillRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4738
3992
  });
4739
3993
  }
4740
3994
  paintImage(image, opacity) {
4741
3995
  this.draw(ctx => {
4742
- paintImage(ctx, this.#canvasManager.size, image, opacity);
3996
+ if (!image) {
3997
+ return;
3998
+ }
3999
+ const prevAlpha = ctx.globalAlpha;
4000
+ ctx.globalAlpha = opacity;
4001
+ ctx.drawImage(image, originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4002
+ ctx.globalAlpha = prevAlpha;
4743
4003
  });
4744
4004
  }
4745
4005
  setContext(context) {
@@ -4753,15 +4013,15 @@
4753
4013
  }
4754
4014
  stop() {
4755
4015
  this.draw(ctx => {
4756
- clear(ctx, this.#canvasManager.size);
4016
+ ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4757
4017
  });
4758
4018
  }
4759
- #applyPostDrawUpdaters = particle => {
4019
+ #applyPostDrawUpdaters(particle) {
4760
4020
  for (const updater of this.#postDrawUpdaters) {
4761
4021
  updater.afterDraw?.(particle);
4762
4022
  }
4763
- };
4764
- #applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
4023
+ }
4024
+ #applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform) {
4765
4025
  for (const updater of this.#preDrawUpdaters) {
4766
4026
  if (updater.getColorStyles) {
4767
4027
  const { fill, stroke } = updater.getColorStyles(particle, ctx, radius, zOpacity);
@@ -4780,8 +4040,114 @@
4780
4040
  }
4781
4041
  updater.beforeDraw?.(particle);
4782
4042
  }
4783
- };
4784
- #getPluginParticleColors = particle => {
4043
+ }
4044
+ #drawAfterEffect(drawer, data) {
4045
+ if (!drawer?.drawAfter) {
4046
+ return;
4047
+ }
4048
+ const { particle } = data;
4049
+ if (!particle.effect) {
4050
+ return;
4051
+ }
4052
+ drawer.drawAfter(data);
4053
+ }
4054
+ #drawBeforeEffect(drawer, data) {
4055
+ if (!drawer?.drawBefore) {
4056
+ return;
4057
+ }
4058
+ const { particle } = data;
4059
+ if (!particle.effect) {
4060
+ return;
4061
+ }
4062
+ drawer.drawBefore(data);
4063
+ }
4064
+ #drawParticle(data) {
4065
+ const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = defaultZoom, drawPosition = {
4066
+ x: pos.x,
4067
+ y: pos.y,
4068
+ };
4069
+ context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
4070
+ if (colorStyles.fill) {
4071
+ context.fillStyle = colorStyles.fill;
4072
+ }
4073
+ const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
4074
+ context.lineWidth = strokeWidth;
4075
+ if (colorStyles.stroke) {
4076
+ context.strokeStyle = colorStyles.stroke;
4077
+ }
4078
+ const drawData = {
4079
+ context,
4080
+ particle,
4081
+ radius,
4082
+ drawRadius: radius * drawScale,
4083
+ opacity,
4084
+ delta,
4085
+ pixelRatio: container.retina.pixelRatio,
4086
+ fill: fillEnabled,
4087
+ stroke: strokeWidth > minStrokeWidth,
4088
+ transformData,
4089
+ position: { ...pos },
4090
+ drawPosition,
4091
+ drawScale,
4092
+ };
4093
+ for (const plugin of container.plugins) {
4094
+ plugin.drawParticleTransform?.(drawData);
4095
+ }
4096
+ const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
4097
+ this.#drawBeforeEffect(effect, drawData);
4098
+ this.#drawShapeBeforeDraw(shape, drawData);
4099
+ this.#drawShape(shape, drawData);
4100
+ this.#drawShapeAfterDraw(shape, drawData);
4101
+ this.#drawAfterEffect(effect, drawData);
4102
+ context.resetTransform();
4103
+ }
4104
+ #drawParticlePlugin(context, plugin, particle, delta) {
4105
+ if (!plugin.drawParticle) {
4106
+ return;
4107
+ }
4108
+ plugin.drawParticle(context, particle, delta);
4109
+ }
4110
+ #drawShape(drawer, data) {
4111
+ if (!drawer) {
4112
+ return;
4113
+ }
4114
+ const { context, fill, particle, stroke } = data;
4115
+ if (!particle.shape) {
4116
+ return;
4117
+ }
4118
+ context.beginPath();
4119
+ drawer.draw(data);
4120
+ if (particle.shapeClose) {
4121
+ context.closePath();
4122
+ }
4123
+ if (fill) {
4124
+ context.fill();
4125
+ }
4126
+ if (stroke) {
4127
+ context.stroke();
4128
+ }
4129
+ }
4130
+ #drawShapeAfterDraw(drawer, data) {
4131
+ if (!drawer?.afterDraw) {
4132
+ return;
4133
+ }
4134
+ const { particle } = data;
4135
+ if (!particle.shape) {
4136
+ return;
4137
+ }
4138
+ drawer.afterDraw(data);
4139
+ }
4140
+ #drawShapeBeforeDraw(drawer, data) {
4141
+ if (!drawer?.beforeDraw) {
4142
+ return;
4143
+ }
4144
+ const { particle } = data;
4145
+ if (!particle.shape) {
4146
+ return;
4147
+ }
4148
+ drawer.beforeDraw(data);
4149
+ }
4150
+ #getPluginParticleColors(particle) {
4785
4151
  let fColor, sColor;
4786
4152
  for (const plugin of this.#colorPlugins) {
4787
4153
  if (!fColor && plugin.particleFillColor) {
@@ -4797,7 +4163,7 @@
4797
4163
  this.#reusablePluginColors[fColorIndex] = fColor;
4798
4164
  this.#reusablePluginColors[sColorIndex] = sColor;
4799
4165
  return this.#reusablePluginColors;
4800
- };
4166
+ }
4801
4167
  }
4802
4168
 
4803
4169
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4929,6 +4295,7 @@
4929
4295
  obs.observe(element, { attributes: true });
4930
4296
  });
4931
4297
  this.initPlugins();
4298
+ this.#initContext();
4932
4299
  this.render.init();
4933
4300
  }
4934
4301
  initBackground() {
@@ -4938,7 +4305,7 @@
4938
4305
  }
4939
4306
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4940
4307
  if (color) {
4941
- elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity);
4308
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4942
4309
  }
4943
4310
  else {
4944
4311
  elementStyle.backgroundColor = "";
@@ -4960,7 +4327,7 @@
4960
4327
  if (this.#generated && this.domElement) {
4961
4328
  this.domElement.remove();
4962
4329
  }
4963
- const container = this.#container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4330
+ const domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4964
4331
  this.domElement = domCanvas;
4965
4332
  this.#generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4966
4333
  this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
@@ -4981,26 +4348,6 @@
4981
4348
  const pxRatio = this.#container.retina.pixelRatio, retinaSize = this.size;
4982
4349
  renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4983
4350
  renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4984
- const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4985
- this.render.setContextSettings({
4986
- alpha: true,
4987
- colorSpace: canSupportHdrQuery?.matches && container.hdr ? "display-p3" : "srgb",
4988
- desynchronized: true,
4989
- willReadFrequently: false,
4990
- });
4991
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4992
- this.#safeMutationObserver(obs => {
4993
- obs.disconnect();
4994
- });
4995
- container.retina.init();
4996
- this.initBackground();
4997
- this.#safeMutationObserver(obs => {
4998
- const element = this.domElement;
4999
- if (!element || !(element instanceof Node)) {
5000
- return;
5001
- }
5002
- obs.observe(element, { attributes: true });
5003
- });
5004
4351
  }
5005
4352
  resize() {
5006
4353
  const element = this.domElement;
@@ -5068,12 +4415,30 @@
5068
4415
  await container.refresh();
5069
4416
  }
5070
4417
  }
5071
- #applyResizePlugins = () => {
4418
+ #applyResizePlugins() {
5072
4419
  for (const plugin of this.#resizePlugins) {
5073
4420
  plugin.resize?.();
5074
4421
  }
5075
- };
5076
- #initStyle = () => {
4422
+ }
4423
+ #initContext() {
4424
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4425
+ safeMatchMedia("(color-gamut: p3)")?.matches &&
4426
+ safeMatchMedia("(dynamic-range: high)")?.matches;
4427
+ this.render.setContextSettings({
4428
+ alpha: true,
4429
+ desynchronized: true,
4430
+ willReadFrequently: false,
4431
+ ...(canSupportHdr
4432
+ ? { colorSpace: "display-p3", colorType: "float16" }
4433
+ : { colorSpace: "srgb" }),
4434
+ });
4435
+ const renderCanvas = this.renderCanvas;
4436
+ if (!renderCanvas) {
4437
+ return;
4438
+ }
4439
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4440
+ }
4441
+ #initStyle() {
5077
4442
  const element = this.domElement, options = this.#container.actualOptions;
5078
4443
  if (!element) {
5079
4444
  return;
@@ -5094,8 +4459,8 @@
5094
4459
  }
5095
4460
  element.style.setProperty(key, value, "important");
5096
4461
  }
5097
- };
5098
- #repairStyle = () => {
4462
+ }
4463
+ #repairStyle() {
5099
4464
  const element = this.domElement;
5100
4465
  if (!element) {
5101
4466
  return;
@@ -5114,27 +4479,27 @@
5114
4479
  }
5115
4480
  observer.observe(element, { attributes: true });
5116
4481
  });
5117
- };
5118
- #resetOriginalStyle = () => {
4482
+ }
4483
+ #resetOriginalStyle() {
5119
4484
  const element = this.domElement, originalStyle = this.#originalStyle;
5120
4485
  if (!element || !originalStyle) {
5121
4486
  return;
5122
4487
  }
5123
4488
  setStyle(element, originalStyle, true);
5124
- };
5125
- #safeMutationObserver = callback => {
4489
+ }
4490
+ #safeMutationObserver(callback) {
5126
4491
  if (!this.#mutationObserver) {
5127
4492
  return;
5128
4493
  }
5129
4494
  callback(this.#mutationObserver);
5130
- };
5131
- #setFullScreenStyle = () => {
4495
+ }
4496
+ #setFullScreenStyle() {
5132
4497
  const element = this.domElement;
5133
4498
  if (!element) {
5134
4499
  return;
5135
4500
  }
5136
4501
  setStyle(element, getFullScreenStyle(this.#container.actualOptions.fullScreen.zIndex), true);
5137
- };
4502
+ }
5138
4503
  }
5139
4504
 
5140
4505
  class EventListeners {
@@ -5159,7 +4524,7 @@
5159
4524
  removeListeners() {
5160
4525
  this.#manageListeners(false);
5161
4526
  }
5162
- #handleVisibilityChange = () => {
4527
+ #handleVisibilityChange() {
5163
4528
  const container = this.#container, options = container.actualOptions;
5164
4529
  if (!options.pauseOnBlur) {
5165
4530
  return;
@@ -5177,8 +4542,8 @@
5177
4542
  container.draw(true);
5178
4543
  }
5179
4544
  }
5180
- };
5181
- #handleWindowResize = () => {
4545
+ }
4546
+ #handleWindowResize() {
5182
4547
  if (this.#resizeTimeout) {
5183
4548
  clearTimeout(this.#resizeTimeout);
5184
4549
  this.#resizeTimeout = undefined;
@@ -5188,13 +4553,13 @@
5188
4553
  await canvas.windowResize();
5189
4554
  };
5190
4555
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
5191
- };
5192
- #manageListeners = add => {
4556
+ }
4557
+ #manageListeners(add) {
5193
4558
  const handlers = this.#handlers;
5194
4559
  this.#manageResize(add);
5195
4560
  manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
5196
- };
5197
- #manageResize = add => {
4561
+ }
4562
+ #manageResize(add) {
5198
4563
  const handlers = this.#handlers, container = this.#container, options = container.actualOptions;
5199
4564
  if (!options.resize.enable) {
5200
4565
  return;
@@ -5221,7 +4586,7 @@
5221
4586
  });
5222
4587
  this.#resizeObserver.observe(canvasEl);
5223
4588
  }
5224
- };
4589
+ }
5225
4590
  }
5226
4591
 
5227
4592
  function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
@@ -5248,6 +4613,131 @@
5248
4613
  data.setCb(data.radius);
5249
4614
  }
5250
4615
  }
4616
+ function normalizeAngle(angle, modulus) {
4617
+ const normalized = angle % modulus;
4618
+ return normalized < defaultAngle ? normalized + modulus : normalized;
4619
+ }
4620
+ function initParticleState(particle, id, group) {
4621
+ particle.id = id;
4622
+ particle.group = group;
4623
+ particle.justWarped = false;
4624
+ particle.effectClose = true;
4625
+ particle.shapeClose = true;
4626
+ particle.pathRotation = false;
4627
+ particle.lastPathTime = 0;
4628
+ particle.destroyed = false;
4629
+ particle.unbreakable = false;
4630
+ particle.isRotating = false;
4631
+ particle.rotation = 0;
4632
+ particle.misplaced = false;
4633
+ particle.retina = {
4634
+ maxDistance: {},
4635
+ maxSpeed: 0,
4636
+ moveDrift: 0,
4637
+ moveSpeed: 0,
4638
+ sizeAnimationSpeed: 0,
4639
+ };
4640
+ particle.size = {
4641
+ value: 1,
4642
+ max: 1,
4643
+ min: 1,
4644
+ enable: false,
4645
+ };
4646
+ particle.outType = ParticleOutType.normal;
4647
+ particle.ignoresResizeRatio = true;
4648
+ }
4649
+ function resolveParticleOptions(particle, container, pluginManager, overrideOptions) {
4650
+ const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates;
4651
+ particle.effect = itemFromSingleOrMultiple(particlesOptions.effect.type, particle.id, reduceDuplicates);
4652
+ particle.shape = itemFromSingleOrMultiple(particlesOptions.shape.type, particle.id, reduceDuplicates);
4653
+ const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
4654
+ if (overrideOptions) {
4655
+ if (overrideOptions.effect) {
4656
+ const overrideEffectType = overrideOptions.effect.type;
4657
+ if (overrideEffectType && overrideEffectType !== particle.effect) {
4658
+ const effect = itemFromSingleOrMultiple(overrideEffectType, particle.id, reduceDuplicates);
4659
+ if (effect) {
4660
+ particle.effect = effect;
4661
+ }
4662
+ }
4663
+ effectOptions.load(overrideOptions.effect);
4664
+ }
4665
+ if (overrideOptions.shape) {
4666
+ const overrideShapeType = overrideOptions.shape.type;
4667
+ if (overrideShapeType && overrideShapeType !== particle.shape) {
4668
+ const shape = itemFromSingleOrMultiple(overrideShapeType, particle.id, reduceDuplicates);
4669
+ if (shape) {
4670
+ particle.shape = shape;
4671
+ }
4672
+ }
4673
+ shapeOptions.load(overrideOptions.shape);
4674
+ }
4675
+ }
4676
+ if (particle.effect === randomColorValue) {
4677
+ const availableEffects = [...container.effectDrawers.keys()];
4678
+ particle.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
4679
+ }
4680
+ if (particle.shape === randomColorValue) {
4681
+ const availableShapes = [...container.shapeDrawers.keys()];
4682
+ particle.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
4683
+ }
4684
+ particle.effectData = particle.effect
4685
+ ? loadEffectData(particle.effect, effectOptions, particle.id, reduceDuplicates)
4686
+ : undefined;
4687
+ particle.shapeData = particle.shape
4688
+ ? loadShapeData(particle.shape, shapeOptions, particle.id, reduceDuplicates)
4689
+ : undefined;
4690
+ particlesOptions.load(overrideOptions);
4691
+ const effectData = particle.effectData, shapeData = particle.shapeData;
4692
+ if (effectData) {
4693
+ particlesOptions.load(effectData.particles);
4694
+ }
4695
+ if (shapeData) {
4696
+ particlesOptions.load(shapeData.particles);
4697
+ }
4698
+ particle.effectClose = effectData?.close ?? particlesOptions.effect.close;
4699
+ particle.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
4700
+ return particlesOptions;
4701
+ }
4702
+ function initParticleDrawers(particle, container) {
4703
+ let effectDrawer, shapeDrawer;
4704
+ if (particle.effect) {
4705
+ effectDrawer = container.effectDrawers.get(particle.effect);
4706
+ }
4707
+ if (effectDrawer?.loadEffect) {
4708
+ effectDrawer.loadEffect(particle);
4709
+ }
4710
+ if (particle.shape) {
4711
+ shapeDrawer = container.shapeDrawers.get(particle.shape);
4712
+ }
4713
+ if (shapeDrawer?.loadShape) {
4714
+ shapeDrawer.loadShape(particle);
4715
+ }
4716
+ const sideCountFunc = shapeDrawer?.getSidesCount;
4717
+ if (sideCountFunc) {
4718
+ particle.sides = sideCountFunc(particle);
4719
+ }
4720
+ }
4721
+ function runUpdaterPreInit(updaters, particle) {
4722
+ for (const updater of updaters) {
4723
+ updater.preInit?.(particle);
4724
+ }
4725
+ }
4726
+ function runUpdaterInit(updaters, particle) {
4727
+ for (const updater of updaters) {
4728
+ updater.init(particle);
4729
+ }
4730
+ }
4731
+ function runDrawerInit(container, particle) {
4732
+ const shapeDrawer = particle.shape ? container.shapeDrawers.get(particle.shape) : undefined, effectDrawer = particle.effect ? container.effectDrawers.get(particle.effect) : undefined;
4733
+ effectDrawer?.particleInit?.(container, particle);
4734
+ shapeDrawer?.particleInit?.(container, particle);
4735
+ }
4736
+ function runParticleCreatedPlugins(container, particle) {
4737
+ for (const plugin of container.particleCreatedPlugins) {
4738
+ plugin.particleCreated?.(particle);
4739
+ }
4740
+ }
5251
4741
  class Particle {
5252
4742
  backColor;
5253
4743
  bubble;
@@ -5373,88 +4863,20 @@
5373
4863
  const rotateData = this.getRotateData(), rotating = this.isRotating;
5374
4864
  this.#cachedTransform.a = rotateData.cos * (externalTransform.a ?? defaultTransform.a);
5375
4865
  this.#cachedTransform.b = rotating
5376
- ? rotateData.sin * (externalTransform.b ?? identity$1)
4866
+ ? rotateData.sin * (externalTransform.b ?? identity)
5377
4867
  : (externalTransform.b ?? defaultTransform.b);
5378
4868
  this.#cachedTransform.c = rotating
5379
- ? -rotateData.sin * (externalTransform.c ?? identity$1)
4869
+ ? -rotateData.sin * (externalTransform.c ?? identity)
5380
4870
  : (externalTransform.c ?? defaultTransform.c);
5381
4871
  this.#cachedTransform.d = rotateData.cos * (externalTransform.d ?? defaultTransform.d);
5382
4872
  return this.#cachedTransform;
5383
4873
  }
5384
4874
  init(id, position, overrideOptions, group) {
5385
4875
  const container = this.#container;
5386
- this.id = id;
5387
- this.group = group;
5388
- this.justWarped = false;
5389
- this.effectClose = true;
5390
- this.shapeClose = true;
5391
- this.pathRotation = false;
5392
- this.lastPathTime = 0;
5393
- this.destroyed = false;
5394
- this.unbreakable = false;
5395
- this.isRotating = false;
5396
- this.rotation = 0;
5397
- this.misplaced = false;
5398
- this.retina = {
5399
- maxDistance: {},
5400
- maxSpeed: 0,
5401
- moveDrift: 0,
5402
- moveSpeed: 0,
5403
- sizeAnimationSpeed: 0,
5404
- };
5405
- this.size = {
5406
- value: 1,
5407
- max: 1,
5408
- min: 1,
5409
- enable: false,
5410
- };
5411
- this.outType = ParticleOutType.normal;
5412
- this.ignoresResizeRatio = true;
5413
- const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(this.#pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates, effectType = particlesOptions.effect.type, shapeType = particlesOptions.shape.type;
5414
- this.effect = itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
5415
- this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
5416
- const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
5417
- if (overrideOptions) {
5418
- if (overrideOptions.effect?.type && overrideOptions.effect.type !== this.effect) {
5419
- const overrideEffectType = overrideOptions.effect.type, effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
5420
- if (effect) {
5421
- this.effect = effect;
5422
- effectOptions.load(overrideOptions.effect);
5423
- }
5424
- }
5425
- if (overrideOptions.shape?.type && overrideOptions.shape.type !== this.shape) {
5426
- const overrideShapeType = overrideOptions.shape.type, shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
5427
- if (shape) {
5428
- this.shape = shape;
5429
- shapeOptions.load(overrideOptions.shape);
5430
- }
5431
- }
5432
- }
5433
- if (this.effect === randomColorValue) {
5434
- const availableEffects = [...this.#container.effectDrawers.keys()];
5435
- this.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
5436
- }
5437
- if (this.shape === randomColorValue) {
5438
- const availableShapes = [...this.#container.shapeDrawers.keys()];
5439
- this.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
5440
- }
5441
- this.effectData = this.effect ? loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates) : undefined;
5442
- this.shapeData = this.shape ? loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates) : undefined;
5443
- particlesOptions.load(overrideOptions);
5444
- const effectData = this.effectData, shapeData = this.shapeData;
5445
- if (effectData) {
5446
- particlesOptions.load(effectData.particles);
5447
- }
5448
- if (shapeData) {
5449
- particlesOptions.load(shapeData.particles);
5450
- }
5451
- this.effectClose = effectData?.close ?? particlesOptions.effect.close;
5452
- this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
5453
- this.options = particlesOptions;
4876
+ initParticleState(this, id, group);
4877
+ this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
5454
4878
  container.retina.initParticle(this);
5455
- for (const updater of container.particleUpdaters) {
5456
- updater.preInit?.(this);
5457
- }
4879
+ runUpdaterPreInit(container.particleUpdaters, this);
5458
4880
  this.bubble = {
5459
4881
  inRange: false,
5460
4882
  };
@@ -5467,32 +4889,11 @@
5467
4889
  this.velocity = this.initialVelocity.copy();
5468
4890
  this.zIndexFactor = this.position.z / container.zLayers;
5469
4891
  this.sides = 24;
5470
- let effectDrawer, shapeDrawer;
5471
- if (this.effect) {
5472
- effectDrawer = container.effectDrawers.get(this.effect);
5473
- }
5474
- if (effectDrawer?.loadEffect) {
5475
- effectDrawer.loadEffect(this);
5476
- }
5477
- if (this.shape) {
5478
- shapeDrawer = container.shapeDrawers.get(this.shape);
5479
- }
5480
- if (shapeDrawer?.loadShape) {
5481
- shapeDrawer.loadShape(this);
5482
- }
5483
- const sideCountFunc = shapeDrawer?.getSidesCount;
5484
- if (sideCountFunc) {
5485
- this.sides = sideCountFunc(this);
5486
- }
4892
+ initParticleDrawers(this, container);
5487
4893
  this.spawning = false;
5488
- for (const updater of container.particleUpdaters) {
5489
- updater.init(this);
5490
- }
5491
- effectDrawer?.particleInit?.(container, this);
5492
- shapeDrawer?.particleInit?.(container, this);
5493
- for (const plugin of container.particleCreatedPlugins) {
5494
- plugin.particleCreated?.(this);
5495
- }
4894
+ runUpdaterInit(container.particleUpdaters, this);
4895
+ runDrawerInit(container, this);
4896
+ runParticleCreatedPlugins(container, this);
5496
4897
  }
5497
4898
  isInsideCanvas(direction) {
5498
4899
  return this.#getInsideCanvasResult({ direction }).inside;
@@ -5506,15 +4907,15 @@
5506
4907
  }
5507
4908
  const angle = this.roll.angle;
5508
4909
  if (this.roll.horizontal && this.roll.vertical) {
5509
- const normalizedAngle = angle % doublePI, adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + doublePI : normalizedAngle;
4910
+ const adjustedAngle = normalizeAngle(angle, doublePI);
5510
4911
  return adjustedAngle >= Math.PI * half && adjustedAngle < Math.PI * triple * half;
5511
4912
  }
5512
4913
  if (this.roll.horizontal) {
5513
- const normalizedAngle = (angle + Math.PI * half) % (Math.PI * double), adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + Math.PI * double : normalizedAngle;
4914
+ const adjustedAngle = normalizeAngle(angle + Math.PI * half, doublePI);
5514
4915
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
5515
4916
  }
5516
4917
  if (this.roll.vertical) {
5517
- const normalizedAngle = angle % (Math.PI * double), adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + Math.PI * double : normalizedAngle;
4918
+ const adjustedAngle = normalizeAngle(angle, doublePI);
5518
4919
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
5519
4920
  }
5520
4921
  return false;
@@ -5527,10 +4928,10 @@
5527
4928
  updater.reset?.(this);
5528
4929
  }
5529
4930
  }
5530
- #calcPosition = (position, zIndex) => {
4931
+ #calcPosition(position, zIndex) {
5531
4932
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
5532
- const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size, abortController = new AbortController(), { signal } = abortController;
5533
- while (!signal.aborted) {
4933
+ const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
4934
+ for (;;) {
5534
4935
  for (const plugin of plugins) {
5535
4936
  const pluginPos = plugin.particlePosition?.(posVec, this);
5536
4937
  if (pluginPos) {
@@ -5558,9 +4959,8 @@
5558
4959
  tryCount += tryCountIncrement;
5559
4960
  posVec = undefined;
5560
4961
  }
5561
- return posVec;
5562
- };
5563
- #calculateVelocity = () => {
4962
+ }
4963
+ #calculateVelocity() {
5564
4964
  const moveOptions = this.options.move, baseVelocity = getParticleBaseVelocity(this.direction), res = baseVelocity.copy();
5565
4965
  if (moveOptions.direction === MoveDirection.inside || moveOptions.direction === MoveDirection.outside) {
5566
4966
  return res;
@@ -5576,8 +4976,8 @@
5576
4976
  res.length *= getRandom();
5577
4977
  }
5578
4978
  return res;
5579
- };
5580
- #fixHorizontal = (pos, radius, outMode) => {
4979
+ }
4980
+ #fixHorizontal(pos, radius, outMode) {
5581
4981
  fixOutMode({
5582
4982
  outMode,
5583
4983
  checkModes: [OutMode.bounce],
@@ -5586,8 +4986,8 @@
5586
4986
  setCb: (value) => (pos.x += value),
5587
4987
  radius,
5588
4988
  });
5589
- };
5590
- #fixVertical = (pos, radius, outMode) => {
4989
+ }
4990
+ #fixVertical(pos, radius, outMode) {
5591
4991
  fixOutMode({
5592
4992
  outMode,
5593
4993
  checkModes: [OutMode.bounce],
@@ -5596,8 +4996,8 @@
5596
4996
  setCb: (value) => (pos.y += value),
5597
4997
  radius,
5598
4998
  });
5599
- };
5600
- #getDefaultInsideCanvasResult = (direction, outMode) => {
4999
+ }
5000
+ #getDefaultInsideCanvasResult(direction, outMode) {
5601
5001
  const radius = this.getRadius(), canvasSize = this.#container.canvas.size, position = this.position, isBounce = outMode === OutMode.bounce;
5602
5002
  if (direction === OutModeDirection.bottom) {
5603
5003
  return {
@@ -5630,8 +5030,8 @@
5630
5030
  position.x <= canvasSize.width + radius,
5631
5031
  reason: "default",
5632
5032
  };
5633
- };
5634
- #getInsideCanvasCallbackData = (direction, outMode) => {
5033
+ }
5034
+ #getInsideCanvasCallbackData(direction, outMode) {
5635
5035
  return {
5636
5036
  canvasSize: this.#container.canvas.size,
5637
5037
  direction,
@@ -5639,8 +5039,8 @@
5639
5039
  particle: this,
5640
5040
  radius: this.getRadius(),
5641
5041
  };
5642
- };
5643
- #getInsideCanvasResult = (data) => {
5042
+ }
5043
+ #getInsideCanvasResult(data) {
5644
5044
  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;
5645
5045
  if (!shapeCheck && !effectCheck) {
5646
5046
  return defaultResult;
@@ -5655,8 +5055,8 @@
5655
5055
  };
5656
5056
  }
5657
5057
  return shapeResult ?? effectResult ?? defaultResult;
5658
- };
5659
- #getRollColor = color => {
5058
+ }
5059
+ #getRollColor(color) {
5660
5060
  if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
5661
5061
  return color;
5662
5062
  }
@@ -5670,8 +5070,8 @@
5670
5070
  return alterHsl(color, this.roll.alter.type, this.roll.alter.value);
5671
5071
  }
5672
5072
  return color;
5673
- };
5674
- #initPosition = position => {
5073
+ }
5074
+ #initPosition(position) {
5675
5075
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5676
5076
  if (!initialPosition) {
5677
5077
  throw new Error("a valid position cannot be found for particle");
@@ -5694,8 +5094,8 @@
5694
5094
  break;
5695
5095
  }
5696
5096
  this.offset = Vector.origin;
5697
- };
5698
- #normalizeInsideCanvasResult = (result, reason) => {
5097
+ }
5098
+ #normalizeInsideCanvasResult(result, reason) {
5699
5099
  if (typeof result === "boolean") {
5700
5100
  return {
5701
5101
  inside: result,
@@ -5707,7 +5107,7 @@
5707
5107
  margin: result.margin,
5708
5108
  reason: result.reason ?? reason,
5709
5109
  };
5710
- };
5110
+ }
5711
5111
  }
5712
5112
 
5713
5113
  class SpatialHashGrid {
@@ -6060,10 +5460,10 @@
6060
5460
  }
6061
5461
  this.#resizeFactor = undefined;
6062
5462
  }
6063
- #addToPool = (...particles) => {
5463
+ #addToPool(...particles) {
6064
5464
  this.#pool.push(...particles);
6065
- };
6066
- #applyDensity = (options, pluginsCount, group, groupOptions) => {
5465
+ }
5466
+ #applyDensity(options, pluginsCount, group, groupOptions) {
6067
5467
  const numberOptions = options.number;
6068
5468
  if (!numberOptions.density.enable) {
6069
5469
  if (group === undefined) {
@@ -6087,36 +5487,19 @@
6087
5487
  else if (particlesCount > particlesNumber) {
6088
5488
  this.removeQuantity(particlesCount - particlesNumber, group);
6089
5489
  }
6090
- };
6091
- #createBuckets = (zLayers) => {
5490
+ }
5491
+ #createBuckets(zLayers) {
6092
5492
  const bucketCount = Math.max(Math.floor(zLayers), one);
6093
5493
  return Array.from({ length: bucketCount }, () => []);
6094
- };
6095
- #getBucketIndex = (zIndex) => {
5494
+ }
5495
+ #getBucketIndex(zIndex) {
6096
5496
  const maxBucketIndex = this.#zBuckets.length - one;
6097
5497
  if (maxBucketIndex <= minIndex) {
6098
5498
  return minIndex;
6099
5499
  }
6100
5500
  return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
6101
- };
6102
- #getParticleInsertIndex = (bucket, particleId) => {
6103
- let start = minIndex, end = bucket.length;
6104
- while (start < end) {
6105
- const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
6106
- if (!middleParticle) {
6107
- end = middle;
6108
- continue;
6109
- }
6110
- if (middleParticle.id < particleId) {
6111
- start = middle + one;
6112
- }
6113
- else {
6114
- end = middle;
6115
- }
6116
- }
6117
- return start;
6118
- };
6119
- #initDensityFactor = densityOptions => {
5501
+ }
5502
+ #initDensityFactor(densityOptions) {
6120
5503
  const container = this.#container;
6121
5504
  if (!densityOptions.enable) {
6122
5505
  return defaultDensityFactor;
@@ -6126,16 +5509,16 @@
6126
5509
  return defaultDensityFactor;
6127
5510
  }
6128
5511
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
6129
- };
6130
- #insertParticleIntoBucket = (particle) => {
5512
+ }
5513
+ #insertParticleIntoBucket(particle) {
6131
5514
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
6132
5515
  if (!bucket) {
6133
5516
  return;
6134
5517
  }
6135
- bucket.splice(this.#getParticleInsertIndex(bucket, particle.id), empty, particle);
5518
+ bucket.push(particle);
6136
5519
  this.#particleBuckets.set(particle.id, bucketIndex);
6137
- };
6138
- #removeParticle = (index, group, override) => {
5520
+ }
5521
+ #removeParticle(index, group, override) {
6139
5522
  const particle = this.#array[index];
6140
5523
  if (!particle) {
6141
5524
  return false;
@@ -6151,22 +5534,20 @@
6151
5534
  });
6152
5535
  this.#addToPool(particle);
6153
5536
  return true;
6154
- };
6155
- #removeParticleFromBucket = (particle) => {
5537
+ }
5538
+ #removeParticleFromBucket(particle) {
6156
5539
  const bucketIndex = this.#particleBuckets.get(particle.id) ?? this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
6157
5540
  if (!bucket) {
6158
5541
  this.#particleBuckets.delete(particle.id);
6159
5542
  return;
6160
5543
  }
6161
- const particleIndex = this.#getParticleInsertIndex(bucket, particle.id);
6162
- if (bucket[particleIndex]?.id !== particle.id) {
6163
- this.#particleBuckets.delete(particle.id);
6164
- return;
5544
+ const idx = bucket.findIndex(p => p.id === particle.id);
5545
+ if (idx >= minIndex) {
5546
+ bucket.splice(idx, deleteCount);
6165
5547
  }
6166
- bucket.splice(particleIndex, deleteCount);
6167
5548
  this.#particleBuckets.delete(particle.id);
6168
- };
6169
- #resetBuckets = (zLayers) => {
5549
+ }
5550
+ #resetBuckets(zLayers) {
6170
5551
  const bucketCount = Math.max(Math.floor(zLayers), one);
6171
5552
  if (this.#zBuckets.length !== bucketCount) {
6172
5553
  this.#zBuckets = this.#createBuckets(bucketCount);
@@ -6175,8 +5556,8 @@
6175
5556
  for (const bucket of this.#zBuckets) {
6176
5557
  bucket.length = minIndex;
6177
5558
  }
6178
- };
6179
- #updateParticleBucket = (particle) => {
5559
+ }
5560
+ #updateParticleBucket(particle) {
6180
5561
  const newBucketIndex = this.#getBucketIndex(particle.position.z), currentBucketIndex = this.#particleBuckets.get(particle.id);
6181
5562
  if (currentBucketIndex === undefined) {
6182
5563
  this.#insertParticleIntoBucket(particle);
@@ -6187,9 +5568,9 @@
6187
5568
  }
6188
5569
  const currentBucket = this.#zBuckets[currentBucketIndex];
6189
5570
  if (currentBucket) {
6190
- const particleIndex = this.#getParticleInsertIndex(currentBucket, particle.id);
6191
- if (currentBucket[particleIndex]?.id === particle.id) {
6192
- currentBucket.splice(particleIndex, deleteCount);
5571
+ const idx = currentBucket.findIndex(p => p.id === particle.id);
5572
+ if (idx >= minIndex) {
5573
+ currentBucket.splice(idx, deleteCount);
6193
5574
  }
6194
5575
  }
6195
5576
  const newBucket = this.#zBuckets[newBucketIndex];
@@ -6197,10 +5578,16 @@
6197
5578
  this.#particleBuckets.set(particle.id, newBucketIndex);
6198
5579
  return;
6199
5580
  }
6200
- newBucket.splice(this.#getParticleInsertIndex(newBucket, particle.id), empty, particle);
5581
+ newBucket.push(particle);
5582
+ if (newBucket.length >= double) {
5583
+ const prev = newBucket[newBucket.length - double];
5584
+ if (prev && particle.id < prev.id) {
5585
+ newBucket.sort((a, b) => a.id - b.id);
5586
+ }
5587
+ }
6201
5588
  this.#particleBuckets.set(particle.id, newBucketIndex);
6202
- };
6203
- #updateParticlesPhase1 = (delta) => {
5589
+ }
5590
+ #updateParticlesPhase1(delta) {
6204
5591
  const particlesToDelete = new Set(), resizeFactor = this.#resizeFactor;
6205
5592
  for (const particle of this.#array) {
6206
5593
  if (resizeFactor && !particle.ignoresResizeRatio) {
@@ -6226,8 +5613,8 @@
6226
5613
  this.grid.insert(particle);
6227
5614
  }
6228
5615
  return particlesToDelete;
6229
- };
6230
- #updateParticlesPhase2 = (delta, particlesToDelete) => {
5616
+ }
5617
+ #updateParticlesPhase2(delta, particlesToDelete) {
6231
5618
  for (const particle of this.#array) {
6232
5619
  if (particle.destroyed) {
6233
5620
  particlesToDelete.add(particle);
@@ -6243,7 +5630,7 @@
6243
5630
  }
6244
5631
  this.#updateParticleBucket(particle);
6245
5632
  }
6246
- };
5633
+ }
6247
5634
  }
6248
5635
 
6249
5636
  class Retina {
@@ -6605,7 +5992,7 @@
6605
5992
  }
6606
5993
  return refresh;
6607
5994
  }
6608
- #nextFrame = (timestamp) => {
5995
+ #nextFrame(timestamp) {
6609
5996
  try {
6610
5997
  if (!this.#smooth &&
6611
5998
  this.#lastFrameTime !== undefined &&
@@ -6633,7 +6020,7 @@
6633
6020
  catch (e) {
6634
6021
  getLogger().error("error in animation loop", e);
6635
6022
  }
6636
- };
6023
+ }
6637
6024
  }
6638
6025
 
6639
6026
  var Container$1 = /*#__PURE__*/Object.freeze({
@@ -6679,7 +6066,7 @@
6679
6066
  BlendPluginInstance: BlendPluginInstance
6680
6067
  });
6681
6068
 
6682
- const minVelocity = 0, identity = 1, moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
6069
+ const moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
6683
6070
  function applyDistance(particle) {
6684
6071
  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;
6685
6072
  if (!hDistance && !vDistance) {
@@ -7074,7 +6461,7 @@
7074
6461
  getLogger().error(e);
7075
6462
  }
7076
6463
  }
7077
- #initTrail = async () => {
6464
+ async #initTrail() {
7078
6465
  const options = this.#container.actualOptions, trail = options.trail;
7079
6466
  if (!trail?.enable) {
7080
6467
  return;
@@ -7112,7 +6499,7 @@
7112
6499
  img.src = trailFill.image;
7113
6500
  });
7114
6501
  }
7115
- };
6502
+ }
7116
6503
  }
7117
6504
 
7118
6505
  var TrailPluginInstance$1 = /*#__PURE__*/Object.freeze({
@@ -7205,7 +6592,13 @@
7205
6592
  this.#paused = !this.options.autoPlay;
7206
6593
  this.#particlesOptions = particlesOptions;
7207
6594
  this.#size = this.#calcSize();
7208
- this.size = getSize(this.#size, this.#container.canvas.size);
6595
+ this.size =
6596
+ this.#size.mode === PixelMode.percent
6597
+ ? {
6598
+ width: (this.#size.width / percentDenominator) * this.#container.canvas.size.width,
6599
+ height: (this.#size.height / percentDenominator) * this.#container.canvas.size.height,
6600
+ }
6601
+ : { width: this.#size.width, height: this.#size.height };
7209
6602
  this.#lifeCount = this.options.life.count ?? defaultLifeCount;
7210
6603
  this.#immortal = this.#lifeCount <= minLifeCount;
7211
6604
  if (this.options.domId) {
@@ -7276,7 +6669,13 @@
7276
6669
  ? initialPosition
7277
6670
  : this.#calcPosition();
7278
6671
  this.#size = this.#calcSize();
7279
- this.size = getSize(this.#size, container.canvas.size);
6672
+ this.size =
6673
+ this.#size.mode === PixelMode.percent
6674
+ ? {
6675
+ width: (this.#size.width / percentDenominator) * container.canvas.size.width,
6676
+ height: (this.#size.height / percentDenominator) * container.canvas.size.height,
6677
+ }
6678
+ : { width: this.#size.width, height: this.#size.height };
7280
6679
  this.#shape?.resize(this.position, this.size);
7281
6680
  }
7282
6681
  update(delta) {
@@ -7376,7 +6775,7 @@
7376
6775
  return size;
7377
6776
  })());
7378
6777
  }
7379
- #destroy = () => {
6778
+ #destroy() {
7380
6779
  this.#mutationObserver?.disconnect();
7381
6780
  this.#mutationObserver = undefined;
7382
6781
  this.#resizeObserver?.disconnect();
@@ -7385,7 +6784,7 @@
7385
6784
  this.#container.dispatchEvent("emitterDestroyed", {
7386
6785
  emitter: this,
7387
6786
  });
7388
- };
6787
+ }
7389
6788
  #emit() {
7390
6789
  if (this.#paused) {
7391
6790
  return;
@@ -7445,7 +6844,7 @@
7445
6844
  }
7446
6845
  }
7447
6846
  }
7448
- #prepareToDie = () => {
6847
+ #prepareToDie() {
7449
6848
  if (this.#paused) {
7450
6849
  return;
7451
6850
  }
@@ -7453,8 +6852,8 @@
7453
6852
  if ((this.#lifeCount > minLifeCount || this.#immortal) && duration !== undefined && duration > minDuration) {
7454
6853
  this.#duration = duration * millisecondsToSeconds;
7455
6854
  }
7456
- };
7457
- #setColorAnimation = (animation, initValue, maxValue, factor = defaultColorAnimationFactor) => {
6855
+ }
6856
+ #setColorAnimation(animation, initValue, maxValue, factor = defaultColorAnimationFactor) {
7458
6857
  const container = this.#container;
7459
6858
  if (!animation.enable) {
7460
6859
  return initValue;
@@ -7463,7 +6862,7 @@
7463
6862
  ? (delay * millisecondsToSeconds) / container.retina.reduceFactor
7464
6863
  : Infinity, colorSpeed = getRangeValue(animation.speed);
7465
6864
  return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
7466
- };
6865
+ }
7467
6866
  }
7468
6867
 
7469
6868
  var EmitterInstance$1 = /*#__PURE__*/Object.freeze({