@tsparticles/preset-fireworks 4.2.1 → 4.3.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.2.1 */
2
+ /* Preset v4.3.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) :
@@ -374,29 +374,27 @@
374
374
  }
375
375
  }
376
376
  else if (!isObject(destination) || Array.isArray(destination)) {
377
- destination = {};
377
+ destination = Object.create(null);
378
378
  }
379
- const sourceKeys = Object.keys(source), dangerousKeys = new Set(["__proto__", "constructor", "prototype"]), hasNested = sourceKeys.some(k => {
379
+ const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
380
380
  const v = source[k];
381
381
  return isObject(v) || Array.isArray(v);
382
382
  });
383
383
  if (!hasNested) {
384
384
  const sourceDict = source, destDict = destination;
385
385
  for (const key of sourceKeys) {
386
- if (dangerousKeys.has(key)) {
386
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
387
387
  continue;
388
388
  }
389
- if (key in sourceDict) {
390
- const v = sourceDict[key];
391
- if (v !== undefined) {
392
- destDict[key] = v;
393
- }
389
+ const v = sourceDict[key];
390
+ if (v !== undefined) {
391
+ destDict[key] = v;
394
392
  }
395
393
  }
396
394
  continue;
397
395
  }
398
396
  for (const key of sourceKeys) {
399
- if (dangerousKeys.has(key)) {
397
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
400
398
  continue;
401
399
  }
402
400
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -812,7 +810,7 @@
812
810
  return this.#domArray;
813
811
  }
814
812
  get version() {
815
- return "4.2.1";
813
+ return "4.3.0";
816
814
  }
817
815
  addEventListener(type, listener) {
818
816
  this.#eventDispatcher.addEventListener(type, listener);
@@ -1045,6 +1043,18 @@
1045
1043
  AnimationStatus["decreasing"] = "decreasing";
1046
1044
  })(AnimationStatus || (AnimationStatus = {}));
1047
1045
 
1046
+ var DrawLayer;
1047
+ (function (DrawLayer) {
1048
+ DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
1049
+ DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
1050
+ DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
1051
+ DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
1052
+ DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
1053
+ DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
1054
+ DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
1055
+ DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1056
+ })(DrawLayer || (DrawLayer = {}));
1057
+
1048
1058
  class OptionLoader {
1049
1059
  load(data) {
1050
1060
  if (isNull(data)) {
@@ -1198,6 +1208,8 @@
1198
1208
 
1199
1209
  class Background extends OptionLoader {
1200
1210
  color;
1211
+ draw;
1212
+ element;
1201
1213
  image = "";
1202
1214
  opacity = 1;
1203
1215
  position = "";
@@ -1212,6 +1224,8 @@
1212
1224
  if (data.color !== undefined) {
1213
1225
  this.color = OptionsColor.create(this.color, data.color);
1214
1226
  }
1227
+ loadProperty(this, "element", data.element);
1228
+ loadProperty(this, "draw", data.draw);
1215
1229
  loadProperty(this, "image", data.image);
1216
1230
  loadProperty(this, "position", data.position);
1217
1231
  loadProperty(this, "repeat", data.repeat);
@@ -1757,7 +1771,7 @@
1757
1771
  }
1758
1772
  }
1759
1773
 
1760
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
1774
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1761
1775
  function getCachedStyle(key, generator) {
1762
1776
  let cached = styleCache.get(key);
1763
1777
  if (!cached) {
@@ -1897,6 +1911,17 @@
1897
1911
  : 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));
1898
1912
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1899
1913
  }
1914
+ function hslToRgbFloat(hsl) {
1915
+ 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;
1916
+ if (s === sMin) {
1917
+ const grayscaleValue = lNormalized * rgbMax;
1918
+ return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1919
+ }
1920
+ const temp1 = lNormalized < half
1921
+ ? lNormalized * (sNormalizedOffset + sNormalized)
1922
+ : 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));
1923
+ return { r: red, g: green, b: blue };
1924
+ }
1900
1925
  function hslaToRgba(hsla) {
1901
1926
  const rgbResult = hslToRgb(hsla);
1902
1927
  return {
@@ -1906,8 +1931,9 @@
1906
1931
  r: rgbResult.r,
1907
1932
  };
1908
1933
  }
1909
- function getRandomRgbColor(min) {
1910
- const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity$1, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1934
+ function getRandomRgbColor(min, hdr) {
1935
+ const fixedMin = defaultRgbMin;
1936
+ const fixedMax = rgbMax + identity$1, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1911
1937
  return {
1912
1938
  b: getRgbInRangeValue(),
1913
1939
  g: getRgbInRangeValue(),
@@ -1915,7 +1941,7 @@
1915
1941
  };
1916
1942
  }
1917
1943
  function getStyleFromRgb(color, hdr, opacity) {
1918
- const op = opacity ?? defaultOpacity$1, key = `rgb-${color.r.toFixed(rgbFixedPrecision)}-${color.g.toFixed(rgbFixedPrecision)}-${color.b.toFixed(rgbFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1944
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1919
1945
  return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
1920
1946
  }
1921
1947
  function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
@@ -1926,9 +1952,9 @@
1926
1952
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1927
1953
  }
1928
1954
  function getStyleFromHsl(color, hdr, opacity) {
1929
- const op = opacity ?? defaultOpacity$1, key = `hsl-${color.h.toFixed(hslFixedPrecision)}-${color.s.toFixed(hslFixedPrecision)}-${color.l.toFixed(hslFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1955
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1930
1956
  return getCachedStyle(key, () => hdr
1931
- ? getStyleFromRgb(hslToRgb(color), true, opacity)
1957
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
1932
1958
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1933
1959
  }
1934
1960
  function getHslFromAnimation(animation) {
@@ -1991,7 +2017,7 @@
1991
2017
  colorValue.velocity = defaultVelocity;
1992
2018
  }
1993
2019
  }
1994
- function updateColorValue(data, decrease, delta) {
2020
+ function updateColorValue(data, decrease, delta, hdr) {
1995
2021
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
1996
2022
  if (!data.enable ||
1997
2023
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2004,7 +2030,7 @@
2004
2030
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2005
2031
  return;
2006
2032
  }
2007
- const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = (data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor, decay = data.decay ?? identity, max = data.max, min = data.min;
2033
+ const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = ((data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor) * (hdr ? hdrAnimationScale : identity), decay = data.decay ?? identity, max = data.max, min = data.min;
2008
2034
  if (!decrease || data.status === AnimationStatus.increasing) {
2009
2035
  data.value += velocity;
2010
2036
  if (data.value > max) {
@@ -2031,14 +2057,14 @@
2031
2057
  }
2032
2058
  data.value = clamp(data.value, min, max);
2033
2059
  }
2034
- function updateColor(color, delta) {
2060
+ function updateColor(color, delta, hdr) {
2035
2061
  if (!color) {
2036
2062
  return;
2037
2063
  }
2038
2064
  const { h, s, l } = color;
2039
- updateColorValue(h, false, delta);
2040
- updateColorValue(s, true, delta);
2041
- updateColorValue(l, true, delta);
2065
+ updateColorValue(h, false, delta, hdr);
2066
+ updateColorValue(s, true, delta, hdr);
2067
+ updateColorValue(l, true, delta, hdr);
2042
2068
  }
2043
2069
  function alterHsl(color, type, value) {
2044
2070
  return {
@@ -2344,7 +2370,7 @@
2344
2370
  }
2345
2371
 
2346
2372
  async function loadBlendPlugin(engine) {
2347
- engine.checkVersion("4.2.1");
2373
+ engine.checkVersion("4.3.0");
2348
2374
  await engine.pluginManager.register(e => {
2349
2375
  e.pluginManager.addPlugin(new BlendPlugin());
2350
2376
  });
@@ -2381,7 +2407,7 @@
2381
2407
  }
2382
2408
 
2383
2409
  async function loadCircleShape(engine) {
2384
- engine.checkVersion("4.2.1");
2410
+ engine.checkVersion("4.3.0");
2385
2411
  await engine.pluginManager.register(e => {
2386
2412
  e.pluginManager.addShape(["circle"], () => {
2387
2413
  return Promise.resolve(new CircleDrawer());
@@ -2429,7 +2455,7 @@
2429
2455
  }
2430
2456
 
2431
2457
  async function loadHexColorPlugin(engine) {
2432
- engine.checkVersion("4.2.1");
2458
+ engine.checkVersion("4.3.0");
2433
2459
  await engine.pluginManager.register(e => {
2434
2460
  e.pluginManager.addColorManager("hex", new HexColorManager());
2435
2461
  });
@@ -2482,7 +2508,7 @@
2482
2508
  }
2483
2509
 
2484
2510
  async function loadHslColorPlugin(engine) {
2485
- engine.checkVersion("4.2.1");
2511
+ engine.checkVersion("4.3.0");
2486
2512
  await engine.pluginManager.register(e => {
2487
2513
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2488
2514
  });
@@ -2506,7 +2532,7 @@
2506
2532
  }
2507
2533
 
2508
2534
  async function loadMovePlugin(engine) {
2509
- engine.checkVersion("4.2.1");
2535
+ engine.checkVersion("4.3.0");
2510
2536
  await engine.pluginManager.register(e => {
2511
2537
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2512
2538
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2722,7 +2748,7 @@
2722
2748
  }
2723
2749
 
2724
2750
  async function loadOpacityUpdater(engine) {
2725
- engine.checkVersion("4.2.1");
2751
+ engine.checkVersion("4.3.0");
2726
2752
  await engine.pluginManager.register(e => {
2727
2753
  e.pluginManager.addParticleUpdater("opacity", container => {
2728
2754
  return Promise.resolve(new OpacityUpdater(container));
@@ -3067,7 +3093,7 @@
3067
3093
  }
3068
3094
 
3069
3095
  async function loadOutModesUpdater(engine) {
3070
- engine.checkVersion("4.2.1");
3096
+ engine.checkVersion("4.3.0");
3071
3097
  await engine.pluginManager.register(e => {
3072
3098
  e.pluginManager.addParticleUpdater("outModes", container => {
3073
3099
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3132,13 +3158,13 @@
3132
3158
  if (!this.isEnabled(particle)) {
3133
3159
  return;
3134
3160
  }
3135
- updateColor(particle.fillColor, delta);
3136
- updateColor(particle.strokeColor, delta);
3161
+ updateColor(particle.fillColor, delta, this.#container.hdr);
3162
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
3137
3163
  }
3138
3164
  }
3139
3165
 
3140
3166
  async function loadPaintUpdater(engine) {
3141
- engine.checkVersion("4.2.1");
3167
+ engine.checkVersion("4.3.0");
3142
3168
  await engine.pluginManager.register(e => {
3143
3169
  e.pluginManager.addParticleUpdater("paint", container => {
3144
3170
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3193,7 +3219,7 @@
3193
3219
  }
3194
3220
 
3195
3221
  async function loadRgbColorPlugin(engine) {
3196
- engine.checkVersion("4.2.1");
3222
+ engine.checkVersion("4.3.0");
3197
3223
  await engine.pluginManager.register(e => {
3198
3224
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3199
3225
  });
@@ -3278,7 +3304,7 @@
3278
3304
  }
3279
3305
 
3280
3306
  async function loadSizeUpdater(engine) {
3281
- engine.checkVersion("4.2.1");
3307
+ engine.checkVersion("4.3.0");
3282
3308
  await engine.pluginManager.register(e => {
3283
3309
  e.pluginManager.addParticleUpdater("size", container => {
3284
3310
  return Promise.resolve(new SizeUpdater(container));
@@ -3287,7 +3313,7 @@
3287
3313
  }
3288
3314
 
3289
3315
  async function loadBasic(engine) {
3290
- engine.checkVersion("4.2.1");
3316
+ engine.checkVersion("4.3.0");
3291
3317
  await engine.pluginManager.register(async (e) => {
3292
3318
  await Promise.all([
3293
3319
  loadBlendPlugin(e),
@@ -3618,7 +3644,7 @@
3618
3644
  }
3619
3645
 
3620
3646
  async function loadDestroyUpdater(engine) {
3621
- engine.checkVersion("4.2.1");
3647
+ engine.checkVersion("4.3.0");
3622
3648
  await engine.pluginManager.register(e => {
3623
3649
  e.pluginManager.addParticleUpdater("destroy", container => {
3624
3650
  return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
@@ -3849,7 +3875,7 @@
3849
3875
  })(EmitterClickMode || (EmitterClickMode = {}));
3850
3876
 
3851
3877
  async function loadEmittersPluginSimple(engine) {
3852
- engine.checkVersion("4.2.1");
3878
+ engine.checkVersion("4.3.0");
3853
3879
  await engine.pluginManager.register(async (e) => {
3854
3880
  const instancesManager = await getEmittersInstancesManager(e);
3855
3881
  await addEmittersShapesManager(e);
@@ -3937,7 +3963,7 @@
3937
3963
  }
3938
3964
 
3939
3965
  async function loadEmittersShapeSquare(engine) {
3940
- engine.checkVersion("4.2.1");
3966
+ engine.checkVersion("4.3.0");
3941
3967
  await engine.pluginManager.register((e) => {
3942
3968
  ensureEmittersPluginLoaded(e);
3943
3969
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -4081,7 +4107,7 @@
4081
4107
  }
4082
4108
 
4083
4109
  async function loadLifeUpdater(engine) {
4084
- engine.checkVersion("4.2.1");
4110
+ engine.checkVersion("4.3.0");
4085
4111
  await engine.pluginManager.register(e => {
4086
4112
  e.pluginManager.addParticleUpdater("life", container => {
4087
4113
  return Promise.resolve(new LifeUpdater(container));
@@ -4107,7 +4133,7 @@
4107
4133
  }
4108
4134
 
4109
4135
  async function loadLineShape(engine) {
4110
- engine.checkVersion("4.2.1");
4136
+ engine.checkVersion("4.3.0");
4111
4137
  await engine.pluginManager.register(e => {
4112
4138
  e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
4113
4139
  });
@@ -4211,7 +4237,7 @@
4211
4237
  }
4212
4238
 
4213
4239
  async function loadRotateUpdater(engine) {
4214
- engine.checkVersion("4.2.1");
4240
+ engine.checkVersion("4.3.0");
4215
4241
  await engine.pluginManager.register(e => {
4216
4242
  e.pluginManager.addParticleUpdater("rotate", container => {
4217
4243
  return Promise.resolve(new RotateUpdater(container));
@@ -4527,7 +4553,7 @@
4527
4553
  }
4528
4554
 
4529
4555
  async function loadSoundsPlugin(engine) {
4530
- engine.checkVersion("4.2.1");
4556
+ engine.checkVersion("4.3.0");
4531
4557
  await engine.pluginManager.register(e => {
4532
4558
  e.pluginManager.addPlugin(new SoundsPlugin(e));
4533
4559
  });
@@ -4643,7 +4669,7 @@
4643
4669
  }
4644
4670
 
4645
4671
  async function loadTrailEffect(engine) {
4646
- engine.checkVersion("4.2.1");
4672
+ engine.checkVersion("4.3.0");
4647
4673
  await engine.pluginManager.register(e => {
4648
4674
  e.pluginManager.addEffect("trail", container => {
4649
4675
  return Promise.resolve(new TrailDrawer(container));
@@ -4684,10 +4710,10 @@
4684
4710
  }
4685
4711
  }
4686
4712
  class RenderManager {
4713
+ #backgroundElement;
4714
+ #backgroundWarnings;
4687
4715
  #canvasClearPlugins;
4688
4716
  #canvasManager;
4689
- #canvasPaintPlugins;
4690
- #clearDrawPlugins;
4691
4717
  #colorPlugins;
4692
4718
  #container;
4693
4719
  #context;
@@ -4695,9 +4721,7 @@
4695
4721
  #drawParticlePlugins;
4696
4722
  #drawParticlesCleanupPlugins;
4697
4723
  #drawParticlesSetupPlugins;
4698
- #drawPlugins;
4699
- #drawSettingsCleanupPlugins;
4700
- #drawSettingsSetupPlugins;
4724
+ #layers;
4701
4725
  #pluginManager;
4702
4726
  #postDrawUpdaters;
4703
4727
  #preDrawUpdaters;
@@ -4709,18 +4733,25 @@
4709
4733
  this.#container = container;
4710
4734
  this.#canvasManager = canvasManager;
4711
4735
  this.#context = null;
4736
+ this.#backgroundElement = null;
4737
+ this.#backgroundWarnings = new Set();
4712
4738
  this.#preDrawUpdaters = [];
4713
4739
  this.#postDrawUpdaters = [];
4714
- this.#colorPlugins = [];
4715
4740
  this.#canvasClearPlugins = [];
4716
- this.#canvasPaintPlugins = [];
4717
- this.#clearDrawPlugins = [];
4741
+ this.#colorPlugins = [];
4718
4742
  this.#drawParticlePlugins = [];
4719
4743
  this.#drawParticlesCleanupPlugins = [];
4720
4744
  this.#drawParticlesSetupPlugins = [];
4721
- this.#drawPlugins = [];
4722
- this.#drawSettingsSetupPlugins = [];
4723
- this.#drawSettingsCleanupPlugins = [];
4745
+ this.#layers = {
4746
+ 0: [],
4747
+ 1: [],
4748
+ 2: [],
4749
+ 3: [],
4750
+ 4: [],
4751
+ 5: [],
4752
+ 6: [],
4753
+ 7: [],
4754
+ };
4724
4755
  }
4725
4756
  get settings() {
4726
4757
  return this.#contextSettings;
@@ -4734,32 +4765,38 @@
4734
4765
  });
4735
4766
  }
4736
4767
  clear() {
4737
- let pluginHandled = false;
4738
4768
  for (const plugin of this.#canvasClearPlugins) {
4739
- pluginHandled = plugin.canvasClear?.() ?? false;
4740
- if (pluginHandled) {
4741
- break;
4769
+ if (plugin.canvasClear?.() ?? false) {
4770
+ return;
4742
4771
  }
4743
4772
  }
4744
- if (pluginHandled) {
4745
- return;
4773
+ for (const layer of Object.values(DrawLayer)) {
4774
+ if (typeof layer === "number") {
4775
+ for (const plugin of this.#getLayerPlugins(layer)) {
4776
+ if (plugin.canvasClear?.() ?? false) {
4777
+ return;
4778
+ }
4779
+ }
4780
+ }
4746
4781
  }
4747
4782
  this.canvasClear();
4748
4783
  }
4749
4784
  destroy() {
4750
4785
  this.stop();
4786
+ this.#backgroundElement = null;
4787
+ this.#backgroundWarnings.clear();
4751
4788
  this.#preDrawUpdaters = [];
4752
4789
  this.#postDrawUpdaters = [];
4753
- this.#colorPlugins = [];
4754
4790
  this.#canvasClearPlugins = [];
4755
- this.#canvasPaintPlugins = [];
4756
- this.#clearDrawPlugins = [];
4791
+ this.#colorPlugins = [];
4757
4792
  this.#drawParticlePlugins = [];
4758
4793
  this.#drawParticlesCleanupPlugins = [];
4759
4794
  this.#drawParticlesSetupPlugins = [];
4760
- this.#drawPlugins = [];
4761
- this.#drawSettingsSetupPlugins = [];
4762
- this.#drawSettingsCleanupPlugins = [];
4795
+ for (const layer of Object.values(DrawLayer)) {
4796
+ if (typeof layer === "number") {
4797
+ this.#layers[layer] = [];
4798
+ }
4799
+ }
4763
4800
  }
4764
4801
  draw(cb) {
4765
4802
  const ctx = this.#context;
@@ -4816,21 +4853,40 @@
4816
4853
  });
4817
4854
  }
4818
4855
  drawParticles(delta) {
4819
- const { particles } = this.#container;
4856
+ const { particles, actualOptions } = this.#container;
4820
4857
  this.clear();
4821
4858
  particles.update(delta);
4822
4859
  this.draw(ctx => {
4823
- for (const plugin of this.#drawSettingsSetupPlugins) {
4860
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
4861
+ if (this.#backgroundElement) {
4862
+ try {
4863
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
4864
+ }
4865
+ catch {
4866
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
4867
+ }
4868
+ }
4869
+ const background = actualOptions.background;
4870
+ if (background.draw) {
4871
+ try {
4872
+ background.draw(ctx, delta);
4873
+ }
4874
+ catch {
4875
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
4876
+ }
4877
+ }
4878
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
4879
+ plugin.canvasPaint?.();
4880
+ }
4881
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
4824
4882
  plugin.drawSettingsSetup?.(ctx, delta);
4825
4883
  }
4826
- for (const plugin of this.#drawPlugins) {
4884
+ for (const plugin of this.#getLayerPlugins(DrawLayer.PluginContent)) {
4827
4885
  plugin.draw?.(ctx, delta);
4828
4886
  }
4829
4887
  particles.drawParticles(delta);
4830
- for (const plugin of this.#clearDrawPlugins) {
4888
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasCleanup)) {
4831
4889
  plugin.clearDraw?.(ctx, delta);
4832
- }
4833
- for (const plugin of this.#drawSettingsCleanupPlugins) {
4834
4890
  plugin.drawSettingsCleanup?.(ctx, delta);
4835
4891
  }
4836
4892
  });
@@ -4838,29 +4894,24 @@
4838
4894
  init() {
4839
4895
  this.initUpdaters();
4840
4896
  this.initPlugins();
4897
+ this.#resolveBackgroundElement();
4841
4898
  this.paint();
4842
4899
  }
4843
4900
  initPlugins() {
4844
- this.#colorPlugins = [];
4845
4901
  this.#canvasClearPlugins = [];
4846
- this.#canvasPaintPlugins = [];
4847
- this.#clearDrawPlugins = [];
4902
+ this.#colorPlugins = [];
4848
4903
  this.#drawParticlePlugins = [];
4849
4904
  this.#drawParticlesSetupPlugins = [];
4850
4905
  this.#drawParticlesCleanupPlugins = [];
4851
- this.#drawPlugins = [];
4852
- this.#drawSettingsSetupPlugins = [];
4853
- this.#drawSettingsCleanupPlugins = [];
4906
+ for (const layer of Object.values(DrawLayer)) {
4907
+ if (typeof layer === "number") {
4908
+ this.#layers[layer] = [];
4909
+ }
4910
+ }
4854
4911
  for (const plugin of this.#container.plugins) {
4855
4912
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4856
4913
  this.#colorPlugins.push(plugin);
4857
4914
  }
4858
- if (plugin.canvasClear) {
4859
- this.#canvasClearPlugins.push(plugin);
4860
- }
4861
- if (plugin.canvasPaint) {
4862
- this.#canvasPaintPlugins.push(plugin);
4863
- }
4864
4915
  if (plugin.drawParticle) {
4865
4916
  this.#drawParticlePlugins.push(plugin);
4866
4917
  }
@@ -4870,17 +4921,20 @@
4870
4921
  if (plugin.drawParticleCleanup) {
4871
4922
  this.#drawParticlesCleanupPlugins.push(plugin);
4872
4923
  }
4873
- if (plugin.draw) {
4874
- this.#drawPlugins.push(plugin);
4924
+ if (plugin.canvasClear) {
4925
+ this.#canvasClearPlugins.push(plugin);
4926
+ }
4927
+ if (plugin.canvasPaint) {
4928
+ this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
4875
4929
  }
4876
4930
  if (plugin.drawSettingsSetup) {
4877
- this.#drawSettingsSetupPlugins.push(plugin);
4931
+ this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
4878
4932
  }
4879
- if (plugin.drawSettingsCleanup) {
4880
- this.#drawSettingsCleanupPlugins.push(plugin);
4933
+ if (plugin.draw) {
4934
+ this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
4881
4935
  }
4882
- if (plugin.clearDraw) {
4883
- this.#clearDrawPlugins.push(plugin);
4936
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
4937
+ this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
4884
4938
  }
4885
4939
  }
4886
4940
  }
@@ -4898,7 +4952,7 @@
4898
4952
  }
4899
4953
  paint() {
4900
4954
  let handled = false;
4901
- for (const plugin of this.#canvasPaintPlugins) {
4955
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
4902
4956
  handled = plugin.canvasPaint?.() ?? false;
4903
4957
  if (handled) {
4904
4958
  break;
@@ -5071,6 +5125,9 @@
5071
5125
  }
5072
5126
  drawer.beforeDraw(data);
5073
5127
  }
5128
+ #getLayerPlugins(layer) {
5129
+ return this.#layers[layer];
5130
+ }
5074
5131
  #getPluginParticleColors(particle) {
5075
5132
  let fColor, sColor;
5076
5133
  for (const plugin of this.#colorPlugins) {
@@ -5088,6 +5145,39 @@
5088
5145
  this.#reusablePluginColors[sColorIndex] = sColor;
5089
5146
  return this.#reusablePluginColors;
5090
5147
  }
5148
+ #resolveBackgroundElement() {
5149
+ const background = this.#container.actualOptions.background;
5150
+ this.#backgroundElement = null;
5151
+ if (!background.element) {
5152
+ return;
5153
+ }
5154
+ if (typeof background.element === "string") {
5155
+ if (typeof document !== "undefined") {
5156
+ const node = document.querySelector(background.element);
5157
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
5158
+ this.#backgroundElement = node;
5159
+ }
5160
+ else if (node) {
5161
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
5162
+ }
5163
+ else {
5164
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
5165
+ }
5166
+ }
5167
+ }
5168
+ else if (background.element instanceof HTMLCanvasElement ||
5169
+ background.element instanceof OffscreenCanvas ||
5170
+ background.element instanceof HTMLVideoElement ||
5171
+ background.element instanceof HTMLImageElement) {
5172
+ this.#backgroundElement = background.element;
5173
+ }
5174
+ }
5175
+ #warnOnce(key, message) {
5176
+ if (!this.#backgroundWarnings.has(key)) {
5177
+ this.#backgroundWarnings.add(key);
5178
+ getLogger().warning(message);
5179
+ }
5180
+ }
5091
5181
  }
5092
5182
 
5093
5183
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -5664,7 +5754,6 @@
5664
5754
  }
5665
5755
  class Particle {
5666
5756
  backColor;
5667
- bubble;
5668
5757
  destroyed;
5669
5758
  direction;
5670
5759
  effect;
@@ -5698,7 +5787,6 @@
5698
5787
  shapeData;
5699
5788
  sides;
5700
5789
  size;
5701
- slow;
5702
5790
  spawning;
5703
5791
  strokeColor;
5704
5792
  strokeOpacity;
@@ -5720,18 +5808,25 @@
5720
5808
  d: 1,
5721
5809
  };
5722
5810
  #container;
5811
+ #modifiers = [];
5723
5812
  #pluginManager;
5724
5813
  constructor(pluginManager, container) {
5725
5814
  this.#pluginManager = pluginManager;
5726
5815
  this.#container = container;
5727
5816
  }
5817
+ addModifier(modifier) {
5818
+ this.#modifiers.push(modifier);
5819
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
5820
+ }
5821
+ clearModifiers() {
5822
+ this.#modifiers.length = 0;
5823
+ }
5728
5824
  destroy(override) {
5729
5825
  if (this.unbreakable || this.destroyed) {
5730
5826
  return;
5731
5827
  }
5732
5828
  this.destroyed = true;
5733
- this.bubble.inRange = false;
5734
- this.slow.inRange = false;
5829
+ this.clearModifiers();
5735
5830
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
5736
5831
  shapeDrawer?.particleDestroy?.(this);
5737
5832
  for (const plugin of container.particleDestroyedPlugins) {
@@ -5753,13 +5848,16 @@
5753
5848
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
5754
5849
  }
5755
5850
  getFillColor() {
5756
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
5851
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
5757
5852
  }
5758
5853
  getMass() {
5759
5854
  return this.getRadius() ** squareExp * Math.PI * half;
5760
5855
  }
5856
+ getModifier(id) {
5857
+ return this.#modifiers.find(m => m.id === id);
5858
+ }
5761
5859
  getOpacity() {
5762
- const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, opacity = this.bubble.opacity ?? getRangeValue(this.opacity?.value ?? defaultOpacity$1), fillOpacity = this.fillOpacity ?? defaultOpacity$1, strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5860
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$1, strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5763
5861
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5764
5862
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5765
5863
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -5772,7 +5870,7 @@
5772
5870
  return this.#cachedPosition;
5773
5871
  }
5774
5872
  getRadius() {
5775
- return this.bubble.radius ?? this.size.value;
5873
+ return this.#applyModifiers(this.size.value, m => m.radius);
5776
5874
  }
5777
5875
  getRotateData() {
5778
5876
  const angle = this.getAngle();
@@ -5781,7 +5879,7 @@
5781
5879
  return this.#cachedRotateData;
5782
5880
  }
5783
5881
  getStrokeColor() {
5784
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
5882
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
5785
5883
  }
5786
5884
  getTransformData(externalTransform) {
5787
5885
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -5801,13 +5899,6 @@
5801
5899
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
5802
5900
  container.retina.initParticle(this);
5803
5901
  runUpdaterPreInit(container.particleUpdaters, this);
5804
- this.bubble = {
5805
- inRange: false,
5806
- };
5807
- this.slow = {
5808
- inRange: false,
5809
- factor: 1,
5810
- };
5811
5902
  this.#initPosition(position);
5812
5903
  this.initialVelocity = this.#calculateVelocity();
5813
5904
  this.velocity = this.initialVelocity.copy();
@@ -5847,11 +5938,29 @@
5847
5938
  isVisible() {
5848
5939
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
5849
5940
  }
5941
+ removeModifier(id) {
5942
+ const idx = this.#modifiers.findIndex(m => m.id === id);
5943
+ if (idx >= defaultAngle) {
5944
+ this.#modifiers.splice(idx, identity$1);
5945
+ }
5946
+ }
5850
5947
  reset() {
5851
5948
  for (const updater of this.#container.particleUpdaters) {
5852
5949
  updater.reset?.(this);
5853
5950
  }
5854
5951
  }
5952
+ #applyModifiers(base, getter) {
5953
+ let value = base;
5954
+ for (const mod of this.#modifiers) {
5955
+ if (mod.enabled) {
5956
+ const override = getter(mod);
5957
+ if (override !== undefined) {
5958
+ value = override;
5959
+ }
5960
+ }
5961
+ }
5962
+ return value;
5963
+ }
5855
5964
  #calcPosition(position, zIndex) {
5856
5965
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
5857
5966
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -6953,6 +7062,7 @@
6953
7062
  });
6954
7063
 
6955
7064
  class BlendPluginInstance {
7065
+ layer = DrawLayer.CanvasSetup;
6956
7066
  #container;
6957
7067
  #defaultCompositeValue;
6958
7068
  constructor(container) {
@@ -7098,7 +7208,8 @@
7098
7208
  particle.lastPathTime -= pathDelay;
7099
7209
  }
7100
7210
  function getProximitySpeedFactor(particle) {
7101
- return particle.slow.inRange ? particle.slow.factor : identity$1;
7211
+ const mod = particle.getModifier("slow");
7212
+ return mod?.enabled ? (mod.speedFactor ?? identity$1) : identity$1;
7102
7213
  }
7103
7214
  function initSpin(container, particle) {
7104
7215
  const options = particle.options, spinOptions = options.move.spin;