@tsparticles/preset-hyperspace 4.1.3 → 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.3 */
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$2 = 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 = 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.3";
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
- }
2026
- }
2027
- }
2028
-
2029
- 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
- }
1511
+ loadProperty(this, "close", data.close);
1512
+ loadProperty(this, "type", data.type);
2053
1513
  }
2054
1514
  }
2055
1515
 
2056
- class ParticlesOptions {
2057
- bounce;
2058
- effect;
2059
- groups;
2060
- move;
2061
- number;
1516
+ class ZIndex extends ValueWithRandom {
1517
+ opacityRate = 1;
1518
+ sizeRate = 1;
1519
+ velocityRate = 1;
1520
+ doLoad(data) {
1521
+ super.doLoad(data);
1522
+ loadProperty(this, "opacityRate", data.opacityRate);
1523
+ loadProperty(this, "sizeRate", data.sizeRate);
1524
+ loadProperty(this, "velocityRate", data.velocityRate);
1525
+ }
1526
+ }
1527
+
1528
+ class ParticlesOptions extends OptionLoader {
1529
+ bounce = new ParticlesBounce();
1530
+ effect = new Effect();
1531
+ groups = {};
1532
+ move = new Move();
1533
+ number = new ParticlesNumber();
2062
1534
  paint;
2063
1535
  palette;
2064
- reduceDuplicates;
2065
- shape;
2066
- zIndex;
1536
+ reduceDuplicates = false;
1537
+ shape = new Shape();
1538
+ zIndex = new ZIndex();
2067
1539
  #container;
2068
1540
  #pluginManager;
2069
1541
  constructor(pluginManager, container) {
1542
+ super();
2070
1543
  this.#pluginManager = pluginManager;
2071
1544
  this.#container = container;
2072
- this.bounce = new ParticlesBounce();
2073
- this.effect = new Effect();
2074
- this.groups = {};
2075
- this.move = new Move();
2076
- this.number = new ParticlesNumber();
2077
1545
  this.paint = new Paint();
2078
1546
  this.paint.color = new AnimatableColor();
2079
1547
  this.paint.color.value = "#fff";
2080
1548
  this.paint.fill = new Fill();
2081
1549
  this.paint.fill.enable = true;
2082
- this.reduceDuplicates = false;
2083
- this.shape = new Shape();
2084
- this.zIndex = new ZIndex();
2085
1550
  }
2086
- load(data) {
2087
- if (isNull(data)) {
2088
- return;
2089
- }
1551
+ doLoad(data) {
2090
1552
  if (data.palette) {
2091
1553
  this.palette = data.palette;
2092
1554
  this.#importPalette(this.palette);
@@ -2144,7 +1606,7 @@
2144
1606
  }
2145
1607
  }
2146
1608
  }
2147
- #importPalette = (palette) => {
1609
+ #importPalette(palette) {
2148
1610
  const paletteData = this.#pluginManager.getPalette(palette);
2149
1611
  if (!paletteData) {
2150
1612
  return;
@@ -2188,69 +1650,49 @@
2188
1650
  mode: paletteData.blendMode,
2189
1651
  },
2190
1652
  });
2191
- };
2192
- }
2193
-
2194
- function loadOptions(options, ...sourceOptionsArr) {
2195
- for (const sourceOptions of sourceOptionsArr) {
2196
- options.load(sourceOptions);
2197
1653
  }
2198
1654
  }
1655
+
2199
1656
  function loadParticlesOptions(pluginManager, container, ...sourceOptionsArr) {
2200
1657
  const options = new ParticlesOptions(pluginManager, container);
2201
1658
  loadOptions(options, ...sourceOptionsArr);
2202
1659
  return options;
2203
1660
  }
2204
1661
 
2205
- class Options {
2206
- autoPlay;
1662
+ class Options extends OptionLoader {
1663
+ autoPlay = true;
2207
1664
  background;
2208
- clear;
2209
- defaultThemes;
2210
- delay;
2211
- detectRetina;
2212
- duration;
2213
- fpsLimit;
1665
+ clear = true;
1666
+ defaultThemes = {};
1667
+ delay = 0;
1668
+ detectRetina = true;
1669
+ duration = 0;
1670
+ fpsLimit = 120;
2214
1671
  fullScreen;
2215
- hdr;
1672
+ hdr = true;
2216
1673
  key;
2217
1674
  name;
2218
1675
  palette;
2219
1676
  particles;
2220
- pauseOnBlur;
2221
- pauseOnOutsideViewport;
1677
+ pauseOnBlur = true;
1678
+ pauseOnOutsideViewport = true;
2222
1679
  preset;
2223
1680
  resize;
2224
- smooth;
2225
- style;
2226
- zLayers;
1681
+ smooth = false;
1682
+ style = {};
1683
+ zLayers = 100;
2227
1684
  #container;
2228
1685
  #pluginManager;
2229
1686
  constructor(pluginManager, container) {
1687
+ super();
2230
1688
  this.#pluginManager = pluginManager;
2231
1689
  this.#container = container;
2232
- this.autoPlay = true;
2233
1690
  this.background = new Background();
2234
- this.clear = true;
2235
- this.defaultThemes = {};
2236
- this.delay = 0;
2237
1691
  this.fullScreen = new FullScreen();
2238
- this.detectRetina = true;
2239
- this.duration = 0;
2240
- this.fpsLimit = 120;
2241
- this.hdr = true;
2242
1692
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
2243
- this.pauseOnBlur = true;
2244
- this.pauseOnOutsideViewport = true;
2245
1693
  this.resize = new ResizeEvent();
2246
- this.smooth = false;
2247
- this.style = {};
2248
- this.zLayers = 100;
2249
1694
  }
2250
- load(data) {
2251
- if (isNull(data)) {
2252
- return;
2253
- }
1695
+ doLoad(data) {
2254
1696
  if (data.preset !== undefined) {
2255
1697
  this.preset = data.preset;
2256
1698
  executeOnSingleOrMultiple(this.preset, preset => {
@@ -2261,44 +1703,18 @@
2261
1703
  this.palette = data.palette;
2262
1704
  this.#importPalette(this.palette);
2263
1705
  }
2264
- if (data.autoPlay !== undefined) {
2265
- this.autoPlay = data.autoPlay;
2266
- }
2267
- if (data.clear !== undefined) {
2268
- this.clear = data.clear;
2269
- }
2270
- if (data.key !== undefined) {
2271
- this.key = data.key;
2272
- }
2273
- if (data.name !== undefined) {
2274
- this.name = data.name;
2275
- }
2276
- if (data.delay !== undefined) {
2277
- this.delay = setRangeValue(data.delay);
2278
- }
2279
- const detectRetina = data.detectRetina;
2280
- if (detectRetina !== undefined) {
2281
- this.detectRetina = detectRetina;
2282
- }
2283
- if (data.duration !== undefined) {
2284
- this.duration = setRangeValue(data.duration);
2285
- }
2286
- const fpsLimit = data.fpsLimit;
2287
- if (fpsLimit !== undefined) {
2288
- this.fpsLimit = fpsLimit;
2289
- }
2290
- if (data.hdr !== undefined) {
2291
- this.hdr = data.hdr;
2292
- }
2293
- if (data.pauseOnBlur !== undefined) {
2294
- this.pauseOnBlur = data.pauseOnBlur;
2295
- }
2296
- if (data.pauseOnOutsideViewport !== undefined) {
2297
- this.pauseOnOutsideViewport = data.pauseOnOutsideViewport;
2298
- }
2299
- if (data.zLayers !== undefined) {
2300
- this.zLayers = data.zLayers;
2301
- }
1706
+ loadProperty(this, "autoPlay", data.autoPlay);
1707
+ loadProperty(this, "clear", data.clear);
1708
+ loadProperty(this, "key", data.key);
1709
+ loadProperty(this, "name", data.name);
1710
+ loadRangeProperty(this, "delay", data.delay);
1711
+ loadProperty(this, "detectRetina", data.detectRetina);
1712
+ loadRangeProperty(this, "duration", data.duration);
1713
+ loadProperty(this, "fpsLimit", data.fpsLimit);
1714
+ loadProperty(this, "hdr", data.hdr);
1715
+ loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1716
+ loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1717
+ loadProperty(this, "zLayers", data.zLayers);
2302
1718
  this.background.load(data.background);
2303
1719
  const fullScreen = data.fullScreen;
2304
1720
  if (isBoolean(fullScreen)) {
@@ -2310,14 +1726,12 @@
2310
1726
  this.particles.load(data.particles);
2311
1727
  this.resize.load(data.resize);
2312
1728
  this.style = deepExtend(this.style, data.style);
2313
- if (data.smooth !== undefined) {
2314
- this.smooth = data.smooth;
2315
- }
1729
+ loadProperty(this, "smooth", data.smooth);
2316
1730
  this.#pluginManager.plugins.forEach(plugin => {
2317
1731
  plugin.loadOptions(this.#container, this, data);
2318
1732
  });
2319
1733
  }
2320
- #importPalette = palette => {
1734
+ #importPalette(palette) {
2321
1735
  const paletteData = this.#pluginManager.getPalette(palette);
2322
1736
  if (!paletteData) {
2323
1737
  return;
@@ -2334,143 +1748,19 @@
2334
1748
  palette,
2335
1749
  },
2336
1750
  });
2337
- };
2338
- #importPreset = preset => {
2339
- this.load(this.#pluginManager.getPreset(preset));
2340
- };
2341
- }
2342
-
2343
- function paintBase(context, dimension, baseColor) {
2344
- context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
2345
- context.fillRect(originPoint.x, originPoint.y, dimension.width, dimension.height);
2346
- }
2347
- function paintImage(context, dimension, image, opacity) {
2348
- if (!image) {
2349
- return;
2350
- }
2351
- const prevAlpha = context.globalAlpha;
2352
- context.globalAlpha = opacity;
2353
- context.drawImage(image, originPoint.x, originPoint.y, dimension.width, dimension.height);
2354
- context.globalAlpha = prevAlpha;
2355
- }
2356
- function clear(context, dimension) {
2357
- context.clearRect(originPoint.x, originPoint.y, dimension.width, dimension.height);
2358
- }
2359
- function drawParticle(data) {
2360
- const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = defaultZoom, drawPosition = {
2361
- x: pos.x,
2362
- y: pos.y,
2363
- };
2364
- context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
2365
- if (colorStyles.fill) {
2366
- context.fillStyle = colorStyles.fill;
2367
- }
2368
- const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
2369
- context.lineWidth = strokeWidth;
2370
- if (colorStyles.stroke) {
2371
- context.strokeStyle = colorStyles.stroke;
2372
- }
2373
- const drawData = {
2374
- context,
2375
- particle,
2376
- radius,
2377
- drawRadius: radius * drawScale,
2378
- opacity,
2379
- delta,
2380
- pixelRatio: container.retina.pixelRatio,
2381
- fill: fillEnabled,
2382
- stroke: strokeWidth > minStrokeWidth,
2383
- transformData,
2384
- position: { ...pos },
2385
- drawPosition,
2386
- drawScale,
2387
- };
2388
- for (const plugin of container.plugins) {
2389
- plugin.drawParticleTransform?.(drawData);
2390
- }
2391
- const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
2392
- drawBeforeEffect(effect, drawData);
2393
- drawShapeBeforeDraw(shape, drawData);
2394
- drawShape(shape, drawData);
2395
- drawShapeAfterDraw(shape, drawData);
2396
- drawAfterEffect(effect, drawData);
2397
- context.resetTransform();
2398
- }
2399
- function drawAfterEffect(drawer, data) {
2400
- if (!drawer?.drawAfter) {
2401
- return;
2402
- }
2403
- const { particle } = data;
2404
- if (!particle.effect) {
2405
- return;
2406
- }
2407
- drawer.drawAfter(data);
2408
- }
2409
- function drawBeforeEffect(drawer, data) {
2410
- if (!drawer?.drawBefore) {
2411
- return;
2412
- }
2413
- const { particle } = data;
2414
- if (!particle.effect) {
2415
- return;
2416
- }
2417
- drawer.drawBefore(data);
2418
- }
2419
- function drawShape(drawer, data) {
2420
- if (!drawer) {
2421
- return;
2422
- }
2423
- const { context, fill, particle, stroke } = data;
2424
- if (!particle.shape) {
2425
- return;
2426
- }
2427
- context.beginPath();
2428
- drawer.draw(data);
2429
- if (particle.shapeClose) {
2430
- context.closePath();
2431
- }
2432
- if (fill) {
2433
- context.fill();
2434
- }
2435
- if (stroke) {
2436
- context.stroke();
2437
- }
2438
- }
2439
- function drawShapeAfterDraw(drawer, data) {
2440
- if (!drawer?.afterDraw) {
2441
- return;
2442
- }
2443
- const { particle } = data;
2444
- if (!particle.shape) {
2445
- return;
2446
- }
2447
- drawer.afterDraw(data);
2448
- }
2449
- function drawShapeBeforeDraw(drawer, data) {
2450
- if (!drawer?.beforeDraw) {
2451
- return;
2452
1751
  }
2453
- const { particle } = data;
2454
- if (!particle.shape) {
2455
- return;
2456
- }
2457
- drawer.beforeDraw(data);
2458
- }
2459
- function drawParticlePlugin(context, plugin, particle, delta) {
2460
- if (!plugin.drawParticle) {
2461
- return;
1752
+ #importPreset(preset) {
1753
+ this.load(this.#pluginManager.getPreset(preset));
2462
1754
  }
2463
- plugin.drawParticle(context, particle, delta);
2464
1755
  }
2465
1756
 
2466
- const styleCache = new Map(), maxCacheSize = 1000, firstIndex = 0, rgbFixedPrecision = 2, hslFixedPrecision = 2;
1757
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
2467
1758
  function getCachedStyle(key, generator) {
2468
1759
  let cached = styleCache.get(key);
2469
1760
  if (!cached) {
2470
1761
  cached = generator();
2471
- if (styleCache.size >= maxCacheSize) {
2472
- const keysToDelete = [...styleCache.keys()].slice(firstIndex, maxCacheSize * half);
2473
- keysToDelete.forEach(k => styleCache.delete(k));
1762
+ if (styleCache.size > maxStyleCacheSize) {
1763
+ styleCache.clear();
2474
1764
  }
2475
1765
  styleCache.set(key, cached);
2476
1766
  }
@@ -2573,34 +1863,35 @@
2573
1863
  function stringToRgb(pluginManager, input) {
2574
1864
  return stringToRgba(pluginManager, input);
2575
1865
  }
1866
+ function hslChannel(temp1, temp2, temp3) {
1867
+ const temp3Min = 0, temp3Max = 1;
1868
+ if (temp3 < temp3Min) {
1869
+ temp3++;
1870
+ }
1871
+ if (temp3 > temp3Max) {
1872
+ temp3--;
1873
+ }
1874
+ if (temp3 * sextuple < temp3Max) {
1875
+ return temp1 + (temp2 - temp1) * sextuple * temp3;
1876
+ }
1877
+ if (temp3 * double < temp3Max) {
1878
+ return temp2;
1879
+ }
1880
+ if (temp3 * triple < temp3Max * double) {
1881
+ const temp3Offset = double / triple;
1882
+ return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
1883
+ }
1884
+ return temp1;
1885
+ }
2576
1886
  function hslToRgb(hsl) {
2577
1887
  const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
2578
1888
  if (s === sMin) {
2579
1889
  const grayscaleValue = Math.round(lNormalized * rgbMax);
2580
1890
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
2581
1891
  }
2582
- const channel = (temp1, temp2, temp3) => {
2583
- const temp3Min = 0, temp3Max = 1;
2584
- if (temp3 < temp3Min) {
2585
- temp3++;
2586
- }
2587
- if (temp3 > temp3Max) {
2588
- temp3--;
2589
- }
2590
- if (temp3 * sextuple < temp3Max) {
2591
- return temp1 + (temp2 - temp1) * sextuple * temp3;
2592
- }
2593
- if (temp3 * double < temp3Max) {
2594
- return temp2;
2595
- }
2596
- if (temp3 * triple < temp3Max * double) {
2597
- const temp3Offset = double / triple;
2598
- return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
2599
- }
2600
- return temp1;
2601
- }, temp1 = lNormalized < half
1892
+ const temp1 = lNormalized < half
2602
1893
  ? lNormalized * (sNormalizedOffset + sNormalized)
2603
- : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * channel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * channel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * channel(temp2, temp1, hNormalized - phaseThird));
1894
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
2604
1895
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
2605
1896
  }
2606
1897
  function hslaToRgba(hsla) {
@@ -2613,7 +1904,7 @@
2613
1904
  };
2614
1905
  }
2615
1906
  function getRandomRgbColor(min) {
2616
- const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity$2, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1907
+ const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity$1, 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.3");
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.3");
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.3");
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.3");
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.3");
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.3");
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.3");
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.3");
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.3");
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.3");
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.3");
3025
+ engine.checkVersion("4.2.0");
3659
3026
  await engine.pluginManager.register(async (e) => {
3660
3027
  await Promise.all([
3661
3028
  loadBlendPlugin(e),
@@ -3676,78 +3043,46 @@
3676
3043
  count;
3677
3044
  delay;
3678
3045
  duration;
3679
- wait;
3680
- constructor() {
3681
- this.wait = false;
3682
- }
3046
+ wait = false;
3683
3047
  load(data) {
3684
3048
  if (isNull(data)) {
3685
3049
  return;
3686
3050
  }
3687
- if (data.count !== undefined) {
3688
- this.count = data.count;
3689
- }
3690
- if (data.delay !== undefined) {
3691
- this.delay = setRangeValue(data.delay);
3692
- }
3693
- if (data.duration !== undefined) {
3694
- this.duration = setRangeValue(data.duration);
3695
- }
3696
- if (data.wait !== undefined) {
3697
- this.wait = data.wait;
3698
- }
3051
+ loadProperty(this, "count", data.count);
3052
+ loadRangeProperty(this, "delay", data.delay);
3053
+ loadRangeProperty(this, "duration", data.duration);
3054
+ loadProperty(this, "wait", data.wait);
3699
3055
  }
3700
3056
  }
3701
3057
 
3702
3058
  class EmitterRate {
3703
- delay;
3704
- quantity;
3705
- constructor() {
3706
- this.quantity = 1;
3707
- this.delay = 0.1;
3708
- }
3059
+ delay = 0.1;
3060
+ quantity = 1;
3709
3061
  load(data) {
3710
3062
  if (isNull(data)) {
3711
3063
  return;
3712
3064
  }
3713
- if (data.quantity !== undefined) {
3714
- this.quantity = setRangeValue(data.quantity);
3715
- }
3716
- if (data.delay !== undefined) {
3717
- this.delay = setRangeValue(data.delay);
3718
- }
3065
+ loadRangeProperty(this, "quantity", data.quantity);
3066
+ loadRangeProperty(this, "delay", data.delay);
3719
3067
  }
3720
3068
  }
3721
3069
 
3722
3070
  class EmitterShapeReplace {
3723
- color;
3724
- opacity;
3725
- constructor() {
3726
- this.color = false;
3727
- this.opacity = false;
3728
- }
3071
+ color = false;
3072
+ opacity = false;
3729
3073
  load(data) {
3730
3074
  if (isNull(data)) {
3731
3075
  return;
3732
3076
  }
3733
- if (data.color !== undefined) {
3734
- this.color = data.color;
3735
- }
3736
- if (data.opacity !== undefined) {
3737
- this.opacity = data.opacity;
3738
- }
3077
+ loadProperty(this, "color", data.color);
3078
+ loadProperty(this, "opacity", data.opacity);
3739
3079
  }
3740
3080
  }
3741
-
3742
- class EmitterShape {
3743
- options;
3744
- replace;
3745
- type;
3746
- constructor() {
3747
- this.options = {};
3748
- this.replace = new EmitterShapeReplace();
3749
- this.type = "square";
3750
- }
3081
+
3082
+ class EmitterShape {
3083
+ options = {};
3084
+ replace = new EmitterShapeReplace();
3085
+ type = "square";
3751
3086
  load(data) {
3752
3087
  if (isNull(data)) {
3753
3088
  return;
@@ -3756,34 +3091,21 @@
3756
3091
  this.options = deepExtend({}, data.options ?? {});
3757
3092
  }
3758
3093
  this.replace.load(data.replace);
3759
- if (data.type !== undefined) {
3760
- this.type = data.type;
3761
- }
3094
+ loadProperty(this, "type", data.type);
3762
3095
  }
3763
3096
  }
3764
3097
 
3765
3098
  class EmitterSize {
3766
- height;
3767
- mode;
3768
- width;
3769
- constructor() {
3770
- this.mode = PixelMode.percent;
3771
- this.height = 0;
3772
- this.width = 0;
3773
- }
3099
+ height = 0;
3100
+ mode = PixelMode.percent;
3101
+ width = 0;
3774
3102
  load(data) {
3775
3103
  if (isNull(data)) {
3776
3104
  return;
3777
3105
  }
3778
- if (data.mode !== undefined) {
3779
- this.mode = data.mode;
3780
- }
3781
- if (data.height !== undefined) {
3782
- this.height = data.height;
3783
- }
3784
- if (data.width !== undefined) {
3785
- this.width = data.width;
3786
- }
3106
+ loadProperty(this, "mode", data.mode);
3107
+ loadProperty(this, "height", data.height);
3108
+ loadProperty(this, "width", data.width);
3787
3109
  }
3788
3110
  }
3789
3111
 
@@ -3806,50 +3128,35 @@
3806
3128
  }
3807
3129
 
3808
3130
  class Emitter {
3809
- autoPlay;
3131
+ autoPlay = true;
3810
3132
  direction;
3811
3133
  domId;
3812
- fill;
3813
- life;
3134
+ fill = true;
3135
+ life = new EmitterLife();
3814
3136
  name;
3815
3137
  particles;
3816
3138
  position;
3817
- rate;
3818
- shape;
3139
+ rate = new EmitterRate();
3140
+ shape = new EmitterShape();
3819
3141
  size;
3820
- spawn;
3142
+ spawn = new EmitterSpawn();
3821
3143
  spawnFillColor;
3822
3144
  spawnStrokeColor;
3823
- startCount;
3824
- constructor() {
3825
- this.autoPlay = true;
3826
- this.fill = true;
3827
- this.life = new EmitterLife();
3828
- this.rate = new EmitterRate();
3829
- this.shape = new EmitterShape();
3830
- this.spawn = new EmitterSpawn();
3831
- this.startCount = 0;
3832
- }
3145
+ startCount = 0;
3833
3146
  load(data) {
3834
3147
  if (isNull(data)) {
3835
3148
  return;
3836
3149
  }
3837
- if (data.autoPlay !== undefined) {
3838
- this.autoPlay = data.autoPlay;
3839
- }
3150
+ loadProperty(this, "autoPlay", data.autoPlay);
3840
3151
  if (data.size !== undefined) {
3841
3152
  this.size ??= new EmitterSize();
3842
3153
  this.size.load(data.size);
3843
3154
  }
3844
- if (data.direction !== undefined) {
3845
- this.direction = data.direction;
3846
- }
3847
- this.domId = data.domId;
3848
- if (data.fill !== undefined) {
3849
- this.fill = data.fill;
3850
- }
3155
+ loadProperty(this, "direction", data.direction);
3156
+ loadProperty(this, "domId", data.domId);
3157
+ loadProperty(this, "fill", data.fill);
3851
3158
  this.life.load(data.life);
3852
- this.name = data.name;
3159
+ loadProperty(this, "name", data.name);
3853
3160
  this.particles = executeOnSingleOrMultiple(data.particles, particles => {
3854
3161
  return deepExtend({}, particles);
3855
3162
  });
@@ -3873,9 +3180,7 @@
3873
3180
  this.spawnStrokeColor ??= new AnimatableColor();
3874
3181
  this.spawnStrokeColor.load(data.spawnStrokeColor);
3875
3182
  }
3876
- if (data.startCount !== undefined) {
3877
- this.startCount = data.startCount;
3878
- }
3183
+ loadProperty(this, "startCount", data.startCount);
3879
3184
  }
3880
3185
  }
3881
3186
 
@@ -3957,7 +3262,7 @@
3957
3262
  })(EmitterClickMode || (EmitterClickMode = {}));
3958
3263
 
3959
3264
  async function loadEmittersPluginSimple(engine) {
3960
- engine.checkVersion("4.1.3");
3265
+ engine.checkVersion("4.2.0");
3961
3266
  await engine.pluginManager.register(async (e) => {
3962
3267
  const instancesManager = await getEmittersInstancesManager(e);
3963
3268
  await addEmittersShapesManager(e);
@@ -4045,7 +3350,7 @@
4045
3350
  }
4046
3351
 
4047
3352
  async function loadEmittersShapeSquare(engine) {
4048
- engine.checkVersion("4.1.3");
3353
+ engine.checkVersion("4.2.0");
4049
3354
  await engine.pluginManager.register((e) => {
4050
3355
  ensureEmittersPluginLoaded(e);
4051
3356
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -4053,55 +3358,36 @@
4053
3358
  }
4054
3359
 
4055
3360
  class LifeDelay extends ValueWithRandom {
4056
- sync;
4057
- constructor() {
4058
- super();
4059
- this.sync = false;
4060
- }
3361
+ sync = false;
4061
3362
  load(data) {
4062
3363
  if (isNull(data)) {
4063
3364
  return;
4064
3365
  }
4065
3366
  super.load(data);
4066
- if (data.sync !== undefined) {
4067
- this.sync = data.sync;
4068
- }
3367
+ loadProperty(this, "sync", data.sync);
4069
3368
  }
4070
3369
  }
4071
3370
 
4072
3371
  class LifeDuration extends ValueWithRandom {
4073
- sync;
4074
- constructor() {
4075
- super();
4076
- this.sync = false;
4077
- }
3372
+ sync = false;
4078
3373
  load(data) {
4079
3374
  if (isNull(data)) {
4080
3375
  return;
4081
3376
  }
4082
3377
  super.load(data);
4083
- if (data.sync !== undefined) {
4084
- this.sync = data.sync;
4085
- }
3378
+ loadProperty(this, "sync", data.sync);
4086
3379
  }
4087
3380
  }
4088
3381
 
4089
3382
  class Life {
4090
- count;
4091
- delay;
4092
- duration;
4093
- constructor() {
4094
- this.count = 0;
4095
- this.delay = new LifeDelay();
4096
- this.duration = new LifeDuration();
4097
- }
3383
+ count = 0;
3384
+ delay = new LifeDelay();
3385
+ duration = new LifeDuration();
4098
3386
  load(data) {
4099
3387
  if (isNull(data)) {
4100
3388
  return;
4101
3389
  }
4102
- if (data.count !== undefined) {
4103
- this.count = data.count;
4104
- }
3390
+ loadProperty(this, "count", data.count);
4105
3391
  this.delay.load(data.delay);
4106
3392
  this.duration.load(data.duration);
4107
3393
  }
@@ -4160,7 +3446,7 @@
4160
3446
  }
4161
3447
  }
4162
3448
 
4163
- const noTime = 0, identity$1 = 1, infiniteValue = -1;
3449
+ const noTime = 0, identity = 1, infiniteValue = -1;
4164
3450
  class LifeUpdater {
4165
3451
  #container;
4166
3452
  constructor(container) {
@@ -4171,7 +3457,7 @@
4171
3457
  if (!lifeOptions) {
4172
3458
  return;
4173
3459
  }
4174
- const delayFactor = lifeOptions.delay.sync ? identity$1 : getRandom(), durationFactor = lifeOptions.duration.sync ? identity$1 : getRandom();
3460
+ const delayFactor = lifeOptions.delay.sync ? identity : getRandom(), durationFactor = lifeOptions.duration.sync ? identity : getRandom();
4175
3461
  particle.life = {
4176
3462
  delay: container.retina.reduceFactor
4177
3463
  ? ((getRangeValue(lifeOptions.delay.value) * delayFactor) / container.retina.reduceFactor) *
@@ -4197,10 +3483,7 @@
4197
3483
  return !particle.destroyed;
4198
3484
  }
4199
3485
  loadOptions(options, ...sources) {
4200
- options.life ??= new Life();
4201
- for (const source of sources) {
4202
- options.life.load(source?.life);
4203
- }
3486
+ loadOptionProperty(options, "life", Life, ...sources);
4204
3487
  }
4205
3488
  update(particle, delta) {
4206
3489
  if (!this.isEnabled(particle) || !particle.life) {
@@ -4211,7 +3494,7 @@
4211
3494
  }
4212
3495
 
4213
3496
  async function loadLifeUpdater(engine) {
4214
- engine.checkVersion("4.1.3");
3497
+ engine.checkVersion("4.2.0");
4215
3498
  await engine.pluginManager.register(e => {
4216
3499
  e.pluginManager.addParticleUpdater("life", container => {
4217
3500
  return Promise.resolve(new LifeUpdater(container));
@@ -4229,34 +3512,23 @@
4229
3512
  if (data.color !== undefined) {
4230
3513
  this.color = OptionsColor.create(this.color, data.color);
4231
3514
  }
4232
- if (data.image !== undefined) {
4233
- this.image = data.image;
4234
- }
3515
+ loadProperty(this, "image", data.image);
4235
3516
  }
4236
3517
  }
4237
3518
 
4238
3519
  class Trail {
4239
- enable;
4240
- fill;
4241
- length;
4242
- constructor() {
4243
- this.enable = false;
4244
- this.length = 10;
4245
- this.fill = new TrailFill();
4246
- }
3520
+ enable = false;
3521
+ fill = new TrailFill();
3522
+ length = 10;
4247
3523
  load(data) {
4248
3524
  if (isNull(data)) {
4249
3525
  return;
4250
3526
  }
4251
- if (data.enable !== undefined) {
4252
- this.enable = data.enable;
4253
- }
3527
+ loadProperty(this, "enable", data.enable);
4254
3528
  if (data.fill !== undefined) {
4255
3529
  this.fill.load(data.fill);
4256
3530
  }
4257
- if (data.length !== undefined) {
4258
- this.length = data.length;
4259
- }
3531
+ loadProperty(this, "length", data.length);
4260
3532
  }
4261
3533
  }
4262
3534
 
@@ -4286,7 +3558,7 @@
4286
3558
  }
4287
3559
 
4288
3560
  async function loadTrailPlugin(engine) {
4289
- engine.checkVersion("4.1.3");
3561
+ engine.checkVersion("4.2.0");
4290
3562
  await engine.pluginManager.register(e => {
4291
3563
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
4292
3564
  });
@@ -4429,7 +3701,7 @@
4429
3701
  return;
4430
3702
  }
4431
3703
  this.draw(ctx => {
4432
- clear(ctx, this.#canvasManager.size);
3704
+ ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4433
3705
  });
4434
3706
  }
4435
3707
  clear() {
@@ -4491,7 +3763,7 @@
4491
3763
  plugin.drawParticleSetup?.(context, particle, delta);
4492
3764
  }
4493
3765
  this.#applyPreDrawUpdaters(context, particle, radius, opacity, colorStyles, transform);
4494
- drawParticle({
3766
+ this.#drawParticle({
4495
3767
  container,
4496
3768
  context,
4497
3769
  particle,
@@ -4510,7 +3782,7 @@
4510
3782
  drawParticlePlugins(particle, delta) {
4511
3783
  this.draw(ctx => {
4512
3784
  for (const plugin of this.#drawParticlePlugins) {
4513
- drawParticlePlugin(ctx, plugin, particle, delta);
3785
+ this.#drawParticlePlugin(ctx, plugin, particle, delta);
4514
3786
  }
4515
3787
  });
4516
3788
  }
@@ -4610,12 +3882,19 @@
4610
3882
  }
4611
3883
  paintBase(baseColor) {
4612
3884
  this.draw(ctx => {
4613
- paintBase(ctx, this.#canvasManager.size, baseColor);
3885
+ ctx.fillStyle = baseColor ?? "rgba(0,0,0,0)";
3886
+ ctx.fillRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4614
3887
  });
4615
3888
  }
4616
3889
  paintImage(image, opacity) {
4617
3890
  this.draw(ctx => {
4618
- paintImage(ctx, this.#canvasManager.size, image, opacity);
3891
+ if (!image) {
3892
+ return;
3893
+ }
3894
+ const prevAlpha = ctx.globalAlpha;
3895
+ ctx.globalAlpha = opacity;
3896
+ ctx.drawImage(image, originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
3897
+ ctx.globalAlpha = prevAlpha;
4619
3898
  });
4620
3899
  }
4621
3900
  setContext(context) {
@@ -4629,15 +3908,15 @@
4629
3908
  }
4630
3909
  stop() {
4631
3910
  this.draw(ctx => {
4632
- clear(ctx, this.#canvasManager.size);
3911
+ ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
4633
3912
  });
4634
3913
  }
4635
- #applyPostDrawUpdaters = particle => {
3914
+ #applyPostDrawUpdaters(particle) {
4636
3915
  for (const updater of this.#postDrawUpdaters) {
4637
3916
  updater.afterDraw?.(particle);
4638
3917
  }
4639
- };
4640
- #applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
3918
+ }
3919
+ #applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform) {
4641
3920
  for (const updater of this.#preDrawUpdaters) {
4642
3921
  if (updater.getColorStyles) {
4643
3922
  const { fill, stroke } = updater.getColorStyles(particle, ctx, radius, zOpacity);
@@ -4656,8 +3935,114 @@
4656
3935
  }
4657
3936
  updater.beforeDraw?.(particle);
4658
3937
  }
4659
- };
4660
- #getPluginParticleColors = particle => {
3938
+ }
3939
+ #drawAfterEffect(drawer, data) {
3940
+ if (!drawer?.drawAfter) {
3941
+ return;
3942
+ }
3943
+ const { particle } = data;
3944
+ if (!particle.effect) {
3945
+ return;
3946
+ }
3947
+ drawer.drawAfter(data);
3948
+ }
3949
+ #drawBeforeEffect(drawer, data) {
3950
+ if (!drawer?.drawBefore) {
3951
+ return;
3952
+ }
3953
+ const { particle } = data;
3954
+ if (!particle.effect) {
3955
+ return;
3956
+ }
3957
+ drawer.drawBefore(data);
3958
+ }
3959
+ #drawParticle(data) {
3960
+ const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = defaultZoom, drawPosition = {
3961
+ x: pos.x,
3962
+ y: pos.y,
3963
+ };
3964
+ context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
3965
+ if (colorStyles.fill) {
3966
+ context.fillStyle = colorStyles.fill;
3967
+ }
3968
+ const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
3969
+ context.lineWidth = strokeWidth;
3970
+ if (colorStyles.stroke) {
3971
+ context.strokeStyle = colorStyles.stroke;
3972
+ }
3973
+ const drawData = {
3974
+ context,
3975
+ particle,
3976
+ radius,
3977
+ drawRadius: radius * drawScale,
3978
+ opacity,
3979
+ delta,
3980
+ pixelRatio: container.retina.pixelRatio,
3981
+ fill: fillEnabled,
3982
+ stroke: strokeWidth > minStrokeWidth,
3983
+ transformData,
3984
+ position: { ...pos },
3985
+ drawPosition,
3986
+ drawScale,
3987
+ };
3988
+ for (const plugin of container.plugins) {
3989
+ plugin.drawParticleTransform?.(drawData);
3990
+ }
3991
+ const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
3992
+ this.#drawBeforeEffect(effect, drawData);
3993
+ this.#drawShapeBeforeDraw(shape, drawData);
3994
+ this.#drawShape(shape, drawData);
3995
+ this.#drawShapeAfterDraw(shape, drawData);
3996
+ this.#drawAfterEffect(effect, drawData);
3997
+ context.resetTransform();
3998
+ }
3999
+ #drawParticlePlugin(context, plugin, particle, delta) {
4000
+ if (!plugin.drawParticle) {
4001
+ return;
4002
+ }
4003
+ plugin.drawParticle(context, particle, delta);
4004
+ }
4005
+ #drawShape(drawer, data) {
4006
+ if (!drawer) {
4007
+ return;
4008
+ }
4009
+ const { context, fill, particle, stroke } = data;
4010
+ if (!particle.shape) {
4011
+ return;
4012
+ }
4013
+ context.beginPath();
4014
+ drawer.draw(data);
4015
+ if (particle.shapeClose) {
4016
+ context.closePath();
4017
+ }
4018
+ if (fill) {
4019
+ context.fill();
4020
+ }
4021
+ if (stroke) {
4022
+ context.stroke();
4023
+ }
4024
+ }
4025
+ #drawShapeAfterDraw(drawer, data) {
4026
+ if (!drawer?.afterDraw) {
4027
+ return;
4028
+ }
4029
+ const { particle } = data;
4030
+ if (!particle.shape) {
4031
+ return;
4032
+ }
4033
+ drawer.afterDraw(data);
4034
+ }
4035
+ #drawShapeBeforeDraw(drawer, data) {
4036
+ if (!drawer?.beforeDraw) {
4037
+ return;
4038
+ }
4039
+ const { particle } = data;
4040
+ if (!particle.shape) {
4041
+ return;
4042
+ }
4043
+ drawer.beforeDraw(data);
4044
+ }
4045
+ #getPluginParticleColors(particle) {
4661
4046
  let fColor, sColor;
4662
4047
  for (const plugin of this.#colorPlugins) {
4663
4048
  if (!fColor && plugin.particleFillColor) {
@@ -4673,7 +4058,7 @@
4673
4058
  this.#reusablePluginColors[fColorIndex] = fColor;
4674
4059
  this.#reusablePluginColors[sColorIndex] = sColor;
4675
4060
  return this.#reusablePluginColors;
4676
- };
4061
+ }
4677
4062
  }
4678
4063
 
4679
4064
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4805,6 +4190,7 @@
4805
4190
  obs.observe(element, { attributes: true });
4806
4191
  });
4807
4192
  this.initPlugins();
4193
+ this.#initContext();
4808
4194
  this.render.init();
4809
4195
  }
4810
4196
  initBackground() {
@@ -4814,7 +4200,7 @@
4814
4200
  }
4815
4201
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4816
4202
  if (color) {
4817
- elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity);
4203
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4818
4204
  }
4819
4205
  else {
4820
4206
  elementStyle.backgroundColor = "";
@@ -4836,7 +4222,7 @@
4836
4222
  if (this.#generated && this.domElement) {
4837
4223
  this.domElement.remove();
4838
4224
  }
4839
- const container = this.#container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4225
+ const domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4840
4226
  this.domElement = domCanvas;
4841
4227
  this.#generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4842
4228
  this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
@@ -4857,26 +4243,6 @@
4857
4243
  const pxRatio = this.#container.retina.pixelRatio, retinaSize = this.size;
4858
4244
  renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4859
4245
  renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4860
- const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4861
- this.render.setContextSettings({
4862
- alpha: true,
4863
- colorSpace: canSupportHdrQuery?.matches && container.hdr ? "display-p3" : "srgb",
4864
- desynchronized: true,
4865
- willReadFrequently: false,
4866
- });
4867
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4868
- this.#safeMutationObserver(obs => {
4869
- obs.disconnect();
4870
- });
4871
- container.retina.init();
4872
- this.initBackground();
4873
- this.#safeMutationObserver(obs => {
4874
- const element = this.domElement;
4875
- if (!element || !(element instanceof Node)) {
4876
- return;
4877
- }
4878
- obs.observe(element, { attributes: true });
4879
- });
4880
4246
  }
4881
4247
  resize() {
4882
4248
  const element = this.domElement;
@@ -4944,12 +4310,30 @@
4944
4310
  await container.refresh();
4945
4311
  }
4946
4312
  }
4947
- #applyResizePlugins = () => {
4313
+ #applyResizePlugins() {
4948
4314
  for (const plugin of this.#resizePlugins) {
4949
4315
  plugin.resize?.();
4950
4316
  }
4951
- };
4952
- #initStyle = () => {
4317
+ }
4318
+ #initContext() {
4319
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4320
+ safeMatchMedia("(color-gamut: p3)")?.matches &&
4321
+ safeMatchMedia("(dynamic-range: high)")?.matches;
4322
+ this.render.setContextSettings({
4323
+ alpha: true,
4324
+ desynchronized: true,
4325
+ willReadFrequently: false,
4326
+ ...(canSupportHdr
4327
+ ? { colorSpace: "display-p3", colorType: "float16" }
4328
+ : { colorSpace: "srgb" }),
4329
+ });
4330
+ const renderCanvas = this.renderCanvas;
4331
+ if (!renderCanvas) {
4332
+ return;
4333
+ }
4334
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4335
+ }
4336
+ #initStyle() {
4953
4337
  const element = this.domElement, options = this.#container.actualOptions;
4954
4338
  if (!element) {
4955
4339
  return;
@@ -4970,8 +4354,8 @@
4970
4354
  }
4971
4355
  element.style.setProperty(key, value, "important");
4972
4356
  }
4973
- };
4974
- #repairStyle = () => {
4357
+ }
4358
+ #repairStyle() {
4975
4359
  const element = this.domElement;
4976
4360
  if (!element) {
4977
4361
  return;
@@ -4990,27 +4374,27 @@
4990
4374
  }
4991
4375
  observer.observe(element, { attributes: true });
4992
4376
  });
4993
- };
4994
- #resetOriginalStyle = () => {
4377
+ }
4378
+ #resetOriginalStyle() {
4995
4379
  const element = this.domElement, originalStyle = this.#originalStyle;
4996
4380
  if (!element || !originalStyle) {
4997
4381
  return;
4998
4382
  }
4999
4383
  setStyle(element, originalStyle, true);
5000
- };
5001
- #safeMutationObserver = callback => {
4384
+ }
4385
+ #safeMutationObserver(callback) {
5002
4386
  if (!this.#mutationObserver) {
5003
4387
  return;
5004
4388
  }
5005
4389
  callback(this.#mutationObserver);
5006
- };
5007
- #setFullScreenStyle = () => {
4390
+ }
4391
+ #setFullScreenStyle() {
5008
4392
  const element = this.domElement;
5009
4393
  if (!element) {
5010
4394
  return;
5011
4395
  }
5012
4396
  setStyle(element, getFullScreenStyle(this.#container.actualOptions.fullScreen.zIndex), true);
5013
- };
4397
+ }
5014
4398
  }
5015
4399
 
5016
4400
  class EventListeners {
@@ -5035,7 +4419,7 @@
5035
4419
  removeListeners() {
5036
4420
  this.#manageListeners(false);
5037
4421
  }
5038
- #handleVisibilityChange = () => {
4422
+ #handleVisibilityChange() {
5039
4423
  const container = this.#container, options = container.actualOptions;
5040
4424
  if (!options.pauseOnBlur) {
5041
4425
  return;
@@ -5053,8 +4437,8 @@
5053
4437
  container.draw(true);
5054
4438
  }
5055
4439
  }
5056
- };
5057
- #handleWindowResize = () => {
4440
+ }
4441
+ #handleWindowResize() {
5058
4442
  if (this.#resizeTimeout) {
5059
4443
  clearTimeout(this.#resizeTimeout);
5060
4444
  this.#resizeTimeout = undefined;
@@ -5064,13 +4448,13 @@
5064
4448
  await canvas.windowResize();
5065
4449
  };
5066
4450
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
5067
- };
5068
- #manageListeners = add => {
4451
+ }
4452
+ #manageListeners(add) {
5069
4453
  const handlers = this.#handlers;
5070
4454
  this.#manageResize(add);
5071
4455
  manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
5072
- };
5073
- #manageResize = add => {
4456
+ }
4457
+ #manageResize(add) {
5074
4458
  const handlers = this.#handlers, container = this.#container, options = container.actualOptions;
5075
4459
  if (!options.resize.enable) {
5076
4460
  return;
@@ -5097,7 +4481,7 @@
5097
4481
  });
5098
4482
  this.#resizeObserver.observe(canvasEl);
5099
4483
  }
5100
- };
4484
+ }
5101
4485
  }
5102
4486
 
5103
4487
  function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
@@ -5124,6 +4508,131 @@
5124
4508
  data.setCb(data.radius);
5125
4509
  }
5126
4510
  }
4511
+ function normalizeAngle(angle, modulus) {
4512
+ const normalized = angle % modulus;
4513
+ return normalized < defaultAngle ? normalized + modulus : normalized;
4514
+ }
4515
+ function initParticleState(particle, id, group) {
4516
+ particle.id = id;
4517
+ particle.group = group;
4518
+ particle.justWarped = false;
4519
+ particle.effectClose = true;
4520
+ particle.shapeClose = true;
4521
+ particle.pathRotation = false;
4522
+ particle.lastPathTime = 0;
4523
+ particle.destroyed = false;
4524
+ particle.unbreakable = false;
4525
+ particle.isRotating = false;
4526
+ particle.rotation = 0;
4527
+ particle.misplaced = false;
4528
+ particle.retina = {
4529
+ maxDistance: {},
4530
+ maxSpeed: 0,
4531
+ moveDrift: 0,
4532
+ moveSpeed: 0,
4533
+ sizeAnimationSpeed: 0,
4534
+ };
4535
+ particle.size = {
4536
+ value: 1,
4537
+ max: 1,
4538
+ min: 1,
4539
+ enable: false,
4540
+ };
4541
+ particle.outType = ParticleOutType.normal;
4542
+ particle.ignoresResizeRatio = true;
4543
+ }
4544
+ function resolveParticleOptions(particle, container, pluginManager, overrideOptions) {
4545
+ const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates;
4546
+ particle.effect = itemFromSingleOrMultiple(particlesOptions.effect.type, particle.id, reduceDuplicates);
4547
+ particle.shape = itemFromSingleOrMultiple(particlesOptions.shape.type, particle.id, reduceDuplicates);
4548
+ const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
4549
+ if (overrideOptions) {
4550
+ if (overrideOptions.effect) {
4551
+ const overrideEffectType = overrideOptions.effect.type;
4552
+ if (overrideEffectType && overrideEffectType !== particle.effect) {
4553
+ const effect = itemFromSingleOrMultiple(overrideEffectType, particle.id, reduceDuplicates);
4554
+ if (effect) {
4555
+ particle.effect = effect;
4556
+ }
4557
+ }
4558
+ effectOptions.load(overrideOptions.effect);
4559
+ }
4560
+ if (overrideOptions.shape) {
4561
+ const overrideShapeType = overrideOptions.shape.type;
4562
+ if (overrideShapeType && overrideShapeType !== particle.shape) {
4563
+ const shape = itemFromSingleOrMultiple(overrideShapeType, particle.id, reduceDuplicates);
4564
+ if (shape) {
4565
+ particle.shape = shape;
4566
+ }
4567
+ }
4568
+ shapeOptions.load(overrideOptions.shape);
4569
+ }
4570
+ }
4571
+ if (particle.effect === randomColorValue) {
4572
+ const availableEffects = [...container.effectDrawers.keys()];
4573
+ particle.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
4574
+ }
4575
+ if (particle.shape === randomColorValue) {
4576
+ const availableShapes = [...container.shapeDrawers.keys()];
4577
+ particle.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
4578
+ }
4579
+ particle.effectData = particle.effect
4580
+ ? loadEffectData(particle.effect, effectOptions, particle.id, reduceDuplicates)
4581
+ : undefined;
4582
+ particle.shapeData = particle.shape
4583
+ ? loadShapeData(particle.shape, shapeOptions, particle.id, reduceDuplicates)
4584
+ : undefined;
4585
+ particlesOptions.load(overrideOptions);
4586
+ const effectData = particle.effectData, shapeData = particle.shapeData;
4587
+ if (effectData) {
4588
+ particlesOptions.load(effectData.particles);
4589
+ }
4590
+ if (shapeData) {
4591
+ particlesOptions.load(shapeData.particles);
4592
+ }
4593
+ particle.effectClose = effectData?.close ?? particlesOptions.effect.close;
4594
+ particle.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
4595
+ return particlesOptions;
4596
+ }
4597
+ function initParticleDrawers(particle, container) {
4598
+ let effectDrawer, shapeDrawer;
4599
+ if (particle.effect) {
4600
+ effectDrawer = container.effectDrawers.get(particle.effect);
4601
+ }
4602
+ if (effectDrawer?.loadEffect) {
4603
+ effectDrawer.loadEffect(particle);
4604
+ }
4605
+ if (particle.shape) {
4606
+ shapeDrawer = container.shapeDrawers.get(particle.shape);
4607
+ }
4608
+ if (shapeDrawer?.loadShape) {
4609
+ shapeDrawer.loadShape(particle);
4610
+ }
4611
+ const sideCountFunc = shapeDrawer?.getSidesCount;
4612
+ if (sideCountFunc) {
4613
+ particle.sides = sideCountFunc(particle);
4614
+ }
4615
+ }
4616
+ function runUpdaterPreInit(updaters, particle) {
4617
+ for (const updater of updaters) {
4618
+ updater.preInit?.(particle);
4619
+ }
4620
+ }
4621
+ function runUpdaterInit(updaters, particle) {
4622
+ for (const updater of updaters) {
4623
+ updater.init(particle);
4624
+ }
4625
+ }
4626
+ function runDrawerInit(container, particle) {
4627
+ const shapeDrawer = particle.shape ? container.shapeDrawers.get(particle.shape) : undefined, effectDrawer = particle.effect ? container.effectDrawers.get(particle.effect) : undefined;
4628
+ effectDrawer?.particleInit?.(container, particle);
4629
+ shapeDrawer?.particleInit?.(container, particle);
4630
+ }
4631
+ function runParticleCreatedPlugins(container, particle) {
4632
+ for (const plugin of container.particleCreatedPlugins) {
4633
+ plugin.particleCreated?.(particle);
4634
+ }
4635
+ }
5127
4636
  class Particle {
5128
4637
  backColor;
5129
4638
  bubble;
@@ -5249,94 +4758,20 @@
5249
4758
  const rotateData = this.getRotateData(), rotating = this.isRotating;
5250
4759
  this.#cachedTransform.a = rotateData.cos * (externalTransform.a ?? defaultTransform.a);
5251
4760
  this.#cachedTransform.b = rotating
5252
- ? rotateData.sin * (externalTransform.b ?? identity$2)
4761
+ ? rotateData.sin * (externalTransform.b ?? identity$1)
5253
4762
  : (externalTransform.b ?? defaultTransform.b);
5254
4763
  this.#cachedTransform.c = rotating
5255
- ? -rotateData.sin * (externalTransform.c ?? identity$2)
4764
+ ? -rotateData.sin * (externalTransform.c ?? identity$1)
5256
4765
  : (externalTransform.c ?? defaultTransform.c);
5257
4766
  this.#cachedTransform.d = rotateData.cos * (externalTransform.d ?? defaultTransform.d);
5258
4767
  return this.#cachedTransform;
5259
4768
  }
5260
4769
  init(id, position, overrideOptions, group) {
5261
4770
  const container = this.#container;
5262
- this.id = id;
5263
- this.group = group;
5264
- this.justWarped = false;
5265
- this.effectClose = true;
5266
- this.shapeClose = true;
5267
- this.pathRotation = false;
5268
- this.lastPathTime = 0;
5269
- this.destroyed = false;
5270
- this.unbreakable = false;
5271
- this.isRotating = false;
5272
- this.rotation = 0;
5273
- this.misplaced = false;
5274
- this.retina = {
5275
- maxDistance: {},
5276
- maxSpeed: 0,
5277
- moveDrift: 0,
5278
- moveSpeed: 0,
5279
- sizeAnimationSpeed: 0,
5280
- };
5281
- this.size = {
5282
- value: 1,
5283
- max: 1,
5284
- min: 1,
5285
- enable: false,
5286
- };
5287
- this.outType = ParticleOutType.normal;
5288
- this.ignoresResizeRatio = true;
5289
- const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(this.#pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates, effectType = particlesOptions.effect.type, shapeType = particlesOptions.shape.type;
5290
- this.effect = itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
5291
- this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
5292
- const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
5293
- if (overrideOptions) {
5294
- if (overrideOptions.effect) {
5295
- const overrideEffectType = overrideOptions.effect.type;
5296
- if (overrideEffectType && overrideEffectType !== this.effect) {
5297
- const effect = itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
5298
- if (effect) {
5299
- this.effect = effect;
5300
- }
5301
- }
5302
- effectOptions.load(overrideOptions.effect);
5303
- }
5304
- if (overrideOptions.shape) {
5305
- const overrideShapeType = overrideOptions.shape.type;
5306
- if (overrideShapeType && overrideShapeType !== this.shape) {
5307
- const shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
5308
- if (shape) {
5309
- this.shape = shape;
5310
- }
5311
- }
5312
- shapeOptions.load(overrideOptions.shape);
5313
- }
5314
- }
5315
- if (this.effect === randomColorValue) {
5316
- const availableEffects = [...this.#container.effectDrawers.keys()];
5317
- this.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
5318
- }
5319
- if (this.shape === randomColorValue) {
5320
- const availableShapes = [...this.#container.shapeDrawers.keys()];
5321
- this.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
5322
- }
5323
- this.effectData = this.effect ? loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates) : undefined;
5324
- this.shapeData = this.shape ? loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates) : undefined;
5325
- particlesOptions.load(overrideOptions);
5326
- const effectData = this.effectData, shapeData = this.shapeData;
5327
- if (effectData) {
5328
- particlesOptions.load(effectData.particles);
5329
- }
5330
- if (shapeData) {
5331
- particlesOptions.load(shapeData.particles);
5332
- }
5333
- this.effectClose = effectData?.close ?? particlesOptions.effect.close;
5334
- this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
5335
- this.options = particlesOptions;
4771
+ initParticleState(this, id, group);
4772
+ this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
5336
4773
  container.retina.initParticle(this);
5337
- for (const updater of container.particleUpdaters) {
5338
- updater.preInit?.(this);
5339
- }
4774
+ runUpdaterPreInit(container.particleUpdaters, this);
5340
4775
  this.bubble = {
5341
4776
  inRange: false,
5342
4777
  };
@@ -5349,32 +4784,11 @@
5349
4784
  this.velocity = this.initialVelocity.copy();
5350
4785
  this.zIndexFactor = this.position.z / container.zLayers;
5351
4786
  this.sides = 24;
5352
- let effectDrawer, shapeDrawer;
5353
- if (this.effect) {
5354
- effectDrawer = container.effectDrawers.get(this.effect);
5355
- }
5356
- if (effectDrawer?.loadEffect) {
5357
- effectDrawer.loadEffect(this);
5358
- }
5359
- if (this.shape) {
5360
- shapeDrawer = container.shapeDrawers.get(this.shape);
5361
- }
5362
- if (shapeDrawer?.loadShape) {
5363
- shapeDrawer.loadShape(this);
5364
- }
5365
- const sideCountFunc = shapeDrawer?.getSidesCount;
5366
- if (sideCountFunc) {
5367
- this.sides = sideCountFunc(this);
5368
- }
4787
+ initParticleDrawers(this, container);
5369
4788
  this.spawning = false;
5370
- for (const updater of container.particleUpdaters) {
5371
- updater.init(this);
5372
- }
5373
- effectDrawer?.particleInit?.(container, this);
5374
- shapeDrawer?.particleInit?.(container, this);
5375
- for (const plugin of container.particleCreatedPlugins) {
5376
- plugin.particleCreated?.(this);
5377
- }
4789
+ runUpdaterInit(container.particleUpdaters, this);
4790
+ runDrawerInit(container, this);
4791
+ runParticleCreatedPlugins(container, this);
5378
4792
  }
5379
4793
  isInsideCanvas(direction) {
5380
4794
  return this.#getInsideCanvasResult({ direction }).inside;
@@ -5388,15 +4802,15 @@
5388
4802
  }
5389
4803
  const angle = this.roll.angle;
5390
4804
  if (this.roll.horizontal && this.roll.vertical) {
5391
- const normalizedAngle = angle % doublePI, adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + doublePI : normalizedAngle;
4805
+ const adjustedAngle = normalizeAngle(angle, doublePI);
5392
4806
  return adjustedAngle >= Math.PI * half && adjustedAngle < Math.PI * triple * half;
5393
4807
  }
5394
4808
  if (this.roll.horizontal) {
5395
- const normalizedAngle = (angle + Math.PI * half) % (Math.PI * double), adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + Math.PI * double : normalizedAngle;
4809
+ const adjustedAngle = normalizeAngle(angle + Math.PI * half, doublePI);
5396
4810
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
5397
4811
  }
5398
4812
  if (this.roll.vertical) {
5399
- const normalizedAngle = angle % (Math.PI * double), adjustedAngle = normalizedAngle < defaultAngle ? normalizedAngle + Math.PI * double : normalizedAngle;
4813
+ const adjustedAngle = normalizeAngle(angle, doublePI);
5400
4814
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
5401
4815
  }
5402
4816
  return false;
@@ -5409,10 +4823,10 @@
5409
4823
  updater.reset?.(this);
5410
4824
  }
5411
4825
  }
5412
- #calcPosition = (position, zIndex) => {
4826
+ #calcPosition(position, zIndex) {
5413
4827
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
5414
- const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size, abortController = new AbortController(), { signal } = abortController;
5415
- while (!signal.aborted) {
4828
+ const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
4829
+ for (;;) {
5416
4830
  for (const plugin of plugins) {
5417
4831
  const pluginPos = plugin.particlePosition?.(posVec, this);
5418
4832
  if (pluginPos) {
@@ -5440,9 +4854,8 @@
5440
4854
  tryCount += tryCountIncrement;
5441
4855
  posVec = undefined;
5442
4856
  }
5443
- return posVec;
5444
- };
5445
- #calculateVelocity = () => {
4857
+ }
4858
+ #calculateVelocity() {
5446
4859
  const moveOptions = this.options.move, baseVelocity = getParticleBaseVelocity(this.direction), res = baseVelocity.copy();
5447
4860
  if (moveOptions.direction === MoveDirection.inside || moveOptions.direction === MoveDirection.outside) {
5448
4861
  return res;
@@ -5458,8 +4871,8 @@
5458
4871
  res.length *= getRandom();
5459
4872
  }
5460
4873
  return res;
5461
- };
5462
- #fixHorizontal = (pos, radius, outMode) => {
4874
+ }
4875
+ #fixHorizontal(pos, radius, outMode) {
5463
4876
  fixOutMode({
5464
4877
  outMode,
5465
4878
  checkModes: [OutMode.bounce],
@@ -5468,8 +4881,8 @@
5468
4881
  setCb: (value) => (pos.x += value),
5469
4882
  radius,
5470
4883
  });
5471
- };
5472
- #fixVertical = (pos, radius, outMode) => {
4884
+ }
4885
+ #fixVertical(pos, radius, outMode) {
5473
4886
  fixOutMode({
5474
4887
  outMode,
5475
4888
  checkModes: [OutMode.bounce],
@@ -5478,8 +4891,8 @@
5478
4891
  setCb: (value) => (pos.y += value),
5479
4892
  radius,
5480
4893
  });
5481
- };
5482
- #getDefaultInsideCanvasResult = (direction, outMode) => {
4894
+ }
4895
+ #getDefaultInsideCanvasResult(direction, outMode) {
5483
4896
  const radius = this.getRadius(), canvasSize = this.#container.canvas.size, position = this.position, isBounce = outMode === OutMode.bounce;
5484
4897
  if (direction === OutModeDirection.bottom) {
5485
4898
  return {
@@ -5512,8 +4925,8 @@
5512
4925
  position.x <= canvasSize.width + radius,
5513
4926
  reason: "default",
5514
4927
  };
5515
- };
5516
- #getInsideCanvasCallbackData = (direction, outMode) => {
4928
+ }
4929
+ #getInsideCanvasCallbackData(direction, outMode) {
5517
4930
  return {
5518
4931
  canvasSize: this.#container.canvas.size,
5519
4932
  direction,
@@ -5521,8 +4934,8 @@
5521
4934
  particle: this,
5522
4935
  radius: this.getRadius(),
5523
4936
  };
5524
- };
5525
- #getInsideCanvasResult = (data) => {
4937
+ }
4938
+ #getInsideCanvasResult(data) {
5526
4939
  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;
5527
4940
  if (!shapeCheck && !effectCheck) {
5528
4941
  return defaultResult;
@@ -5537,8 +4950,8 @@
5537
4950
  };
5538
4951
  }
5539
4952
  return shapeResult ?? effectResult ?? defaultResult;
5540
- };
5541
- #getRollColor = color => {
4953
+ }
4954
+ #getRollColor(color) {
5542
4955
  if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
5543
4956
  return color;
5544
4957
  }
@@ -5552,8 +4965,8 @@
5552
4965
  return alterHsl(color, this.roll.alter.type, this.roll.alter.value);
5553
4966
  }
5554
4967
  return color;
5555
- };
5556
- #initPosition = position => {
4968
+ }
4969
+ #initPosition(position) {
5557
4970
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5558
4971
  if (!initialPosition) {
5559
4972
  throw new Error("a valid position cannot be found for particle");
@@ -5576,8 +4989,8 @@
5576
4989
  break;
5577
4990
  }
5578
4991
  this.offset = Vector.origin;
5579
- };
5580
- #normalizeInsideCanvasResult = (result, reason) => {
4992
+ }
4993
+ #normalizeInsideCanvasResult(result, reason) {
5581
4994
  if (typeof result === "boolean") {
5582
4995
  return {
5583
4996
  inside: result,
@@ -5589,7 +5002,7 @@
5589
5002
  margin: result.margin,
5590
5003
  reason: result.reason ?? reason,
5591
5004
  };
5592
- };
5005
+ }
5593
5006
  }
5594
5007
 
5595
5008
  class SpatialHashGrid {
@@ -5942,10 +5355,10 @@
5942
5355
  }
5943
5356
  this.#resizeFactor = undefined;
5944
5357
  }
5945
- #addToPool = (...particles) => {
5358
+ #addToPool(...particles) {
5946
5359
  this.#pool.push(...particles);
5947
- };
5948
- #applyDensity = (options, pluginsCount, group, groupOptions) => {
5360
+ }
5361
+ #applyDensity(options, pluginsCount, group, groupOptions) {
5949
5362
  const numberOptions = options.number;
5950
5363
  if (!numberOptions.density.enable) {
5951
5364
  if (group === undefined) {
@@ -5969,36 +5382,19 @@
5969
5382
  else if (particlesCount > particlesNumber) {
5970
5383
  this.removeQuantity(particlesCount - particlesNumber, group);
5971
5384
  }
5972
- };
5973
- #createBuckets = (zLayers) => {
5385
+ }
5386
+ #createBuckets(zLayers) {
5974
5387
  const bucketCount = Math.max(Math.floor(zLayers), one);
5975
5388
  return Array.from({ length: bucketCount }, () => []);
5976
- };
5977
- #getBucketIndex = (zIndex) => {
5389
+ }
5390
+ #getBucketIndex(zIndex) {
5978
5391
  const maxBucketIndex = this.#zBuckets.length - one;
5979
5392
  if (maxBucketIndex <= minIndex) {
5980
5393
  return minIndex;
5981
5394
  }
5982
5395
  return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
5983
- };
5984
- #getParticleInsertIndex = (bucket, particleId) => {
5985
- let start = minIndex, end = bucket.length;
5986
- while (start < end) {
5987
- const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
5988
- if (!middleParticle) {
5989
- end = middle;
5990
- continue;
5991
- }
5992
- if (middleParticle.id < particleId) {
5993
- start = middle + one;
5994
- }
5995
- else {
5996
- end = middle;
5997
- }
5998
- }
5999
- return start;
6000
- };
6001
- #initDensityFactor = densityOptions => {
5396
+ }
5397
+ #initDensityFactor(densityOptions) {
6002
5398
  const container = this.#container;
6003
5399
  if (!densityOptions.enable) {
6004
5400
  return defaultDensityFactor;
@@ -6008,16 +5404,16 @@
6008
5404
  return defaultDensityFactor;
6009
5405
  }
6010
5406
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
6011
- };
6012
- #insertParticleIntoBucket = (particle) => {
5407
+ }
5408
+ #insertParticleIntoBucket(particle) {
6013
5409
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
6014
5410
  if (!bucket) {
6015
5411
  return;
6016
5412
  }
6017
- bucket.splice(this.#getParticleInsertIndex(bucket, particle.id), empty, particle);
5413
+ bucket.push(particle);
6018
5414
  this.#particleBuckets.set(particle.id, bucketIndex);
6019
- };
6020
- #removeParticle = (index, group, override) => {
5415
+ }
5416
+ #removeParticle(index, group, override) {
6021
5417
  const particle = this.#array[index];
6022
5418
  if (!particle) {
6023
5419
  return false;
@@ -6033,22 +5429,20 @@
6033
5429
  });
6034
5430
  this.#addToPool(particle);
6035
5431
  return true;
6036
- };
6037
- #removeParticleFromBucket = (particle) => {
5432
+ }
5433
+ #removeParticleFromBucket(particle) {
6038
5434
  const bucketIndex = this.#particleBuckets.get(particle.id) ?? this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
6039
5435
  if (!bucket) {
6040
5436
  this.#particleBuckets.delete(particle.id);
6041
5437
  return;
6042
5438
  }
6043
- const particleIndex = this.#getParticleInsertIndex(bucket, particle.id);
6044
- if (bucket[particleIndex]?.id !== particle.id) {
6045
- this.#particleBuckets.delete(particle.id);
6046
- return;
5439
+ const idx = bucket.findIndex(p => p.id === particle.id);
5440
+ if (idx >= minIndex) {
5441
+ bucket.splice(idx, deleteCount);
6047
5442
  }
6048
- bucket.splice(particleIndex, deleteCount);
6049
5443
  this.#particleBuckets.delete(particle.id);
6050
- };
6051
- #resetBuckets = (zLayers) => {
5444
+ }
5445
+ #resetBuckets(zLayers) {
6052
5446
  const bucketCount = Math.max(Math.floor(zLayers), one);
6053
5447
  if (this.#zBuckets.length !== bucketCount) {
6054
5448
  this.#zBuckets = this.#createBuckets(bucketCount);
@@ -6057,8 +5451,8 @@
6057
5451
  for (const bucket of this.#zBuckets) {
6058
5452
  bucket.length = minIndex;
6059
5453
  }
6060
- };
6061
- #updateParticleBucket = (particle) => {
5454
+ }
5455
+ #updateParticleBucket(particle) {
6062
5456
  const newBucketIndex = this.#getBucketIndex(particle.position.z), currentBucketIndex = this.#particleBuckets.get(particle.id);
6063
5457
  if (currentBucketIndex === undefined) {
6064
5458
  this.#insertParticleIntoBucket(particle);
@@ -6069,9 +5463,9 @@
6069
5463
  }
6070
5464
  const currentBucket = this.#zBuckets[currentBucketIndex];
6071
5465
  if (currentBucket) {
6072
- const particleIndex = this.#getParticleInsertIndex(currentBucket, particle.id);
6073
- if (currentBucket[particleIndex]?.id === particle.id) {
6074
- currentBucket.splice(particleIndex, deleteCount);
5466
+ const idx = currentBucket.findIndex(p => p.id === particle.id);
5467
+ if (idx >= minIndex) {
5468
+ currentBucket.splice(idx, deleteCount);
6075
5469
  }
6076
5470
  }
6077
5471
  const newBucket = this.#zBuckets[newBucketIndex];
@@ -6079,10 +5473,16 @@
6079
5473
  this.#particleBuckets.set(particle.id, newBucketIndex);
6080
5474
  return;
6081
5475
  }
6082
- newBucket.splice(this.#getParticleInsertIndex(newBucket, particle.id), empty, particle);
5476
+ newBucket.push(particle);
5477
+ if (newBucket.length >= double) {
5478
+ const prev = newBucket[newBucket.length - double];
5479
+ if (prev && particle.id < prev.id) {
5480
+ newBucket.sort((a, b) => a.id - b.id);
5481
+ }
5482
+ }
6083
5483
  this.#particleBuckets.set(particle.id, newBucketIndex);
6084
- };
6085
- #updateParticlesPhase1 = (delta) => {
5484
+ }
5485
+ #updateParticlesPhase1(delta) {
6086
5486
  const particlesToDelete = new Set(), resizeFactor = this.#resizeFactor;
6087
5487
  for (const particle of this.#array) {
6088
5488
  if (resizeFactor && !particle.ignoresResizeRatio) {
@@ -6108,8 +5508,8 @@
6108
5508
  this.grid.insert(particle);
6109
5509
  }
6110
5510
  return particlesToDelete;
6111
- };
6112
- #updateParticlesPhase2 = (delta, particlesToDelete) => {
5511
+ }
5512
+ #updateParticlesPhase2(delta, particlesToDelete) {
6113
5513
  for (const particle of this.#array) {
6114
5514
  if (particle.destroyed) {
6115
5515
  particlesToDelete.add(particle);
@@ -6125,7 +5525,7 @@
6125
5525
  }
6126
5526
  this.#updateParticleBucket(particle);
6127
5527
  }
6128
- };
5528
+ }
6129
5529
  }
6130
5530
 
6131
5531
  class Retina {
@@ -6487,7 +5887,7 @@
6487
5887
  }
6488
5888
  return refresh;
6489
5889
  }
6490
- #nextFrame = (timestamp) => {
5890
+ #nextFrame(timestamp) {
6491
5891
  try {
6492
5892
  if (!this.#smooth &&
6493
5893
  this.#lastFrameTime !== undefined &&
@@ -6515,7 +5915,7 @@
6515
5915
  catch (e) {
6516
5916
  getLogger().error("error in animation loop", e);
6517
5917
  }
6518
- };
5918
+ }
6519
5919
  }
6520
5920
 
6521
5921
  var Container$1 = /*#__PURE__*/Object.freeze({
@@ -6561,7 +5961,7 @@
6561
5961
  BlendPluginInstance: BlendPluginInstance
6562
5962
  });
6563
5963
 
6564
- const minVelocity = 0, identity = 1, moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
5964
+ const moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
6565
5965
  function applyDistance(particle) {
6566
5966
  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;
6567
5967
  if (!hDistance && !vDistance) {
@@ -6594,7 +5994,7 @@
6594
5994
  }
6595
5995
  function move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, reduceFactor, delta) {
6596
5996
  applyPath(particle, delta);
6597
- const gravityOptions = particle.gravity, gravityFactor = gravityOptions?.enable && gravityOptions.inverse ? -identity : identity;
5997
+ const gravityOptions = particle.gravity, gravityFactor = gravityOptions?.enable && gravityOptions.inverse ? -identity$1 : identity$1;
6598
5998
  if (moveDrift && moveSpeed) {
6599
5999
  particle.velocity.x += (moveDrift * delta.factor) / (moveSpeedFactor * moveSpeed);
6600
6000
  }
@@ -6614,7 +6014,7 @@
6614
6014
  particle.velocity.y = velocity.y / moveSpeed;
6615
6015
  }
6616
6016
  }
6617
- const zIndexOptions = particle.options.zIndex, zVelocityFactor = (identity - particle.zIndexFactor) ** zIndexOptions.velocityRate;
6017
+ const zIndexOptions = particle.options.zIndex, zVelocityFactor = (identity$1 - particle.zIndexFactor) ** zIndexOptions.velocityRate;
6618
6018
  velocity.multTo(zVelocityFactor);
6619
6019
  velocity.multTo(reduceFactor);
6620
6020
  const { position } = particle;
@@ -6640,13 +6040,13 @@
6640
6040
  const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height), halfMaxSize = maxCanvasSize * half;
6641
6041
  if (particle.spin.radius > halfMaxSize) {
6642
6042
  particle.spin.radius = halfMaxSize;
6643
- particle.spin.acceleration *= -identity;
6043
+ particle.spin.acceleration *= -identity$1;
6644
6044
  }
6645
6045
  else if (particle.spin.radius < minSpinRadius) {
6646
6046
  particle.spin.radius = minSpinRadius;
6647
- particle.spin.acceleration *= -identity;
6047
+ particle.spin.acceleration *= -identity$1;
6648
6048
  }
6649
- particle.spin.angle += moveSpeed * spinFactor * (identity - particle.spin.radius / maxCanvasSize);
6049
+ particle.spin.angle += moveSpeed * spinFactor * (identity$1 - particle.spin.radius / maxCanvasSize);
6650
6050
  }
6651
6051
  function applyPath(particle, delta) {
6652
6052
  const particlesOptions = particle.options, pathOptions = particlesOptions.move.path, pathEnabled = pathOptions.enable;
@@ -6663,13 +6063,13 @@
6663
6063
  particle.velocity.addTo(path);
6664
6064
  }
6665
6065
  if (pathOptions.clamp) {
6666
- particle.velocity.x = clamp(particle.velocity.x, -identity, identity);
6667
- particle.velocity.y = clamp(particle.velocity.y, -identity, identity);
6066
+ particle.velocity.x = clamp(particle.velocity.x, -identity$1, identity$1);
6067
+ particle.velocity.y = clamp(particle.velocity.y, -identity$1, identity$1);
6668
6068
  }
6669
6069
  particle.lastPathTime -= pathDelay;
6670
6070
  }
6671
6071
  function getProximitySpeedFactor(particle) {
6672
- return particle.slow.inRange ? particle.slow.factor : identity;
6072
+ return particle.slow.inRange ? particle.slow.factor : identity$1;
6673
6073
  }
6674
6074
  function initSpin(container, particle) {
6675
6075
  const options = particle.options, spinOptions = options.move.spin;
@@ -6956,7 +6356,7 @@
6956
6356
  getLogger().error(e);
6957
6357
  }
6958
6358
  }
6959
- #initTrail = async () => {
6359
+ async #initTrail() {
6960
6360
  const options = this.#container.actualOptions, trail = options.trail;
6961
6361
  if (!trail?.enable) {
6962
6362
  return;
@@ -6994,7 +6394,7 @@
6994
6394
  img.src = trailFill.image;
6995
6395
  });
6996
6396
  }
6997
- };
6397
+ }
6998
6398
  }
6999
6399
 
7000
6400
  var TrailPluginInstance$1 = /*#__PURE__*/Object.freeze({
@@ -7087,7 +6487,13 @@
7087
6487
  this.#paused = !this.options.autoPlay;
7088
6488
  this.#particlesOptions = particlesOptions;
7089
6489
  this.#size = this.#calcSize();
7090
- this.size = getSize(this.#size, this.#container.canvas.size);
6490
+ this.size =
6491
+ this.#size.mode === PixelMode.percent
6492
+ ? {
6493
+ width: (this.#size.width / percentDenominator) * this.#container.canvas.size.width,
6494
+ height: (this.#size.height / percentDenominator) * this.#container.canvas.size.height,
6495
+ }
6496
+ : { width: this.#size.width, height: this.#size.height };
7091
6497
  this.#lifeCount = this.options.life.count ?? defaultLifeCount;
7092
6498
  this.#immortal = this.#lifeCount <= minLifeCount;
7093
6499
  if (this.options.domId) {
@@ -7158,7 +6564,13 @@
7158
6564
  ? initialPosition
7159
6565
  : this.#calcPosition();
7160
6566
  this.#size = this.#calcSize();
7161
- this.size = getSize(this.#size, container.canvas.size);
6567
+ this.size =
6568
+ this.#size.mode === PixelMode.percent
6569
+ ? {
6570
+ width: (this.#size.width / percentDenominator) * container.canvas.size.width,
6571
+ height: (this.#size.height / percentDenominator) * container.canvas.size.height,
6572
+ }
6573
+ : { width: this.#size.width, height: this.#size.height };
7162
6574
  this.#shape?.resize(this.position, this.size);
7163
6575
  }
7164
6576
  update(delta) {
@@ -7258,7 +6670,7 @@
7258
6670
  return size;
7259
6671
  })());
7260
6672
  }
7261
- #destroy = () => {
6673
+ #destroy() {
7262
6674
  this.#mutationObserver?.disconnect();
7263
6675
  this.#mutationObserver = undefined;
7264
6676
  this.#resizeObserver?.disconnect();
@@ -7267,7 +6679,7 @@
7267
6679
  this.#container.dispatchEvent("emitterDestroyed", {
7268
6680
  emitter: this,
7269
6681
  });
7270
- };
6682
+ }
7271
6683
  #emit() {
7272
6684
  if (this.#paused) {
7273
6685
  return;
@@ -7327,7 +6739,7 @@
7327
6739
  }
7328
6740
  }
7329
6741
  }
7330
- #prepareToDie = () => {
6742
+ #prepareToDie() {
7331
6743
  if (this.#paused) {
7332
6744
  return;
7333
6745
  }
@@ -7335,8 +6747,8 @@
7335
6747
  if ((this.#lifeCount > minLifeCount || this.#immortal) && duration !== undefined && duration > minDuration) {
7336
6748
  this.#duration = duration * millisecondsToSeconds;
7337
6749
  }
7338
- };
7339
- #setColorAnimation = (animation, initValue, maxValue, factor = defaultColorAnimationFactor) => {
6750
+ }
6751
+ #setColorAnimation(animation, initValue, maxValue, factor = defaultColorAnimationFactor) {
7340
6752
  const container = this.#container;
7341
6753
  if (!animation.enable) {
7342
6754
  return initValue;
@@ -7345,7 +6757,7 @@
7345
6757
  ? (delay * millisecondsToSeconds) / container.retina.reduceFactor
7346
6758
  : Infinity, colorSpeed = getRangeValue(animation.speed);
7347
6759
  return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
7348
- };
6760
+ }
7349
6761
  }
7350
6762
 
7351
6763
  var EmitterInstance$1 = /*#__PURE__*/Object.freeze({