@tsparticles/preset-triangles 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) :
@@ -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.0";
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
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.0");
3551
3577
  await engine.pluginManager.register((e) => {
3552
3578
  const pluginManager = e.pluginManager;
3553
3579
  ensureInteractivityPluginLoaded(e);
@@ -3621,10 +3647,10 @@
3621
3647
  }
3622
3648
  }
3623
3649
  class RenderManager {
3650
+ #backgroundElement;
3651
+ #backgroundWarnings;
3624
3652
  #canvasClearPlugins;
3625
3653
  #canvasManager;
3626
- #canvasPaintPlugins;
3627
- #clearDrawPlugins;
3628
3654
  #colorPlugins;
3629
3655
  #container;
3630
3656
  #context;
@@ -3632,9 +3658,7 @@
3632
3658
  #drawParticlePlugins;
3633
3659
  #drawParticlesCleanupPlugins;
3634
3660
  #drawParticlesSetupPlugins;
3635
- #drawPlugins;
3636
- #drawSettingsCleanupPlugins;
3637
- #drawSettingsSetupPlugins;
3661
+ #layers;
3638
3662
  #pluginManager;
3639
3663
  #postDrawUpdaters;
3640
3664
  #preDrawUpdaters;
@@ -3646,18 +3670,25 @@
3646
3670
  this.#container = container;
3647
3671
  this.#canvasManager = canvasManager;
3648
3672
  this.#context = null;
3673
+ this.#backgroundElement = null;
3674
+ this.#backgroundWarnings = new Set();
3649
3675
  this.#preDrawUpdaters = [];
3650
3676
  this.#postDrawUpdaters = [];
3651
- this.#colorPlugins = [];
3652
3677
  this.#canvasClearPlugins = [];
3653
- this.#canvasPaintPlugins = [];
3654
- this.#clearDrawPlugins = [];
3678
+ this.#colorPlugins = [];
3655
3679
  this.#drawParticlePlugins = [];
3656
3680
  this.#drawParticlesCleanupPlugins = [];
3657
3681
  this.#drawParticlesSetupPlugins = [];
3658
- this.#drawPlugins = [];
3659
- this.#drawSettingsSetupPlugins = [];
3660
- this.#drawSettingsCleanupPlugins = [];
3682
+ this.#layers = {
3683
+ 0: [],
3684
+ 1: [],
3685
+ 2: [],
3686
+ 3: [],
3687
+ 4: [],
3688
+ 5: [],
3689
+ 6: [],
3690
+ 7: [],
3691
+ };
3661
3692
  }
3662
3693
  get settings() {
3663
3694
  return this.#contextSettings;
@@ -3671,32 +3702,38 @@
3671
3702
  });
3672
3703
  }
3673
3704
  clear() {
3674
- let pluginHandled = false;
3675
3705
  for (const plugin of this.#canvasClearPlugins) {
3676
- pluginHandled = plugin.canvasClear?.() ?? false;
3677
- if (pluginHandled) {
3678
- break;
3706
+ if (plugin.canvasClear?.() ?? false) {
3707
+ return;
3679
3708
  }
3680
3709
  }
3681
- if (pluginHandled) {
3682
- return;
3710
+ for (const layer of Object.values(DrawLayer)) {
3711
+ if (typeof layer === "number") {
3712
+ for (const plugin of this.#getLayerPlugins(layer)) {
3713
+ if (plugin.canvasClear?.() ?? false) {
3714
+ return;
3715
+ }
3716
+ }
3717
+ }
3683
3718
  }
3684
3719
  this.canvasClear();
3685
3720
  }
3686
3721
  destroy() {
3687
3722
  this.stop();
3723
+ this.#backgroundElement = null;
3724
+ this.#backgroundWarnings.clear();
3688
3725
  this.#preDrawUpdaters = [];
3689
3726
  this.#postDrawUpdaters = [];
3690
- this.#colorPlugins = [];
3691
3727
  this.#canvasClearPlugins = [];
3692
- this.#canvasPaintPlugins = [];
3693
- this.#clearDrawPlugins = [];
3728
+ this.#colorPlugins = [];
3694
3729
  this.#drawParticlePlugins = [];
3695
3730
  this.#drawParticlesCleanupPlugins = [];
3696
3731
  this.#drawParticlesSetupPlugins = [];
3697
- this.#drawPlugins = [];
3698
- this.#drawSettingsSetupPlugins = [];
3699
- this.#drawSettingsCleanupPlugins = [];
3732
+ for (const layer of Object.values(DrawLayer)) {
3733
+ if (typeof layer === "number") {
3734
+ this.#layers[layer] = [];
3735
+ }
3736
+ }
3700
3737
  }
3701
3738
  draw(cb) {
3702
3739
  const ctx = this.#context;
@@ -3753,21 +3790,40 @@
3753
3790
  });
3754
3791
  }
3755
3792
  drawParticles(delta) {
3756
- const { particles } = this.#container;
3793
+ const { particles, actualOptions } = this.#container;
3757
3794
  this.clear();
3758
3795
  particles.update(delta);
3759
3796
  this.draw(ctx => {
3760
- for (const plugin of this.#drawSettingsSetupPlugins) {
3797
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
3798
+ if (this.#backgroundElement) {
3799
+ try {
3800
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
3801
+ }
3802
+ catch {
3803
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
3804
+ }
3805
+ }
3806
+ const background = actualOptions.background;
3807
+ if (background.draw) {
3808
+ try {
3809
+ background.draw(ctx, delta);
3810
+ }
3811
+ catch {
3812
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
3813
+ }
3814
+ }
3815
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3816
+ plugin.canvasPaint?.();
3817
+ }
3818
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3761
3819
  plugin.drawSettingsSetup?.(ctx, delta);
3762
3820
  }
3763
- for (const plugin of this.#drawPlugins) {
3821
+ for (const plugin of this.#getLayerPlugins(DrawLayer.PluginContent)) {
3764
3822
  plugin.draw?.(ctx, delta);
3765
3823
  }
3766
3824
  particles.drawParticles(delta);
3767
- for (const plugin of this.#clearDrawPlugins) {
3825
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasCleanup)) {
3768
3826
  plugin.clearDraw?.(ctx, delta);
3769
- }
3770
- for (const plugin of this.#drawSettingsCleanupPlugins) {
3771
3827
  plugin.drawSettingsCleanup?.(ctx, delta);
3772
3828
  }
3773
3829
  });
@@ -3775,29 +3831,24 @@
3775
3831
  init() {
3776
3832
  this.initUpdaters();
3777
3833
  this.initPlugins();
3834
+ this.#resolveBackgroundElement();
3778
3835
  this.paint();
3779
3836
  }
3780
3837
  initPlugins() {
3781
- this.#colorPlugins = [];
3782
3838
  this.#canvasClearPlugins = [];
3783
- this.#canvasPaintPlugins = [];
3784
- this.#clearDrawPlugins = [];
3839
+ this.#colorPlugins = [];
3785
3840
  this.#drawParticlePlugins = [];
3786
3841
  this.#drawParticlesSetupPlugins = [];
3787
3842
  this.#drawParticlesCleanupPlugins = [];
3788
- this.#drawPlugins = [];
3789
- this.#drawSettingsSetupPlugins = [];
3790
- this.#drawSettingsCleanupPlugins = [];
3843
+ for (const layer of Object.values(DrawLayer)) {
3844
+ if (typeof layer === "number") {
3845
+ this.#layers[layer] = [];
3846
+ }
3847
+ }
3791
3848
  for (const plugin of this.#container.plugins) {
3792
3849
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3793
3850
  this.#colorPlugins.push(plugin);
3794
3851
  }
3795
- if (plugin.canvasClear) {
3796
- this.#canvasClearPlugins.push(plugin);
3797
- }
3798
- if (plugin.canvasPaint) {
3799
- this.#canvasPaintPlugins.push(plugin);
3800
- }
3801
3852
  if (plugin.drawParticle) {
3802
3853
  this.#drawParticlePlugins.push(plugin);
3803
3854
  }
@@ -3807,17 +3858,20 @@
3807
3858
  if (plugin.drawParticleCleanup) {
3808
3859
  this.#drawParticlesCleanupPlugins.push(plugin);
3809
3860
  }
3810
- if (plugin.draw) {
3811
- this.#drawPlugins.push(plugin);
3861
+ if (plugin.canvasClear) {
3862
+ this.#canvasClearPlugins.push(plugin);
3863
+ }
3864
+ if (plugin.canvasPaint) {
3865
+ this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
3812
3866
  }
3813
3867
  if (plugin.drawSettingsSetup) {
3814
- this.#drawSettingsSetupPlugins.push(plugin);
3868
+ this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
3815
3869
  }
3816
- if (plugin.drawSettingsCleanup) {
3817
- this.#drawSettingsCleanupPlugins.push(plugin);
3870
+ if (plugin.draw) {
3871
+ this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
3818
3872
  }
3819
- if (plugin.clearDraw) {
3820
- this.#clearDrawPlugins.push(plugin);
3873
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
3874
+ this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
3821
3875
  }
3822
3876
  }
3823
3877
  }
@@ -3835,7 +3889,7 @@
3835
3889
  }
3836
3890
  paint() {
3837
3891
  let handled = false;
3838
- for (const plugin of this.#canvasPaintPlugins) {
3892
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3839
3893
  handled = plugin.canvasPaint?.() ?? false;
3840
3894
  if (handled) {
3841
3895
  break;
@@ -4008,6 +4062,9 @@
4008
4062
  }
4009
4063
  drawer.beforeDraw(data);
4010
4064
  }
4065
+ #getLayerPlugins(layer) {
4066
+ return this.#layers[layer];
4067
+ }
4011
4068
  #getPluginParticleColors(particle) {
4012
4069
  let fColor, sColor;
4013
4070
  for (const plugin of this.#colorPlugins) {
@@ -4025,6 +4082,39 @@
4025
4082
  this.#reusablePluginColors[sColorIndex] = sColor;
4026
4083
  return this.#reusablePluginColors;
4027
4084
  }
4085
+ #resolveBackgroundElement() {
4086
+ const background = this.#container.actualOptions.background;
4087
+ this.#backgroundElement = null;
4088
+ if (!background.element) {
4089
+ return;
4090
+ }
4091
+ if (typeof background.element === "string") {
4092
+ if (typeof document !== "undefined") {
4093
+ const node = document.querySelector(background.element);
4094
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4095
+ this.#backgroundElement = node;
4096
+ }
4097
+ else if (node) {
4098
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
4099
+ }
4100
+ else {
4101
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
4102
+ }
4103
+ }
4104
+ }
4105
+ else if (background.element instanceof HTMLCanvasElement ||
4106
+ background.element instanceof OffscreenCanvas ||
4107
+ background.element instanceof HTMLVideoElement ||
4108
+ background.element instanceof HTMLImageElement) {
4109
+ this.#backgroundElement = background.element;
4110
+ }
4111
+ }
4112
+ #warnOnce(key, message) {
4113
+ if (!this.#backgroundWarnings.has(key)) {
4114
+ this.#backgroundWarnings.add(key);
4115
+ getLogger().warning(message);
4116
+ }
4117
+ }
4028
4118
  }
4029
4119
 
4030
4120
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4601,7 +4691,6 @@
4601
4691
  }
4602
4692
  class Particle {
4603
4693
  backColor;
4604
- bubble;
4605
4694
  destroyed;
4606
4695
  direction;
4607
4696
  effect;
@@ -4635,7 +4724,6 @@
4635
4724
  shapeData;
4636
4725
  sides;
4637
4726
  size;
4638
- slow;
4639
4727
  spawning;
4640
4728
  strokeColor;
4641
4729
  strokeOpacity;
@@ -4657,18 +4745,25 @@
4657
4745
  d: 1,
4658
4746
  };
4659
4747
  #container;
4748
+ #modifiers = [];
4660
4749
  #pluginManager;
4661
4750
  constructor(pluginManager, container) {
4662
4751
  this.#pluginManager = pluginManager;
4663
4752
  this.#container = container;
4664
4753
  }
4754
+ addModifier(modifier) {
4755
+ this.#modifiers.push(modifier);
4756
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
4757
+ }
4758
+ clearModifiers() {
4759
+ this.#modifiers.length = 0;
4760
+ }
4665
4761
  destroy(override) {
4666
4762
  if (this.unbreakable || this.destroyed) {
4667
4763
  return;
4668
4764
  }
4669
4765
  this.destroyed = true;
4670
- this.bubble.inRange = false;
4671
- this.slow.inRange = false;
4766
+ this.clearModifiers();
4672
4767
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
4673
4768
  shapeDrawer?.particleDestroy?.(this);
4674
4769
  for (const plugin of container.particleDestroyedPlugins) {
@@ -4690,13 +4785,16 @@
4690
4785
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
4691
4786
  }
4692
4787
  getFillColor() {
4693
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
4788
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
4694
4789
  }
4695
4790
  getMass() {
4696
4791
  return this.getRadius() ** squareExp * Math.PI * half;
4697
4792
  }
4793
+ getModifier(id) {
4794
+ return this.#modifiers.find(m => m.id === id);
4795
+ }
4698
4796
  getOpacity() {
4699
- 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;
4797
+ 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;
4700
4798
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4701
4799
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4702
4800
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -4709,7 +4807,7 @@
4709
4807
  return this.#cachedPosition;
4710
4808
  }
4711
4809
  getRadius() {
4712
- return this.bubble.radius ?? this.size.value;
4810
+ return this.#applyModifiers(this.size.value, m => m.radius);
4713
4811
  }
4714
4812
  getRotateData() {
4715
4813
  const angle = this.getAngle();
@@ -4718,7 +4816,7 @@
4718
4816
  return this.#cachedRotateData;
4719
4817
  }
4720
4818
  getStrokeColor() {
4721
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
4819
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
4722
4820
  }
4723
4821
  getTransformData(externalTransform) {
4724
4822
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -4738,13 +4836,6 @@
4738
4836
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
4739
4837
  container.retina.initParticle(this);
4740
4838
  runUpdaterPreInit(container.particleUpdaters, this);
4741
- this.bubble = {
4742
- inRange: false,
4743
- };
4744
- this.slow = {
4745
- inRange: false,
4746
- factor: 1,
4747
- };
4748
4839
  this.#initPosition(position);
4749
4840
  this.initialVelocity = this.#calculateVelocity();
4750
4841
  this.velocity = this.initialVelocity.copy();
@@ -4784,11 +4875,29 @@
4784
4875
  isVisible() {
4785
4876
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
4786
4877
  }
4878
+ removeModifier(id) {
4879
+ const idx = this.#modifiers.findIndex(m => m.id === id);
4880
+ if (idx >= defaultAngle) {
4881
+ this.#modifiers.splice(idx, identity);
4882
+ }
4883
+ }
4787
4884
  reset() {
4788
4885
  for (const updater of this.#container.particleUpdaters) {
4789
4886
  updater.reset?.(this);
4790
4887
  }
4791
4888
  }
4889
+ #applyModifiers(base, getter) {
4890
+ let value = base;
4891
+ for (const mod of this.#modifiers) {
4892
+ if (mod.enabled) {
4893
+ const override = getter(mod);
4894
+ if (override !== undefined) {
4895
+ value = override;
4896
+ }
4897
+ }
4898
+ }
4899
+ return value;
4900
+ }
4792
4901
  #calcPosition(position, zIndex) {
4793
4902
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
4794
4903
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -5890,6 +5999,7 @@
5890
5999
  });
5891
6000
 
5892
6001
  class BlendPluginInstance {
6002
+ layer = DrawLayer.CanvasSetup;
5893
6003
  #container;
5894
6004
  #defaultCompositeValue;
5895
6005
  constructor(container) {
@@ -6035,7 +6145,8 @@
6035
6145
  particle.lastPathTime -= pathDelay;
6036
6146
  }
6037
6147
  function getProximitySpeedFactor(particle) {
6038
- return particle.slow.inRange ? particle.slow.factor : identity;
6148
+ const mod = particle.getModifier("slow");
6149
+ return mod?.enabled ? (mod.speedFactor ?? identity) : identity;
6039
6150
  }
6040
6151
  function initSpin(container, particle) {
6041
6152
  const options = particle.options, spinOptions = options.move.spin;