@tsparticles/preset-hyperspace 4.2.0 → 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.0 */
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) :
@@ -371,29 +371,27 @@
371
371
  }
372
372
  }
373
373
  else if (!isObject(destination) || Array.isArray(destination)) {
374
- destination = {};
374
+ destination = Object.create(null);
375
375
  }
376
- const sourceKeys = Object.keys(source), dangerousKeys = new Set(["__proto__", "constructor", "prototype"]), hasNested = sourceKeys.some(k => {
376
+ const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
377
377
  const v = source[k];
378
378
  return isObject(v) || Array.isArray(v);
379
379
  });
380
380
  if (!hasNested) {
381
381
  const sourceDict = source, destDict = destination;
382
382
  for (const key of sourceKeys) {
383
- if (dangerousKeys.has(key)) {
383
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
384
384
  continue;
385
385
  }
386
- if (key in sourceDict) {
387
- const v = sourceDict[key];
388
- if (v !== undefined) {
389
- destDict[key] = v;
390
- }
386
+ const v = sourceDict[key];
387
+ if (v !== undefined) {
388
+ destDict[key] = v;
391
389
  }
392
390
  }
393
391
  continue;
394
392
  }
395
393
  for (const key of sourceKeys) {
396
- if (dangerousKeys.has(key)) {
394
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
397
395
  continue;
398
396
  }
399
397
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -809,7 +807,7 @@
809
807
  return this.#domArray;
810
808
  }
811
809
  get version() {
812
- return "4.2.0";
810
+ return "4.3.0";
813
811
  }
814
812
  addEventListener(type, listener) {
815
813
  this.#eventDispatcher.addEventListener(type, listener);
@@ -1042,6 +1040,18 @@
1042
1040
  AnimationStatus["decreasing"] = "decreasing";
1043
1041
  })(AnimationStatus || (AnimationStatus = {}));
1044
1042
 
1043
+ var DrawLayer;
1044
+ (function (DrawLayer) {
1045
+ DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
1046
+ DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
1047
+ DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
1048
+ DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
1049
+ DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
1050
+ DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
1051
+ DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
1052
+ DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1053
+ })(DrawLayer || (DrawLayer = {}));
1054
+
1045
1055
  class OptionLoader {
1046
1056
  load(data) {
1047
1057
  if (isNull(data)) {
@@ -1195,6 +1205,8 @@
1195
1205
 
1196
1206
  class Background extends OptionLoader {
1197
1207
  color;
1208
+ draw;
1209
+ element;
1198
1210
  image = "";
1199
1211
  opacity = 1;
1200
1212
  position = "";
@@ -1209,6 +1221,8 @@
1209
1221
  if (data.color !== undefined) {
1210
1222
  this.color = OptionsColor.create(this.color, data.color);
1211
1223
  }
1224
+ loadProperty(this, "element", data.element);
1225
+ loadProperty(this, "draw", data.draw);
1212
1226
  loadProperty(this, "image", data.image);
1213
1227
  loadProperty(this, "position", data.position);
1214
1228
  loadProperty(this, "repeat", data.repeat);
@@ -1754,7 +1768,7 @@
1754
1768
  }
1755
1769
  }
1756
1770
 
1757
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
1771
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1758
1772
  function getCachedStyle(key, generator) {
1759
1773
  let cached = styleCache.get(key);
1760
1774
  if (!cached) {
@@ -1894,6 +1908,17 @@
1894
1908
  : 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));
1895
1909
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1896
1910
  }
1911
+ function hslToRgbFloat(hsl) {
1912
+ 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;
1913
+ if (s === sMin) {
1914
+ const grayscaleValue = lNormalized * rgbMax;
1915
+ return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1916
+ }
1917
+ const temp1 = lNormalized < half
1918
+ ? lNormalized * (sNormalizedOffset + sNormalized)
1919
+ : 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));
1920
+ return { r: red, g: green, b: blue };
1921
+ }
1897
1922
  function hslaToRgba(hsla) {
1898
1923
  const rgbResult = hslToRgb(hsla);
1899
1924
  return {
@@ -1903,8 +1928,9 @@
1903
1928
  r: rgbResult.r,
1904
1929
  };
1905
1930
  }
1906
- function getRandomRgbColor(min) {
1907
- const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity$1, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1931
+ function getRandomRgbColor(min, hdr) {
1932
+ const fixedMin = defaultRgbMin;
1933
+ const fixedMax = rgbMax + identity$1, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1908
1934
  return {
1909
1935
  b: getRgbInRangeValue(),
1910
1936
  g: getRgbInRangeValue(),
@@ -1912,7 +1938,7 @@
1912
1938
  };
1913
1939
  }
1914
1940
  function getStyleFromRgb(color, hdr, opacity) {
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()}`;
1941
+ 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()}`;
1916
1942
  return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
1917
1943
  }
1918
1944
  function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
@@ -1923,9 +1949,9 @@
1923
1949
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1924
1950
  }
1925
1951
  function getStyleFromHsl(color, hdr, opacity) {
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()}`;
1952
+ 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()}`;
1927
1953
  return getCachedStyle(key, () => hdr
1928
- ? getStyleFromRgb(hslToRgb(color), true, opacity)
1954
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
1929
1955
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1930
1956
  }
1931
1957
  function getHslFromAnimation(animation) {
@@ -1988,7 +2014,7 @@
1988
2014
  colorValue.velocity = defaultVelocity;
1989
2015
  }
1990
2016
  }
1991
- function updateColorValue(data, decrease, delta) {
2017
+ function updateColorValue(data, decrease, delta, hdr) {
1992
2018
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
1993
2019
  if (!data.enable ||
1994
2020
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2001,7 +2027,7 @@
2001
2027
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2002
2028
  return;
2003
2029
  }
2004
- 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;
2030
+ 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;
2005
2031
  if (!decrease || data.status === AnimationStatus.increasing) {
2006
2032
  data.value += velocity;
2007
2033
  if (data.value > max) {
@@ -2028,14 +2054,14 @@
2028
2054
  }
2029
2055
  data.value = clamp(data.value, min, max);
2030
2056
  }
2031
- function updateColor(color, delta) {
2057
+ function updateColor(color, delta, hdr) {
2032
2058
  if (!color) {
2033
2059
  return;
2034
2060
  }
2035
2061
  const { h, s, l } = color;
2036
- updateColorValue(h, false, delta);
2037
- updateColorValue(s, true, delta);
2038
- updateColorValue(l, true, delta);
2062
+ updateColorValue(h, false, delta, hdr);
2063
+ updateColorValue(s, true, delta, hdr);
2064
+ updateColorValue(l, true, delta, hdr);
2039
2065
  }
2040
2066
  function alterHsl(color, type, value) {
2041
2067
  return {
@@ -2085,7 +2111,7 @@
2085
2111
  }
2086
2112
 
2087
2113
  async function loadBlendPlugin(engine) {
2088
- engine.checkVersion("4.2.0");
2114
+ engine.checkVersion("4.3.0");
2089
2115
  await engine.pluginManager.register(e => {
2090
2116
  e.pluginManager.addPlugin(new BlendPlugin());
2091
2117
  });
@@ -2122,7 +2148,7 @@
2122
2148
  }
2123
2149
 
2124
2150
  async function loadCircleShape(engine) {
2125
- engine.checkVersion("4.2.0");
2151
+ engine.checkVersion("4.3.0");
2126
2152
  await engine.pluginManager.register(e => {
2127
2153
  e.pluginManager.addShape(["circle"], () => {
2128
2154
  return Promise.resolve(new CircleDrawer());
@@ -2170,7 +2196,7 @@
2170
2196
  }
2171
2197
 
2172
2198
  async function loadHexColorPlugin(engine) {
2173
- engine.checkVersion("4.2.0");
2199
+ engine.checkVersion("4.3.0");
2174
2200
  await engine.pluginManager.register(e => {
2175
2201
  e.pluginManager.addColorManager("hex", new HexColorManager());
2176
2202
  });
@@ -2223,7 +2249,7 @@
2223
2249
  }
2224
2250
 
2225
2251
  async function loadHslColorPlugin(engine) {
2226
- engine.checkVersion("4.2.0");
2252
+ engine.checkVersion("4.3.0");
2227
2253
  await engine.pluginManager.register(e => {
2228
2254
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2229
2255
  });
@@ -2247,7 +2273,7 @@
2247
2273
  }
2248
2274
 
2249
2275
  async function loadMovePlugin(engine) {
2250
- engine.checkVersion("4.2.0");
2276
+ engine.checkVersion("4.3.0");
2251
2277
  await engine.pluginManager.register(e => {
2252
2278
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2253
2279
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2457,7 +2483,7 @@
2457
2483
  }
2458
2484
 
2459
2485
  async function loadOpacityUpdater(engine) {
2460
- engine.checkVersion("4.2.0");
2486
+ engine.checkVersion("4.3.0");
2461
2487
  await engine.pluginManager.register(e => {
2462
2488
  e.pluginManager.addParticleUpdater("opacity", container => {
2463
2489
  return Promise.resolve(new OpacityUpdater(container));
@@ -2802,7 +2828,7 @@
2802
2828
  }
2803
2829
 
2804
2830
  async function loadOutModesUpdater(engine) {
2805
- engine.checkVersion("4.2.0");
2831
+ engine.checkVersion("4.3.0");
2806
2832
  await engine.pluginManager.register(e => {
2807
2833
  e.pluginManager.addParticleUpdater("outModes", container => {
2808
2834
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2867,13 +2893,13 @@
2867
2893
  if (!this.isEnabled(particle)) {
2868
2894
  return;
2869
2895
  }
2870
- updateColor(particle.fillColor, delta);
2871
- updateColor(particle.strokeColor, delta);
2896
+ updateColor(particle.fillColor, delta, this.#container.hdr);
2897
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
2872
2898
  }
2873
2899
  }
2874
2900
 
2875
2901
  async function loadPaintUpdater(engine) {
2876
- engine.checkVersion("4.2.0");
2902
+ engine.checkVersion("4.3.0");
2877
2903
  await engine.pluginManager.register(e => {
2878
2904
  e.pluginManager.addParticleUpdater("paint", container => {
2879
2905
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2928,7 +2954,7 @@
2928
2954
  }
2929
2955
 
2930
2956
  async function loadRgbColorPlugin(engine) {
2931
- engine.checkVersion("4.2.0");
2957
+ engine.checkVersion("4.3.0");
2932
2958
  await engine.pluginManager.register(e => {
2933
2959
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2934
2960
  });
@@ -3013,7 +3039,7 @@
3013
3039
  }
3014
3040
 
3015
3041
  async function loadSizeUpdater(engine) {
3016
- engine.checkVersion("4.2.0");
3042
+ engine.checkVersion("4.3.0");
3017
3043
  await engine.pluginManager.register(e => {
3018
3044
  e.pluginManager.addParticleUpdater("size", container => {
3019
3045
  return Promise.resolve(new SizeUpdater(container));
@@ -3022,7 +3048,7 @@
3022
3048
  }
3023
3049
 
3024
3050
  async function loadBasic(engine) {
3025
- engine.checkVersion("4.2.0");
3051
+ engine.checkVersion("4.3.0");
3026
3052
  await engine.pluginManager.register(async (e) => {
3027
3053
  await Promise.all([
3028
3054
  loadBlendPlugin(e),
@@ -3262,7 +3288,7 @@
3262
3288
  })(EmitterClickMode || (EmitterClickMode = {}));
3263
3289
 
3264
3290
  async function loadEmittersPluginSimple(engine) {
3265
- engine.checkVersion("4.2.0");
3291
+ engine.checkVersion("4.3.0");
3266
3292
  await engine.pluginManager.register(async (e) => {
3267
3293
  const instancesManager = await getEmittersInstancesManager(e);
3268
3294
  await addEmittersShapesManager(e);
@@ -3350,7 +3376,7 @@
3350
3376
  }
3351
3377
 
3352
3378
  async function loadEmittersShapeSquare(engine) {
3353
- engine.checkVersion("4.2.0");
3379
+ engine.checkVersion("4.3.0");
3354
3380
  await engine.pluginManager.register((e) => {
3355
3381
  ensureEmittersPluginLoaded(e);
3356
3382
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -3494,7 +3520,7 @@
3494
3520
  }
3495
3521
 
3496
3522
  async function loadLifeUpdater(engine) {
3497
- engine.checkVersion("4.2.0");
3523
+ engine.checkVersion("4.3.0");
3498
3524
  await engine.pluginManager.register(e => {
3499
3525
  e.pluginManager.addParticleUpdater("life", container => {
3500
3526
  return Promise.resolve(new LifeUpdater(container));
@@ -3558,7 +3584,7 @@
3558
3584
  }
3559
3585
 
3560
3586
  async function loadTrailPlugin(engine) {
3561
- engine.checkVersion("4.2.0");
3587
+ engine.checkVersion("4.3.0");
3562
3588
  await engine.pluginManager.register(e => {
3563
3589
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
3564
3590
  });
@@ -3655,10 +3681,10 @@
3655
3681
  }
3656
3682
  }
3657
3683
  class RenderManager {
3684
+ #backgroundElement;
3685
+ #backgroundWarnings;
3658
3686
  #canvasClearPlugins;
3659
3687
  #canvasManager;
3660
- #canvasPaintPlugins;
3661
- #clearDrawPlugins;
3662
3688
  #colorPlugins;
3663
3689
  #container;
3664
3690
  #context;
@@ -3666,9 +3692,7 @@
3666
3692
  #drawParticlePlugins;
3667
3693
  #drawParticlesCleanupPlugins;
3668
3694
  #drawParticlesSetupPlugins;
3669
- #drawPlugins;
3670
- #drawSettingsCleanupPlugins;
3671
- #drawSettingsSetupPlugins;
3695
+ #layers;
3672
3696
  #pluginManager;
3673
3697
  #postDrawUpdaters;
3674
3698
  #preDrawUpdaters;
@@ -3680,18 +3704,25 @@
3680
3704
  this.#container = container;
3681
3705
  this.#canvasManager = canvasManager;
3682
3706
  this.#context = null;
3707
+ this.#backgroundElement = null;
3708
+ this.#backgroundWarnings = new Set();
3683
3709
  this.#preDrawUpdaters = [];
3684
3710
  this.#postDrawUpdaters = [];
3685
- this.#colorPlugins = [];
3686
3711
  this.#canvasClearPlugins = [];
3687
- this.#canvasPaintPlugins = [];
3688
- this.#clearDrawPlugins = [];
3712
+ this.#colorPlugins = [];
3689
3713
  this.#drawParticlePlugins = [];
3690
3714
  this.#drawParticlesCleanupPlugins = [];
3691
3715
  this.#drawParticlesSetupPlugins = [];
3692
- this.#drawPlugins = [];
3693
- this.#drawSettingsSetupPlugins = [];
3694
- this.#drawSettingsCleanupPlugins = [];
3716
+ this.#layers = {
3717
+ 0: [],
3718
+ 1: [],
3719
+ 2: [],
3720
+ 3: [],
3721
+ 4: [],
3722
+ 5: [],
3723
+ 6: [],
3724
+ 7: [],
3725
+ };
3695
3726
  }
3696
3727
  get settings() {
3697
3728
  return this.#contextSettings;
@@ -3705,32 +3736,38 @@
3705
3736
  });
3706
3737
  }
3707
3738
  clear() {
3708
- let pluginHandled = false;
3709
3739
  for (const plugin of this.#canvasClearPlugins) {
3710
- pluginHandled = plugin.canvasClear?.() ?? false;
3711
- if (pluginHandled) {
3712
- break;
3740
+ if (plugin.canvasClear?.() ?? false) {
3741
+ return;
3713
3742
  }
3714
3743
  }
3715
- if (pluginHandled) {
3716
- return;
3744
+ for (const layer of Object.values(DrawLayer)) {
3745
+ if (typeof layer === "number") {
3746
+ for (const plugin of this.#getLayerPlugins(layer)) {
3747
+ if (plugin.canvasClear?.() ?? false) {
3748
+ return;
3749
+ }
3750
+ }
3751
+ }
3717
3752
  }
3718
3753
  this.canvasClear();
3719
3754
  }
3720
3755
  destroy() {
3721
3756
  this.stop();
3757
+ this.#backgroundElement = null;
3758
+ this.#backgroundWarnings.clear();
3722
3759
  this.#preDrawUpdaters = [];
3723
3760
  this.#postDrawUpdaters = [];
3724
- this.#colorPlugins = [];
3725
3761
  this.#canvasClearPlugins = [];
3726
- this.#canvasPaintPlugins = [];
3727
- this.#clearDrawPlugins = [];
3762
+ this.#colorPlugins = [];
3728
3763
  this.#drawParticlePlugins = [];
3729
3764
  this.#drawParticlesCleanupPlugins = [];
3730
3765
  this.#drawParticlesSetupPlugins = [];
3731
- this.#drawPlugins = [];
3732
- this.#drawSettingsSetupPlugins = [];
3733
- this.#drawSettingsCleanupPlugins = [];
3766
+ for (const layer of Object.values(DrawLayer)) {
3767
+ if (typeof layer === "number") {
3768
+ this.#layers[layer] = [];
3769
+ }
3770
+ }
3734
3771
  }
3735
3772
  draw(cb) {
3736
3773
  const ctx = this.#context;
@@ -3787,21 +3824,40 @@
3787
3824
  });
3788
3825
  }
3789
3826
  drawParticles(delta) {
3790
- const { particles } = this.#container;
3827
+ const { particles, actualOptions } = this.#container;
3791
3828
  this.clear();
3792
3829
  particles.update(delta);
3793
3830
  this.draw(ctx => {
3794
- for (const plugin of this.#drawSettingsSetupPlugins) {
3831
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
3832
+ if (this.#backgroundElement) {
3833
+ try {
3834
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
3835
+ }
3836
+ catch {
3837
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
3838
+ }
3839
+ }
3840
+ const background = actualOptions.background;
3841
+ if (background.draw) {
3842
+ try {
3843
+ background.draw(ctx, delta);
3844
+ }
3845
+ catch {
3846
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
3847
+ }
3848
+ }
3849
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3850
+ plugin.canvasPaint?.();
3851
+ }
3852
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3795
3853
  plugin.drawSettingsSetup?.(ctx, delta);
3796
3854
  }
3797
- for (const plugin of this.#drawPlugins) {
3855
+ for (const plugin of this.#getLayerPlugins(DrawLayer.PluginContent)) {
3798
3856
  plugin.draw?.(ctx, delta);
3799
3857
  }
3800
3858
  particles.drawParticles(delta);
3801
- for (const plugin of this.#clearDrawPlugins) {
3859
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasCleanup)) {
3802
3860
  plugin.clearDraw?.(ctx, delta);
3803
- }
3804
- for (const plugin of this.#drawSettingsCleanupPlugins) {
3805
3861
  plugin.drawSettingsCleanup?.(ctx, delta);
3806
3862
  }
3807
3863
  });
@@ -3809,29 +3865,24 @@
3809
3865
  init() {
3810
3866
  this.initUpdaters();
3811
3867
  this.initPlugins();
3868
+ this.#resolveBackgroundElement();
3812
3869
  this.paint();
3813
3870
  }
3814
3871
  initPlugins() {
3815
- this.#colorPlugins = [];
3816
3872
  this.#canvasClearPlugins = [];
3817
- this.#canvasPaintPlugins = [];
3818
- this.#clearDrawPlugins = [];
3873
+ this.#colorPlugins = [];
3819
3874
  this.#drawParticlePlugins = [];
3820
3875
  this.#drawParticlesSetupPlugins = [];
3821
3876
  this.#drawParticlesCleanupPlugins = [];
3822
- this.#drawPlugins = [];
3823
- this.#drawSettingsSetupPlugins = [];
3824
- this.#drawSettingsCleanupPlugins = [];
3877
+ for (const layer of Object.values(DrawLayer)) {
3878
+ if (typeof layer === "number") {
3879
+ this.#layers[layer] = [];
3880
+ }
3881
+ }
3825
3882
  for (const plugin of this.#container.plugins) {
3826
3883
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3827
3884
  this.#colorPlugins.push(plugin);
3828
3885
  }
3829
- if (plugin.canvasClear) {
3830
- this.#canvasClearPlugins.push(plugin);
3831
- }
3832
- if (plugin.canvasPaint) {
3833
- this.#canvasPaintPlugins.push(plugin);
3834
- }
3835
3886
  if (plugin.drawParticle) {
3836
3887
  this.#drawParticlePlugins.push(plugin);
3837
3888
  }
@@ -3841,17 +3892,20 @@
3841
3892
  if (plugin.drawParticleCleanup) {
3842
3893
  this.#drawParticlesCleanupPlugins.push(plugin);
3843
3894
  }
3844
- if (plugin.draw) {
3845
- this.#drawPlugins.push(plugin);
3895
+ if (plugin.canvasClear) {
3896
+ this.#canvasClearPlugins.push(plugin);
3897
+ }
3898
+ if (plugin.canvasPaint) {
3899
+ this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
3846
3900
  }
3847
3901
  if (plugin.drawSettingsSetup) {
3848
- this.#drawSettingsSetupPlugins.push(plugin);
3902
+ this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
3849
3903
  }
3850
- if (plugin.drawSettingsCleanup) {
3851
- this.#drawSettingsCleanupPlugins.push(plugin);
3904
+ if (plugin.draw) {
3905
+ this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
3852
3906
  }
3853
- if (plugin.clearDraw) {
3854
- this.#clearDrawPlugins.push(plugin);
3907
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
3908
+ this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
3855
3909
  }
3856
3910
  }
3857
3911
  }
@@ -3869,7 +3923,7 @@
3869
3923
  }
3870
3924
  paint() {
3871
3925
  let handled = false;
3872
- for (const plugin of this.#canvasPaintPlugins) {
3926
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3873
3927
  handled = plugin.canvasPaint?.() ?? false;
3874
3928
  if (handled) {
3875
3929
  break;
@@ -4042,6 +4096,9 @@
4042
4096
  }
4043
4097
  drawer.beforeDraw(data);
4044
4098
  }
4099
+ #getLayerPlugins(layer) {
4100
+ return this.#layers[layer];
4101
+ }
4045
4102
  #getPluginParticleColors(particle) {
4046
4103
  let fColor, sColor;
4047
4104
  for (const plugin of this.#colorPlugins) {
@@ -4059,6 +4116,39 @@
4059
4116
  this.#reusablePluginColors[sColorIndex] = sColor;
4060
4117
  return this.#reusablePluginColors;
4061
4118
  }
4119
+ #resolveBackgroundElement() {
4120
+ const background = this.#container.actualOptions.background;
4121
+ this.#backgroundElement = null;
4122
+ if (!background.element) {
4123
+ return;
4124
+ }
4125
+ if (typeof background.element === "string") {
4126
+ if (typeof document !== "undefined") {
4127
+ const node = document.querySelector(background.element);
4128
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4129
+ this.#backgroundElement = node;
4130
+ }
4131
+ else if (node) {
4132
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
4133
+ }
4134
+ else {
4135
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
4136
+ }
4137
+ }
4138
+ }
4139
+ else if (background.element instanceof HTMLCanvasElement ||
4140
+ background.element instanceof OffscreenCanvas ||
4141
+ background.element instanceof HTMLVideoElement ||
4142
+ background.element instanceof HTMLImageElement) {
4143
+ this.#backgroundElement = background.element;
4144
+ }
4145
+ }
4146
+ #warnOnce(key, message) {
4147
+ if (!this.#backgroundWarnings.has(key)) {
4148
+ this.#backgroundWarnings.add(key);
4149
+ getLogger().warning(message);
4150
+ }
4151
+ }
4062
4152
  }
4063
4153
 
4064
4154
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4635,7 +4725,6 @@
4635
4725
  }
4636
4726
  class Particle {
4637
4727
  backColor;
4638
- bubble;
4639
4728
  destroyed;
4640
4729
  direction;
4641
4730
  effect;
@@ -4669,7 +4758,6 @@
4669
4758
  shapeData;
4670
4759
  sides;
4671
4760
  size;
4672
- slow;
4673
4761
  spawning;
4674
4762
  strokeColor;
4675
4763
  strokeOpacity;
@@ -4691,18 +4779,25 @@
4691
4779
  d: 1,
4692
4780
  };
4693
4781
  #container;
4782
+ #modifiers = [];
4694
4783
  #pluginManager;
4695
4784
  constructor(pluginManager, container) {
4696
4785
  this.#pluginManager = pluginManager;
4697
4786
  this.#container = container;
4698
4787
  }
4788
+ addModifier(modifier) {
4789
+ this.#modifiers.push(modifier);
4790
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
4791
+ }
4792
+ clearModifiers() {
4793
+ this.#modifiers.length = 0;
4794
+ }
4699
4795
  destroy(override) {
4700
4796
  if (this.unbreakable || this.destroyed) {
4701
4797
  return;
4702
4798
  }
4703
4799
  this.destroyed = true;
4704
- this.bubble.inRange = false;
4705
- this.slow.inRange = false;
4800
+ this.clearModifiers();
4706
4801
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
4707
4802
  shapeDrawer?.particleDestroy?.(this);
4708
4803
  for (const plugin of container.particleDestroyedPlugins) {
@@ -4724,13 +4819,16 @@
4724
4819
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
4725
4820
  }
4726
4821
  getFillColor() {
4727
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
4822
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
4728
4823
  }
4729
4824
  getMass() {
4730
4825
  return this.getRadius() ** squareExp * Math.PI * half;
4731
4826
  }
4827
+ getModifier(id) {
4828
+ return this.#modifiers.find(m => m.id === id);
4829
+ }
4732
4830
  getOpacity() {
4733
- 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;
4831
+ 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;
4734
4832
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4735
4833
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4736
4834
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -4743,7 +4841,7 @@
4743
4841
  return this.#cachedPosition;
4744
4842
  }
4745
4843
  getRadius() {
4746
- return this.bubble.radius ?? this.size.value;
4844
+ return this.#applyModifiers(this.size.value, m => m.radius);
4747
4845
  }
4748
4846
  getRotateData() {
4749
4847
  const angle = this.getAngle();
@@ -4752,7 +4850,7 @@
4752
4850
  return this.#cachedRotateData;
4753
4851
  }
4754
4852
  getStrokeColor() {
4755
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
4853
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
4756
4854
  }
4757
4855
  getTransformData(externalTransform) {
4758
4856
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -4772,13 +4870,6 @@
4772
4870
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
4773
4871
  container.retina.initParticle(this);
4774
4872
  runUpdaterPreInit(container.particleUpdaters, this);
4775
- this.bubble = {
4776
- inRange: false,
4777
- };
4778
- this.slow = {
4779
- inRange: false,
4780
- factor: 1,
4781
- };
4782
4873
  this.#initPosition(position);
4783
4874
  this.initialVelocity = this.#calculateVelocity();
4784
4875
  this.velocity = this.initialVelocity.copy();
@@ -4818,11 +4909,29 @@
4818
4909
  isVisible() {
4819
4910
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
4820
4911
  }
4912
+ removeModifier(id) {
4913
+ const idx = this.#modifiers.findIndex(m => m.id === id);
4914
+ if (idx >= defaultAngle) {
4915
+ this.#modifiers.splice(idx, identity$1);
4916
+ }
4917
+ }
4821
4918
  reset() {
4822
4919
  for (const updater of this.#container.particleUpdaters) {
4823
4920
  updater.reset?.(this);
4824
4921
  }
4825
4922
  }
4923
+ #applyModifiers(base, getter) {
4924
+ let value = base;
4925
+ for (const mod of this.#modifiers) {
4926
+ if (mod.enabled) {
4927
+ const override = getter(mod);
4928
+ if (override !== undefined) {
4929
+ value = override;
4930
+ }
4931
+ }
4932
+ }
4933
+ return value;
4934
+ }
4826
4935
  #calcPosition(position, zIndex) {
4827
4936
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
4828
4937
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -5924,6 +6033,7 @@
5924
6033
  });
5925
6034
 
5926
6035
  class BlendPluginInstance {
6036
+ layer = DrawLayer.CanvasSetup;
5927
6037
  #container;
5928
6038
  #defaultCompositeValue;
5929
6039
  constructor(container) {
@@ -6069,7 +6179,8 @@
6069
6179
  particle.lastPathTime -= pathDelay;
6070
6180
  }
6071
6181
  function getProximitySpeedFactor(particle) {
6072
- return particle.slow.inRange ? particle.slow.factor : identity$1;
6182
+ const mod = particle.getModifier("slow");
6183
+ return mod?.enabled ? (mod.speedFactor ?? identity$1) : identity$1;
6073
6184
  }
6074
6185
  function initSpin(container, particle) {
6075
6186
  const options = particle.options, spinOptions = options.move.spin;
@@ -6324,6 +6435,7 @@
6324
6435
 
6325
6436
  const minimumLength = 0;
6326
6437
  class TrailPluginInstance {
6438
+ layer = DrawLayer.PluginContent;
6327
6439
  #container;
6328
6440
  #pluginManager;
6329
6441
  #trailFill;