@tsparticles/preset-links 4.2.1 → 4.3.1

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.1 */
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) :
@@ -361,29 +361,27 @@
361
361
  }
362
362
  }
363
363
  else if (!isObject(destination) || Array.isArray(destination)) {
364
- destination = {};
364
+ destination = Object.create(null);
365
365
  }
366
- const sourceKeys = Object.keys(source), dangerousKeys = new Set(["__proto__", "constructor", "prototype"]), hasNested = sourceKeys.some(k => {
366
+ const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
367
367
  const v = source[k];
368
368
  return isObject(v) || Array.isArray(v);
369
369
  });
370
370
  if (!hasNested) {
371
371
  const sourceDict = source, destDict = destination;
372
372
  for (const key of sourceKeys) {
373
- if (dangerousKeys.has(key)) {
373
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
374
374
  continue;
375
375
  }
376
- if (key in sourceDict) {
377
- const v = sourceDict[key];
378
- if (v !== undefined) {
379
- destDict[key] = v;
380
- }
376
+ const v = sourceDict[key];
377
+ if (v !== undefined) {
378
+ destDict[key] = v;
381
379
  }
382
380
  }
383
381
  continue;
384
382
  }
385
383
  for (const key of sourceKeys) {
386
- if (dangerousKeys.has(key)) {
384
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
387
385
  continue;
388
386
  }
389
387
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -799,7 +797,7 @@
799
797
  return this.#domArray;
800
798
  }
801
799
  get version() {
802
- return "4.2.1";
800
+ return "4.3.1";
803
801
  }
804
802
  addEventListener(type, listener) {
805
803
  this.#eventDispatcher.addEventListener(type, listener);
@@ -1032,6 +1030,18 @@
1032
1030
  AnimationStatus["decreasing"] = "decreasing";
1033
1031
  })(AnimationStatus || (AnimationStatus = {}));
1034
1032
 
1033
+ var DrawLayer;
1034
+ (function (DrawLayer) {
1035
+ DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
1036
+ DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
1037
+ DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
1038
+ DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
1039
+ DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
1040
+ DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
1041
+ DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
1042
+ DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1043
+ })(DrawLayer || (DrawLayer = {}));
1044
+
1035
1045
  class OptionLoader {
1036
1046
  load(data) {
1037
1047
  if (isNull(data)) {
@@ -1185,6 +1195,8 @@
1185
1195
 
1186
1196
  class Background extends OptionLoader {
1187
1197
  color;
1198
+ draw;
1199
+ element;
1188
1200
  image = "";
1189
1201
  opacity = 1;
1190
1202
  position = "";
@@ -1199,6 +1211,8 @@
1199
1211
  if (data.color !== undefined) {
1200
1212
  this.color = OptionsColor.create(this.color, data.color);
1201
1213
  }
1214
+ loadProperty(this, "element", data.element);
1215
+ loadProperty(this, "draw", data.draw);
1202
1216
  loadProperty(this, "image", data.image);
1203
1217
  loadProperty(this, "position", data.position);
1204
1218
  loadProperty(this, "repeat", data.repeat);
@@ -1744,7 +1758,7 @@
1744
1758
  }
1745
1759
  }
1746
1760
 
1747
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
1761
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1748
1762
  function getCachedStyle(key, generator) {
1749
1763
  let cached = styleCache.get(key);
1750
1764
  if (!cached) {
@@ -1884,6 +1898,17 @@
1884
1898
  : 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));
1885
1899
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1886
1900
  }
1901
+ function hslToRgbFloat(hsl) {
1902
+ 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;
1903
+ if (s === sMin) {
1904
+ const grayscaleValue = lNormalized * rgbMax;
1905
+ return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1906
+ }
1907
+ const temp1 = lNormalized < half
1908
+ ? lNormalized * (sNormalizedOffset + sNormalized)
1909
+ : 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));
1910
+ return { r: red, g: green, b: blue };
1911
+ }
1887
1912
  function hslaToRgba(hsla) {
1888
1913
  const rgbResult = hslToRgb(hsla);
1889
1914
  return {
@@ -1893,8 +1918,9 @@
1893
1918
  r: rgbResult.r,
1894
1919
  };
1895
1920
  }
1896
- function getRandomRgbColor(min) {
1897
- const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1921
+ function getRandomRgbColor(min, hdr) {
1922
+ const fixedMin = defaultRgbMin;
1923
+ const fixedMax = rgbMax + identity, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1898
1924
  return {
1899
1925
  b: getRgbInRangeValue(),
1900
1926
  g: getRgbInRangeValue(),
@@ -1902,7 +1928,7 @@
1902
1928
  };
1903
1929
  }
1904
1930
  function getStyleFromRgb(color, hdr, opacity) {
1905
- const op = opacity ?? defaultOpacity$1, key = `rgb-${color.r.toFixed(rgbFixedPrecision)}-${color.g.toFixed(rgbFixedPrecision)}-${color.b.toFixed(rgbFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1931
+ 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()}`;
1906
1932
  return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
1907
1933
  }
1908
1934
  function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
@@ -1913,9 +1939,9 @@
1913
1939
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1914
1940
  }
1915
1941
  function getStyleFromHsl(color, hdr, opacity) {
1916
- const op = opacity ?? defaultOpacity$1, key = `hsl-${color.h.toFixed(hslFixedPrecision)}-${color.s.toFixed(hslFixedPrecision)}-${color.l.toFixed(hslFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1942
+ 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()}`;
1917
1943
  return getCachedStyle(key, () => hdr
1918
- ? getStyleFromRgb(hslToRgb(color), true, opacity)
1944
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
1919
1945
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1920
1946
  }
1921
1947
  function colorMix(color1, color2, size1, size2) {
@@ -2035,7 +2061,7 @@
2035
2061
  colorValue.velocity = defaultVelocity;
2036
2062
  }
2037
2063
  }
2038
- function updateColorValue(data, decrease, delta) {
2064
+ function updateColorValue(data, decrease, delta, hdr) {
2039
2065
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2040
2066
  if (!data.enable ||
2041
2067
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2048,7 +2074,7 @@
2048
2074
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2049
2075
  return;
2050
2076
  }
2051
- 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;
2077
+ 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;
2052
2078
  if (!decrease || data.status === AnimationStatus.increasing) {
2053
2079
  data.value += velocity;
2054
2080
  if (data.value > max) {
@@ -2075,14 +2101,14 @@
2075
2101
  }
2076
2102
  data.value = clamp(data.value, min, max);
2077
2103
  }
2078
- function updateColor(color, delta) {
2104
+ function updateColor(color, delta, hdr) {
2079
2105
  if (!color) {
2080
2106
  return;
2081
2107
  }
2082
2108
  const { h, s, l } = color;
2083
- updateColorValue(h, false, delta);
2084
- updateColorValue(s, true, delta);
2085
- updateColorValue(l, true, delta);
2109
+ updateColorValue(h, false, delta, hdr);
2110
+ updateColorValue(s, true, delta, hdr);
2111
+ updateColorValue(l, true, delta, hdr);
2086
2112
  }
2087
2113
  function alterHsl(color, type, value) {
2088
2114
  return {
@@ -2132,7 +2158,7 @@
2132
2158
  }
2133
2159
 
2134
2160
  async function loadBlendPlugin(engine) {
2135
- engine.checkVersion("4.2.1");
2161
+ engine.checkVersion("4.3.1");
2136
2162
  await engine.pluginManager.register(e => {
2137
2163
  e.pluginManager.addPlugin(new BlendPlugin());
2138
2164
  });
@@ -2169,7 +2195,7 @@
2169
2195
  }
2170
2196
 
2171
2197
  async function loadCircleShape(engine) {
2172
- engine.checkVersion("4.2.1");
2198
+ engine.checkVersion("4.3.1");
2173
2199
  await engine.pluginManager.register(e => {
2174
2200
  e.pluginManager.addShape(["circle"], () => {
2175
2201
  return Promise.resolve(new CircleDrawer());
@@ -2217,7 +2243,7 @@
2217
2243
  }
2218
2244
 
2219
2245
  async function loadHexColorPlugin(engine) {
2220
- engine.checkVersion("4.2.1");
2246
+ engine.checkVersion("4.3.1");
2221
2247
  await engine.pluginManager.register(e => {
2222
2248
  e.pluginManager.addColorManager("hex", new HexColorManager());
2223
2249
  });
@@ -2270,7 +2296,7 @@
2270
2296
  }
2271
2297
 
2272
2298
  async function loadHslColorPlugin(engine) {
2273
- engine.checkVersion("4.2.1");
2299
+ engine.checkVersion("4.3.1");
2274
2300
  await engine.pluginManager.register(e => {
2275
2301
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2276
2302
  });
@@ -2294,7 +2320,7 @@
2294
2320
  }
2295
2321
 
2296
2322
  async function loadMovePlugin(engine) {
2297
- engine.checkVersion("4.2.1");
2323
+ engine.checkVersion("4.3.1");
2298
2324
  await engine.pluginManager.register(e => {
2299
2325
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2300
2326
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2504,7 +2530,7 @@
2504
2530
  }
2505
2531
 
2506
2532
  async function loadOpacityUpdater(engine) {
2507
- engine.checkVersion("4.2.1");
2533
+ engine.checkVersion("4.3.1");
2508
2534
  await engine.pluginManager.register(e => {
2509
2535
  e.pluginManager.addParticleUpdater("opacity", container => {
2510
2536
  return Promise.resolve(new OpacityUpdater(container));
@@ -2849,7 +2875,7 @@
2849
2875
  }
2850
2876
 
2851
2877
  async function loadOutModesUpdater(engine) {
2852
- engine.checkVersion("4.2.1");
2878
+ engine.checkVersion("4.3.1");
2853
2879
  await engine.pluginManager.register(e => {
2854
2880
  e.pluginManager.addParticleUpdater("outModes", container => {
2855
2881
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2914,13 +2940,13 @@
2914
2940
  if (!this.isEnabled(particle)) {
2915
2941
  return;
2916
2942
  }
2917
- updateColor(particle.fillColor, delta);
2918
- updateColor(particle.strokeColor, delta);
2943
+ updateColor(particle.fillColor, delta, this.#container.hdr);
2944
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
2919
2945
  }
2920
2946
  }
2921
2947
 
2922
2948
  async function loadPaintUpdater(engine) {
2923
- engine.checkVersion("4.2.1");
2949
+ engine.checkVersion("4.3.1");
2924
2950
  await engine.pluginManager.register(e => {
2925
2951
  e.pluginManager.addParticleUpdater("paint", container => {
2926
2952
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2975,7 +3001,7 @@
2975
3001
  }
2976
3002
 
2977
3003
  async function loadRgbColorPlugin(engine) {
2978
- engine.checkVersion("4.2.1");
3004
+ engine.checkVersion("4.3.1");
2979
3005
  await engine.pluginManager.register(e => {
2980
3006
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2981
3007
  });
@@ -3060,7 +3086,7 @@
3060
3086
  }
3061
3087
 
3062
3088
  async function loadSizeUpdater(engine) {
3063
- engine.checkVersion("4.2.1");
3089
+ engine.checkVersion("4.3.1");
3064
3090
  await engine.pluginManager.register(e => {
3065
3091
  e.pluginManager.addParticleUpdater("size", container => {
3066
3092
  return Promise.resolve(new SizeUpdater(container));
@@ -3069,7 +3095,7 @@
3069
3095
  }
3070
3096
 
3071
3097
  async function loadBasic(engine) {
3072
- engine.checkVersion("4.2.1");
3098
+ engine.checkVersion("4.3.1");
3073
3099
  await engine.pluginManager.register(async (e) => {
3074
3100
  await Promise.all([
3075
3101
  loadBlendPlugin(e),
@@ -3270,7 +3296,7 @@
3270
3296
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3271
3297
 
3272
3298
  async function loadInteractivityPlugin(engine) {
3273
- engine.checkVersion("4.2.1");
3299
+ engine.checkVersion("4.3.1");
3274
3300
  await engine.pluginManager.register(e => {
3275
3301
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3276
3302
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3547,7 +3573,7 @@
3547
3573
  }
3548
3574
 
3549
3575
  async function loadParticlesLinksInteraction(engine) {
3550
- engine.checkVersion("4.2.1");
3576
+ engine.checkVersion("4.3.1");
3551
3577
  await engine.pluginManager.register((e) => {
3552
3578
  const pluginManager = e.pluginManager;
3553
3579
  ensureInteractivityPluginLoaded(e);
@@ -3615,10 +3641,10 @@
3615
3641
  }
3616
3642
  }
3617
3643
  class RenderManager {
3644
+ #backgroundElement;
3645
+ #backgroundWarnings;
3618
3646
  #canvasClearPlugins;
3619
3647
  #canvasManager;
3620
- #canvasPaintPlugins;
3621
- #clearDrawPlugins;
3622
3648
  #colorPlugins;
3623
3649
  #container;
3624
3650
  #context;
@@ -3626,9 +3652,7 @@
3626
3652
  #drawParticlePlugins;
3627
3653
  #drawParticlesCleanupPlugins;
3628
3654
  #drawParticlesSetupPlugins;
3629
- #drawPlugins;
3630
- #drawSettingsCleanupPlugins;
3631
- #drawSettingsSetupPlugins;
3655
+ #layers;
3632
3656
  #pluginManager;
3633
3657
  #postDrawUpdaters;
3634
3658
  #preDrawUpdaters;
@@ -3640,18 +3664,25 @@
3640
3664
  this.#container = container;
3641
3665
  this.#canvasManager = canvasManager;
3642
3666
  this.#context = null;
3667
+ this.#backgroundElement = null;
3668
+ this.#backgroundWarnings = new Set();
3643
3669
  this.#preDrawUpdaters = [];
3644
3670
  this.#postDrawUpdaters = [];
3645
- this.#colorPlugins = [];
3646
3671
  this.#canvasClearPlugins = [];
3647
- this.#canvasPaintPlugins = [];
3648
- this.#clearDrawPlugins = [];
3672
+ this.#colorPlugins = [];
3649
3673
  this.#drawParticlePlugins = [];
3650
3674
  this.#drawParticlesCleanupPlugins = [];
3651
3675
  this.#drawParticlesSetupPlugins = [];
3652
- this.#drawPlugins = [];
3653
- this.#drawSettingsSetupPlugins = [];
3654
- this.#drawSettingsCleanupPlugins = [];
3676
+ this.#layers = {
3677
+ 0: [],
3678
+ 1: [],
3679
+ 2: [],
3680
+ 3: [],
3681
+ 4: [],
3682
+ 5: [],
3683
+ 6: [],
3684
+ 7: [],
3685
+ };
3655
3686
  }
3656
3687
  get settings() {
3657
3688
  return this.#contextSettings;
@@ -3665,32 +3696,38 @@
3665
3696
  });
3666
3697
  }
3667
3698
  clear() {
3668
- let pluginHandled = false;
3669
3699
  for (const plugin of this.#canvasClearPlugins) {
3670
- pluginHandled = plugin.canvasClear?.() ?? false;
3671
- if (pluginHandled) {
3672
- break;
3700
+ if (plugin.canvasClear?.() ?? false) {
3701
+ return;
3673
3702
  }
3674
3703
  }
3675
- if (pluginHandled) {
3676
- return;
3704
+ for (const layer of Object.values(DrawLayer)) {
3705
+ if (typeof layer === "number") {
3706
+ for (const plugin of this.#getLayerPlugins(layer)) {
3707
+ if (plugin.canvasClear?.() ?? false) {
3708
+ return;
3709
+ }
3710
+ }
3711
+ }
3677
3712
  }
3678
3713
  this.canvasClear();
3679
3714
  }
3680
3715
  destroy() {
3681
3716
  this.stop();
3717
+ this.#backgroundElement = null;
3718
+ this.#backgroundWarnings.clear();
3682
3719
  this.#preDrawUpdaters = [];
3683
3720
  this.#postDrawUpdaters = [];
3684
- this.#colorPlugins = [];
3685
3721
  this.#canvasClearPlugins = [];
3686
- this.#canvasPaintPlugins = [];
3687
- this.#clearDrawPlugins = [];
3722
+ this.#colorPlugins = [];
3688
3723
  this.#drawParticlePlugins = [];
3689
3724
  this.#drawParticlesCleanupPlugins = [];
3690
3725
  this.#drawParticlesSetupPlugins = [];
3691
- this.#drawPlugins = [];
3692
- this.#drawSettingsSetupPlugins = [];
3693
- this.#drawSettingsCleanupPlugins = [];
3726
+ for (const layer of Object.values(DrawLayer)) {
3727
+ if (typeof layer === "number") {
3728
+ this.#layers[layer] = [];
3729
+ }
3730
+ }
3694
3731
  }
3695
3732
  draw(cb) {
3696
3733
  const ctx = this.#context;
@@ -3747,21 +3784,40 @@
3747
3784
  });
3748
3785
  }
3749
3786
  drawParticles(delta) {
3750
- const { particles } = this.#container;
3787
+ const { particles, actualOptions } = this.#container;
3751
3788
  this.clear();
3752
3789
  particles.update(delta);
3753
3790
  this.draw(ctx => {
3754
- for (const plugin of this.#drawSettingsSetupPlugins) {
3791
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
3792
+ if (this.#backgroundElement) {
3793
+ try {
3794
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
3795
+ }
3796
+ catch {
3797
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
3798
+ }
3799
+ }
3800
+ const background = actualOptions.background;
3801
+ if (background.draw) {
3802
+ try {
3803
+ background.draw(ctx, delta);
3804
+ }
3805
+ catch {
3806
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
3807
+ }
3808
+ }
3809
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3810
+ plugin.canvasPaint?.();
3811
+ }
3812
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3755
3813
  plugin.drawSettingsSetup?.(ctx, delta);
3756
3814
  }
3757
- for (const plugin of this.#drawPlugins) {
3815
+ for (const plugin of this.#getLayerPlugins(DrawLayer.PluginContent)) {
3758
3816
  plugin.draw?.(ctx, delta);
3759
3817
  }
3760
3818
  particles.drawParticles(delta);
3761
- for (const plugin of this.#clearDrawPlugins) {
3819
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasCleanup)) {
3762
3820
  plugin.clearDraw?.(ctx, delta);
3763
- }
3764
- for (const plugin of this.#drawSettingsCleanupPlugins) {
3765
3821
  plugin.drawSettingsCleanup?.(ctx, delta);
3766
3822
  }
3767
3823
  });
@@ -3769,29 +3825,24 @@
3769
3825
  init() {
3770
3826
  this.initUpdaters();
3771
3827
  this.initPlugins();
3828
+ this.#resolveBackgroundElement();
3772
3829
  this.paint();
3773
3830
  }
3774
3831
  initPlugins() {
3775
- this.#colorPlugins = [];
3776
3832
  this.#canvasClearPlugins = [];
3777
- this.#canvasPaintPlugins = [];
3778
- this.#clearDrawPlugins = [];
3833
+ this.#colorPlugins = [];
3779
3834
  this.#drawParticlePlugins = [];
3780
3835
  this.#drawParticlesSetupPlugins = [];
3781
3836
  this.#drawParticlesCleanupPlugins = [];
3782
- this.#drawPlugins = [];
3783
- this.#drawSettingsSetupPlugins = [];
3784
- this.#drawSettingsCleanupPlugins = [];
3837
+ for (const layer of Object.values(DrawLayer)) {
3838
+ if (typeof layer === "number") {
3839
+ this.#layers[layer] = [];
3840
+ }
3841
+ }
3785
3842
  for (const plugin of this.#container.plugins) {
3786
3843
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3787
3844
  this.#colorPlugins.push(plugin);
3788
3845
  }
3789
- if (plugin.canvasClear) {
3790
- this.#canvasClearPlugins.push(plugin);
3791
- }
3792
- if (plugin.canvasPaint) {
3793
- this.#canvasPaintPlugins.push(plugin);
3794
- }
3795
3846
  if (plugin.drawParticle) {
3796
3847
  this.#drawParticlePlugins.push(plugin);
3797
3848
  }
@@ -3801,17 +3852,20 @@
3801
3852
  if (plugin.drawParticleCleanup) {
3802
3853
  this.#drawParticlesCleanupPlugins.push(plugin);
3803
3854
  }
3804
- if (plugin.draw) {
3805
- this.#drawPlugins.push(plugin);
3855
+ if (plugin.canvasClear) {
3856
+ this.#canvasClearPlugins.push(plugin);
3857
+ }
3858
+ if (plugin.canvasPaint) {
3859
+ this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
3806
3860
  }
3807
3861
  if (plugin.drawSettingsSetup) {
3808
- this.#drawSettingsSetupPlugins.push(plugin);
3862
+ this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
3809
3863
  }
3810
- if (plugin.drawSettingsCleanup) {
3811
- this.#drawSettingsCleanupPlugins.push(plugin);
3864
+ if (plugin.draw) {
3865
+ this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
3812
3866
  }
3813
- if (plugin.clearDraw) {
3814
- this.#clearDrawPlugins.push(plugin);
3867
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
3868
+ this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
3815
3869
  }
3816
3870
  }
3817
3871
  }
@@ -3829,7 +3883,7 @@
3829
3883
  }
3830
3884
  paint() {
3831
3885
  let handled = false;
3832
- for (const plugin of this.#canvasPaintPlugins) {
3886
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3833
3887
  handled = plugin.canvasPaint?.() ?? false;
3834
3888
  if (handled) {
3835
3889
  break;
@@ -4002,6 +4056,9 @@
4002
4056
  }
4003
4057
  drawer.beforeDraw(data);
4004
4058
  }
4059
+ #getLayerPlugins(layer) {
4060
+ return this.#layers[layer];
4061
+ }
4005
4062
  #getPluginParticleColors(particle) {
4006
4063
  let fColor, sColor;
4007
4064
  for (const plugin of this.#colorPlugins) {
@@ -4019,6 +4076,39 @@
4019
4076
  this.#reusablePluginColors[sColorIndex] = sColor;
4020
4077
  return this.#reusablePluginColors;
4021
4078
  }
4079
+ #resolveBackgroundElement() {
4080
+ const background = this.#container.actualOptions.background;
4081
+ this.#backgroundElement = null;
4082
+ if (!background.element) {
4083
+ return;
4084
+ }
4085
+ if (typeof background.element === "string") {
4086
+ if (typeof document !== "undefined") {
4087
+ const node = document.querySelector(background.element);
4088
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4089
+ this.#backgroundElement = node;
4090
+ }
4091
+ else if (node) {
4092
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
4093
+ }
4094
+ else {
4095
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
4096
+ }
4097
+ }
4098
+ }
4099
+ else if (background.element instanceof HTMLCanvasElement ||
4100
+ background.element instanceof OffscreenCanvas ||
4101
+ background.element instanceof HTMLVideoElement ||
4102
+ background.element instanceof HTMLImageElement) {
4103
+ this.#backgroundElement = background.element;
4104
+ }
4105
+ }
4106
+ #warnOnce(key, message) {
4107
+ if (!this.#backgroundWarnings.has(key)) {
4108
+ this.#backgroundWarnings.add(key);
4109
+ getLogger().warning(message);
4110
+ }
4111
+ }
4022
4112
  }
4023
4113
 
4024
4114
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4595,7 +4685,6 @@
4595
4685
  }
4596
4686
  class Particle {
4597
4687
  backColor;
4598
- bubble;
4599
4688
  destroyed;
4600
4689
  direction;
4601
4690
  effect;
@@ -4629,7 +4718,6 @@
4629
4718
  shapeData;
4630
4719
  sides;
4631
4720
  size;
4632
- slow;
4633
4721
  spawning;
4634
4722
  strokeColor;
4635
4723
  strokeOpacity;
@@ -4651,18 +4739,25 @@
4651
4739
  d: 1,
4652
4740
  };
4653
4741
  #container;
4742
+ #modifiers = [];
4654
4743
  #pluginManager;
4655
4744
  constructor(pluginManager, container) {
4656
4745
  this.#pluginManager = pluginManager;
4657
4746
  this.#container = container;
4658
4747
  }
4748
+ addModifier(modifier) {
4749
+ this.#modifiers.push(modifier);
4750
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
4751
+ }
4752
+ clearModifiers() {
4753
+ this.#modifiers.length = 0;
4754
+ }
4659
4755
  destroy(override) {
4660
4756
  if (this.unbreakable || this.destroyed) {
4661
4757
  return;
4662
4758
  }
4663
4759
  this.destroyed = true;
4664
- this.bubble.inRange = false;
4665
- this.slow.inRange = false;
4760
+ this.clearModifiers();
4666
4761
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
4667
4762
  shapeDrawer?.particleDestroy?.(this);
4668
4763
  for (const plugin of container.particleDestroyedPlugins) {
@@ -4684,13 +4779,16 @@
4684
4779
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
4685
4780
  }
4686
4781
  getFillColor() {
4687
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
4782
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
4688
4783
  }
4689
4784
  getMass() {
4690
4785
  return this.getRadius() ** squareExp * Math.PI * half;
4691
4786
  }
4787
+ getModifier(id) {
4788
+ return this.#modifiers.find(m => m.id === id);
4789
+ }
4692
4790
  getOpacity() {
4693
- 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;
4791
+ 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;
4694
4792
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4695
4793
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4696
4794
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -4703,7 +4801,7 @@
4703
4801
  return this.#cachedPosition;
4704
4802
  }
4705
4803
  getRadius() {
4706
- return this.bubble.radius ?? this.size.value;
4804
+ return this.#applyModifiers(this.size.value, m => m.radius);
4707
4805
  }
4708
4806
  getRotateData() {
4709
4807
  const angle = this.getAngle();
@@ -4712,7 +4810,7 @@
4712
4810
  return this.#cachedRotateData;
4713
4811
  }
4714
4812
  getStrokeColor() {
4715
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
4813
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
4716
4814
  }
4717
4815
  getTransformData(externalTransform) {
4718
4816
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -4732,13 +4830,6 @@
4732
4830
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
4733
4831
  container.retina.initParticle(this);
4734
4832
  runUpdaterPreInit(container.particleUpdaters, this);
4735
- this.bubble = {
4736
- inRange: false,
4737
- };
4738
- this.slow = {
4739
- inRange: false,
4740
- factor: 1,
4741
- };
4742
4833
  this.#initPosition(position);
4743
4834
  this.initialVelocity = this.#calculateVelocity();
4744
4835
  this.velocity = this.initialVelocity.copy();
@@ -4778,11 +4869,29 @@
4778
4869
  isVisible() {
4779
4870
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
4780
4871
  }
4872
+ removeModifier(id) {
4873
+ const idx = this.#modifiers.findIndex(m => m.id === id);
4874
+ if (idx >= defaultAngle) {
4875
+ this.#modifiers.splice(idx, identity);
4876
+ }
4877
+ }
4781
4878
  reset() {
4782
4879
  for (const updater of this.#container.particleUpdaters) {
4783
4880
  updater.reset?.(this);
4784
4881
  }
4785
4882
  }
4883
+ #applyModifiers(base, getter) {
4884
+ let value = base;
4885
+ for (const mod of this.#modifiers) {
4886
+ if (mod.enabled) {
4887
+ const override = getter(mod);
4888
+ if (override !== undefined) {
4889
+ value = override;
4890
+ }
4891
+ }
4892
+ }
4893
+ return value;
4894
+ }
4786
4895
  #calcPosition(position, zIndex) {
4787
4896
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
4788
4897
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -5884,6 +5993,7 @@
5884
5993
  });
5885
5994
 
5886
5995
  class BlendPluginInstance {
5996
+ layer = DrawLayer.CanvasSetup;
5887
5997
  #container;
5888
5998
  #defaultCompositeValue;
5889
5999
  constructor(container) {
@@ -6029,7 +6139,8 @@
6029
6139
  particle.lastPathTime -= pathDelay;
6030
6140
  }
6031
6141
  function getProximitySpeedFactor(particle) {
6032
- return particle.slow.inRange ? particle.slow.factor : identity;
6142
+ const mod = particle.getModifier("slow");
6143
+ return mod?.enabled ? (mod.speedFactor ?? identity) : identity;
6033
6144
  }
6034
6145
  function initSpin(container, particle) {
6035
6146
  const options = particle.options, spinOptions = options.move.spin;