@tsparticles/preset-big-circles 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) :
@@ -358,29 +358,27 @@
358
358
  }
359
359
  }
360
360
  else if (!isObject(destination) || Array.isArray(destination)) {
361
- destination = {};
361
+ destination = Object.create(null);
362
362
  }
363
- const sourceKeys = Object.keys(source), dangerousKeys = new Set(["__proto__", "constructor", "prototype"]), hasNested = sourceKeys.some(k => {
363
+ const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
364
364
  const v = source[k];
365
365
  return isObject(v) || Array.isArray(v);
366
366
  });
367
367
  if (!hasNested) {
368
368
  const sourceDict = source, destDict = destination;
369
369
  for (const key of sourceKeys) {
370
- if (dangerousKeys.has(key)) {
370
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
371
371
  continue;
372
372
  }
373
- if (key in sourceDict) {
374
- const v = sourceDict[key];
375
- if (v !== undefined) {
376
- destDict[key] = v;
377
- }
373
+ const v = sourceDict[key];
374
+ if (v !== undefined) {
375
+ destDict[key] = v;
378
376
  }
379
377
  }
380
378
  continue;
381
379
  }
382
380
  for (const key of sourceKeys) {
383
- if (dangerousKeys.has(key)) {
381
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
384
382
  continue;
385
383
  }
386
384
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -796,7 +794,7 @@
796
794
  return this.#domArray;
797
795
  }
798
796
  get version() {
799
- return "4.2.1";
797
+ return "4.3.0";
800
798
  }
801
799
  addEventListener(type, listener) {
802
800
  this.#eventDispatcher.addEventListener(type, listener);
@@ -1029,6 +1027,18 @@
1029
1027
  AnimationStatus["decreasing"] = "decreasing";
1030
1028
  })(AnimationStatus || (AnimationStatus = {}));
1031
1029
 
1030
+ var DrawLayer;
1031
+ (function (DrawLayer) {
1032
+ DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
1033
+ DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
1034
+ DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
1035
+ DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
1036
+ DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
1037
+ DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
1038
+ DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
1039
+ DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1040
+ })(DrawLayer || (DrawLayer = {}));
1041
+
1032
1042
  class OptionLoader {
1033
1043
  load(data) {
1034
1044
  if (isNull(data)) {
@@ -1182,6 +1192,8 @@
1182
1192
 
1183
1193
  class Background extends OptionLoader {
1184
1194
  color;
1195
+ draw;
1196
+ element;
1185
1197
  image = "";
1186
1198
  opacity = 1;
1187
1199
  position = "";
@@ -1196,6 +1208,8 @@
1196
1208
  if (data.color !== undefined) {
1197
1209
  this.color = OptionsColor.create(this.color, data.color);
1198
1210
  }
1211
+ loadProperty(this, "element", data.element);
1212
+ loadProperty(this, "draw", data.draw);
1199
1213
  loadProperty(this, "image", data.image);
1200
1214
  loadProperty(this, "position", data.position);
1201
1215
  loadProperty(this, "repeat", data.repeat);
@@ -1741,7 +1755,7 @@
1741
1755
  }
1742
1756
  }
1743
1757
 
1744
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
1758
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1745
1759
  function getCachedStyle(key, generator) {
1746
1760
  let cached = styleCache.get(key);
1747
1761
  if (!cached) {
@@ -1881,6 +1895,17 @@
1881
1895
  : 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));
1882
1896
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1883
1897
  }
1898
+ function hslToRgbFloat(hsl) {
1899
+ 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;
1900
+ if (s === sMin) {
1901
+ const grayscaleValue = lNormalized * rgbMax;
1902
+ return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1903
+ }
1904
+ const temp1 = lNormalized < half
1905
+ ? lNormalized * (sNormalizedOffset + sNormalized)
1906
+ : 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));
1907
+ return { r: red, g: green, b: blue };
1908
+ }
1884
1909
  function hslaToRgba(hsla) {
1885
1910
  const rgbResult = hslToRgb(hsla);
1886
1911
  return {
@@ -1890,8 +1915,9 @@
1890
1915
  r: rgbResult.r,
1891
1916
  };
1892
1917
  }
1893
- function getRandomRgbColor(min) {
1894
- const fixedMin = defaultRgbMin, fixedMax = rgbMax + identity, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1918
+ function getRandomRgbColor(min, hdr) {
1919
+ const fixedMin = defaultRgbMin;
1920
+ const fixedMax = rgbMax + identity, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1895
1921
  return {
1896
1922
  b: getRgbInRangeValue(),
1897
1923
  g: getRgbInRangeValue(),
@@ -1899,7 +1925,7 @@
1899
1925
  };
1900
1926
  }
1901
1927
  function getStyleFromRgb(color, hdr, opacity) {
1902
- const op = opacity ?? defaultOpacity$1, key = `rgb-${color.r.toFixed(rgbFixedPrecision)}-${color.g.toFixed(rgbFixedPrecision)}-${color.b.toFixed(rgbFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1928
+ 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()}`;
1903
1929
  return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
1904
1930
  }
1905
1931
  function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
@@ -1910,9 +1936,9 @@
1910
1936
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1911
1937
  }
1912
1938
  function getStyleFromHsl(color, hdr, opacity) {
1913
- const op = opacity ?? defaultOpacity$1, key = `hsl-${color.h.toFixed(hslFixedPrecision)}-${color.s.toFixed(hslFixedPrecision)}-${color.l.toFixed(hslFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1939
+ 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()}`;
1914
1940
  return getCachedStyle(key, () => hdr
1915
- ? getStyleFromRgb(hslToRgb(color), true, opacity)
1941
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
1916
1942
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1917
1943
  }
1918
1944
  function getHslFromAnimation(animation) {
@@ -1975,7 +2001,7 @@
1975
2001
  colorValue.velocity = defaultVelocity;
1976
2002
  }
1977
2003
  }
1978
- function updateColorValue(data, decrease, delta) {
2004
+ function updateColorValue(data, decrease, delta, hdr) {
1979
2005
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
1980
2006
  if (!data.enable ||
1981
2007
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -1988,7 +2014,7 @@
1988
2014
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
1989
2015
  return;
1990
2016
  }
1991
- 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;
2017
+ 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;
1992
2018
  if (!decrease || data.status === AnimationStatus.increasing) {
1993
2019
  data.value += velocity;
1994
2020
  if (data.value > max) {
@@ -2015,14 +2041,14 @@
2015
2041
  }
2016
2042
  data.value = clamp(data.value, min, max);
2017
2043
  }
2018
- function updateColor(color, delta) {
2044
+ function updateColor(color, delta, hdr) {
2019
2045
  if (!color) {
2020
2046
  return;
2021
2047
  }
2022
2048
  const { h, s, l } = color;
2023
- updateColorValue(h, false, delta);
2024
- updateColorValue(s, true, delta);
2025
- updateColorValue(l, true, delta);
2049
+ updateColorValue(h, false, delta, hdr);
2050
+ updateColorValue(s, true, delta, hdr);
2051
+ updateColorValue(l, true, delta, hdr);
2026
2052
  }
2027
2053
  function alterHsl(color, type, value) {
2028
2054
  return {
@@ -2072,7 +2098,7 @@
2072
2098
  }
2073
2099
 
2074
2100
  async function loadBlendPlugin(engine) {
2075
- engine.checkVersion("4.2.1");
2101
+ engine.checkVersion("4.3.0");
2076
2102
  await engine.pluginManager.register(e => {
2077
2103
  e.pluginManager.addPlugin(new BlendPlugin());
2078
2104
  });
@@ -2109,7 +2135,7 @@
2109
2135
  }
2110
2136
 
2111
2137
  async function loadCircleShape(engine) {
2112
- engine.checkVersion("4.2.1");
2138
+ engine.checkVersion("4.3.0");
2113
2139
  await engine.pluginManager.register(e => {
2114
2140
  e.pluginManager.addShape(["circle"], () => {
2115
2141
  return Promise.resolve(new CircleDrawer());
@@ -2157,7 +2183,7 @@
2157
2183
  }
2158
2184
 
2159
2185
  async function loadHexColorPlugin(engine) {
2160
- engine.checkVersion("4.2.1");
2186
+ engine.checkVersion("4.3.0");
2161
2187
  await engine.pluginManager.register(e => {
2162
2188
  e.pluginManager.addColorManager("hex", new HexColorManager());
2163
2189
  });
@@ -2210,7 +2236,7 @@
2210
2236
  }
2211
2237
 
2212
2238
  async function loadHslColorPlugin(engine) {
2213
- engine.checkVersion("4.2.1");
2239
+ engine.checkVersion("4.3.0");
2214
2240
  await engine.pluginManager.register(e => {
2215
2241
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2216
2242
  });
@@ -2234,7 +2260,7 @@
2234
2260
  }
2235
2261
 
2236
2262
  async function loadMovePlugin(engine) {
2237
- engine.checkVersion("4.2.1");
2263
+ engine.checkVersion("4.3.0");
2238
2264
  await engine.pluginManager.register(e => {
2239
2265
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2240
2266
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2444,7 +2470,7 @@
2444
2470
  }
2445
2471
 
2446
2472
  async function loadOpacityUpdater(engine) {
2447
- engine.checkVersion("4.2.1");
2473
+ engine.checkVersion("4.3.0");
2448
2474
  await engine.pluginManager.register(e => {
2449
2475
  e.pluginManager.addParticleUpdater("opacity", container => {
2450
2476
  return Promise.resolve(new OpacityUpdater(container));
@@ -2789,7 +2815,7 @@
2789
2815
  }
2790
2816
 
2791
2817
  async function loadOutModesUpdater(engine) {
2792
- engine.checkVersion("4.2.1");
2818
+ engine.checkVersion("4.3.0");
2793
2819
  await engine.pluginManager.register(e => {
2794
2820
  e.pluginManager.addParticleUpdater("outModes", container => {
2795
2821
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2854,13 +2880,13 @@
2854
2880
  if (!this.isEnabled(particle)) {
2855
2881
  return;
2856
2882
  }
2857
- updateColor(particle.fillColor, delta);
2858
- updateColor(particle.strokeColor, delta);
2883
+ updateColor(particle.fillColor, delta, this.#container.hdr);
2884
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
2859
2885
  }
2860
2886
  }
2861
2887
 
2862
2888
  async function loadPaintUpdater(engine) {
2863
- engine.checkVersion("4.2.1");
2889
+ engine.checkVersion("4.3.0");
2864
2890
  await engine.pluginManager.register(e => {
2865
2891
  e.pluginManager.addParticleUpdater("paint", container => {
2866
2892
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2915,7 +2941,7 @@
2915
2941
  }
2916
2942
 
2917
2943
  async function loadRgbColorPlugin(engine) {
2918
- engine.checkVersion("4.2.1");
2944
+ engine.checkVersion("4.3.0");
2919
2945
  await engine.pluginManager.register(e => {
2920
2946
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2921
2947
  });
@@ -3000,7 +3026,7 @@
3000
3026
  }
3001
3027
 
3002
3028
  async function loadSizeUpdater(engine) {
3003
- engine.checkVersion("4.2.1");
3029
+ engine.checkVersion("4.3.0");
3004
3030
  await engine.pluginManager.register(e => {
3005
3031
  e.pluginManager.addParticleUpdater("size", container => {
3006
3032
  return Promise.resolve(new SizeUpdater(container));
@@ -3009,7 +3035,7 @@
3009
3035
  }
3010
3036
 
3011
3037
  async function loadBasic(engine) {
3012
- engine.checkVersion("4.2.1");
3038
+ engine.checkVersion("4.3.0");
3013
3039
  await engine.pluginManager.register(async (e) => {
3014
3040
  await Promise.all([
3015
3041
  loadBlendPlugin(e),
@@ -3131,10 +3157,10 @@
3131
3157
  }
3132
3158
  }
3133
3159
  class RenderManager {
3160
+ #backgroundElement;
3161
+ #backgroundWarnings;
3134
3162
  #canvasClearPlugins;
3135
3163
  #canvasManager;
3136
- #canvasPaintPlugins;
3137
- #clearDrawPlugins;
3138
3164
  #colorPlugins;
3139
3165
  #container;
3140
3166
  #context;
@@ -3142,9 +3168,7 @@
3142
3168
  #drawParticlePlugins;
3143
3169
  #drawParticlesCleanupPlugins;
3144
3170
  #drawParticlesSetupPlugins;
3145
- #drawPlugins;
3146
- #drawSettingsCleanupPlugins;
3147
- #drawSettingsSetupPlugins;
3171
+ #layers;
3148
3172
  #pluginManager;
3149
3173
  #postDrawUpdaters;
3150
3174
  #preDrawUpdaters;
@@ -3156,18 +3180,25 @@
3156
3180
  this.#container = container;
3157
3181
  this.#canvasManager = canvasManager;
3158
3182
  this.#context = null;
3183
+ this.#backgroundElement = null;
3184
+ this.#backgroundWarnings = new Set();
3159
3185
  this.#preDrawUpdaters = [];
3160
3186
  this.#postDrawUpdaters = [];
3161
- this.#colorPlugins = [];
3162
3187
  this.#canvasClearPlugins = [];
3163
- this.#canvasPaintPlugins = [];
3164
- this.#clearDrawPlugins = [];
3188
+ this.#colorPlugins = [];
3165
3189
  this.#drawParticlePlugins = [];
3166
3190
  this.#drawParticlesCleanupPlugins = [];
3167
3191
  this.#drawParticlesSetupPlugins = [];
3168
- this.#drawPlugins = [];
3169
- this.#drawSettingsSetupPlugins = [];
3170
- this.#drawSettingsCleanupPlugins = [];
3192
+ this.#layers = {
3193
+ 0: [],
3194
+ 1: [],
3195
+ 2: [],
3196
+ 3: [],
3197
+ 4: [],
3198
+ 5: [],
3199
+ 6: [],
3200
+ 7: [],
3201
+ };
3171
3202
  }
3172
3203
  get settings() {
3173
3204
  return this.#contextSettings;
@@ -3181,32 +3212,38 @@
3181
3212
  });
3182
3213
  }
3183
3214
  clear() {
3184
- let pluginHandled = false;
3185
3215
  for (const plugin of this.#canvasClearPlugins) {
3186
- pluginHandled = plugin.canvasClear?.() ?? false;
3187
- if (pluginHandled) {
3188
- break;
3216
+ if (plugin.canvasClear?.() ?? false) {
3217
+ return;
3189
3218
  }
3190
3219
  }
3191
- if (pluginHandled) {
3192
- return;
3220
+ for (const layer of Object.values(DrawLayer)) {
3221
+ if (typeof layer === "number") {
3222
+ for (const plugin of this.#getLayerPlugins(layer)) {
3223
+ if (plugin.canvasClear?.() ?? false) {
3224
+ return;
3225
+ }
3226
+ }
3227
+ }
3193
3228
  }
3194
3229
  this.canvasClear();
3195
3230
  }
3196
3231
  destroy() {
3197
3232
  this.stop();
3233
+ this.#backgroundElement = null;
3234
+ this.#backgroundWarnings.clear();
3198
3235
  this.#preDrawUpdaters = [];
3199
3236
  this.#postDrawUpdaters = [];
3200
- this.#colorPlugins = [];
3201
3237
  this.#canvasClearPlugins = [];
3202
- this.#canvasPaintPlugins = [];
3203
- this.#clearDrawPlugins = [];
3238
+ this.#colorPlugins = [];
3204
3239
  this.#drawParticlePlugins = [];
3205
3240
  this.#drawParticlesCleanupPlugins = [];
3206
3241
  this.#drawParticlesSetupPlugins = [];
3207
- this.#drawPlugins = [];
3208
- this.#drawSettingsSetupPlugins = [];
3209
- this.#drawSettingsCleanupPlugins = [];
3242
+ for (const layer of Object.values(DrawLayer)) {
3243
+ if (typeof layer === "number") {
3244
+ this.#layers[layer] = [];
3245
+ }
3246
+ }
3210
3247
  }
3211
3248
  draw(cb) {
3212
3249
  const ctx = this.#context;
@@ -3263,21 +3300,40 @@
3263
3300
  });
3264
3301
  }
3265
3302
  drawParticles(delta) {
3266
- const { particles } = this.#container;
3303
+ const { particles, actualOptions } = this.#container;
3267
3304
  this.clear();
3268
3305
  particles.update(delta);
3269
3306
  this.draw(ctx => {
3270
- for (const plugin of this.#drawSettingsSetupPlugins) {
3307
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
3308
+ if (this.#backgroundElement) {
3309
+ try {
3310
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
3311
+ }
3312
+ catch {
3313
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
3314
+ }
3315
+ }
3316
+ const background = actualOptions.background;
3317
+ if (background.draw) {
3318
+ try {
3319
+ background.draw(ctx, delta);
3320
+ }
3321
+ catch {
3322
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
3323
+ }
3324
+ }
3325
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3326
+ plugin.canvasPaint?.();
3327
+ }
3328
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3271
3329
  plugin.drawSettingsSetup?.(ctx, delta);
3272
3330
  }
3273
- for (const plugin of this.#drawPlugins) {
3331
+ for (const plugin of this.#getLayerPlugins(DrawLayer.PluginContent)) {
3274
3332
  plugin.draw?.(ctx, delta);
3275
3333
  }
3276
3334
  particles.drawParticles(delta);
3277
- for (const plugin of this.#clearDrawPlugins) {
3335
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasCleanup)) {
3278
3336
  plugin.clearDraw?.(ctx, delta);
3279
- }
3280
- for (const plugin of this.#drawSettingsCleanupPlugins) {
3281
3337
  plugin.drawSettingsCleanup?.(ctx, delta);
3282
3338
  }
3283
3339
  });
@@ -3285,29 +3341,24 @@
3285
3341
  init() {
3286
3342
  this.initUpdaters();
3287
3343
  this.initPlugins();
3344
+ this.#resolveBackgroundElement();
3288
3345
  this.paint();
3289
3346
  }
3290
3347
  initPlugins() {
3291
- this.#colorPlugins = [];
3292
3348
  this.#canvasClearPlugins = [];
3293
- this.#canvasPaintPlugins = [];
3294
- this.#clearDrawPlugins = [];
3349
+ this.#colorPlugins = [];
3295
3350
  this.#drawParticlePlugins = [];
3296
3351
  this.#drawParticlesSetupPlugins = [];
3297
3352
  this.#drawParticlesCleanupPlugins = [];
3298
- this.#drawPlugins = [];
3299
- this.#drawSettingsSetupPlugins = [];
3300
- this.#drawSettingsCleanupPlugins = [];
3353
+ for (const layer of Object.values(DrawLayer)) {
3354
+ if (typeof layer === "number") {
3355
+ this.#layers[layer] = [];
3356
+ }
3357
+ }
3301
3358
  for (const plugin of this.#container.plugins) {
3302
3359
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3303
3360
  this.#colorPlugins.push(plugin);
3304
3361
  }
3305
- if (plugin.canvasClear) {
3306
- this.#canvasClearPlugins.push(plugin);
3307
- }
3308
- if (plugin.canvasPaint) {
3309
- this.#canvasPaintPlugins.push(plugin);
3310
- }
3311
3362
  if (plugin.drawParticle) {
3312
3363
  this.#drawParticlePlugins.push(plugin);
3313
3364
  }
@@ -3317,17 +3368,20 @@
3317
3368
  if (plugin.drawParticleCleanup) {
3318
3369
  this.#drawParticlesCleanupPlugins.push(plugin);
3319
3370
  }
3320
- if (plugin.draw) {
3321
- this.#drawPlugins.push(plugin);
3371
+ if (plugin.canvasClear) {
3372
+ this.#canvasClearPlugins.push(plugin);
3373
+ }
3374
+ if (plugin.canvasPaint) {
3375
+ this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
3322
3376
  }
3323
3377
  if (plugin.drawSettingsSetup) {
3324
- this.#drawSettingsSetupPlugins.push(plugin);
3378
+ this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
3325
3379
  }
3326
- if (plugin.drawSettingsCleanup) {
3327
- this.#drawSettingsCleanupPlugins.push(plugin);
3380
+ if (plugin.draw) {
3381
+ this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
3328
3382
  }
3329
- if (plugin.clearDraw) {
3330
- this.#clearDrawPlugins.push(plugin);
3383
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
3384
+ this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
3331
3385
  }
3332
3386
  }
3333
3387
  }
@@ -3345,7 +3399,7 @@
3345
3399
  }
3346
3400
  paint() {
3347
3401
  let handled = false;
3348
- for (const plugin of this.#canvasPaintPlugins) {
3402
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3349
3403
  handled = plugin.canvasPaint?.() ?? false;
3350
3404
  if (handled) {
3351
3405
  break;
@@ -3518,6 +3572,9 @@
3518
3572
  }
3519
3573
  drawer.beforeDraw(data);
3520
3574
  }
3575
+ #getLayerPlugins(layer) {
3576
+ return this.#layers[layer];
3577
+ }
3521
3578
  #getPluginParticleColors(particle) {
3522
3579
  let fColor, sColor;
3523
3580
  for (const plugin of this.#colorPlugins) {
@@ -3535,6 +3592,39 @@
3535
3592
  this.#reusablePluginColors[sColorIndex] = sColor;
3536
3593
  return this.#reusablePluginColors;
3537
3594
  }
3595
+ #resolveBackgroundElement() {
3596
+ const background = this.#container.actualOptions.background;
3597
+ this.#backgroundElement = null;
3598
+ if (!background.element) {
3599
+ return;
3600
+ }
3601
+ if (typeof background.element === "string") {
3602
+ if (typeof document !== "undefined") {
3603
+ const node = document.querySelector(background.element);
3604
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
3605
+ this.#backgroundElement = node;
3606
+ }
3607
+ else if (node) {
3608
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
3609
+ }
3610
+ else {
3611
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
3612
+ }
3613
+ }
3614
+ }
3615
+ else if (background.element instanceof HTMLCanvasElement ||
3616
+ background.element instanceof OffscreenCanvas ||
3617
+ background.element instanceof HTMLVideoElement ||
3618
+ background.element instanceof HTMLImageElement) {
3619
+ this.#backgroundElement = background.element;
3620
+ }
3621
+ }
3622
+ #warnOnce(key, message) {
3623
+ if (!this.#backgroundWarnings.has(key)) {
3624
+ this.#backgroundWarnings.add(key);
3625
+ getLogger().warning(message);
3626
+ }
3627
+ }
3538
3628
  }
3539
3629
 
3540
3630
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4111,7 +4201,6 @@
4111
4201
  }
4112
4202
  class Particle {
4113
4203
  backColor;
4114
- bubble;
4115
4204
  destroyed;
4116
4205
  direction;
4117
4206
  effect;
@@ -4145,7 +4234,6 @@
4145
4234
  shapeData;
4146
4235
  sides;
4147
4236
  size;
4148
- slow;
4149
4237
  spawning;
4150
4238
  strokeColor;
4151
4239
  strokeOpacity;
@@ -4167,18 +4255,25 @@
4167
4255
  d: 1,
4168
4256
  };
4169
4257
  #container;
4258
+ #modifiers = [];
4170
4259
  #pluginManager;
4171
4260
  constructor(pluginManager, container) {
4172
4261
  this.#pluginManager = pluginManager;
4173
4262
  this.#container = container;
4174
4263
  }
4264
+ addModifier(modifier) {
4265
+ this.#modifiers.push(modifier);
4266
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
4267
+ }
4268
+ clearModifiers() {
4269
+ this.#modifiers.length = 0;
4270
+ }
4175
4271
  destroy(override) {
4176
4272
  if (this.unbreakable || this.destroyed) {
4177
4273
  return;
4178
4274
  }
4179
4275
  this.destroyed = true;
4180
- this.bubble.inRange = false;
4181
- this.slow.inRange = false;
4276
+ this.clearModifiers();
4182
4277
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
4183
4278
  shapeDrawer?.particleDestroy?.(this);
4184
4279
  for (const plugin of container.particleDestroyedPlugins) {
@@ -4200,13 +4295,16 @@
4200
4295
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
4201
4296
  }
4202
4297
  getFillColor() {
4203
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
4298
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
4204
4299
  }
4205
4300
  getMass() {
4206
4301
  return this.getRadius() ** squareExp * Math.PI * half;
4207
4302
  }
4303
+ getModifier(id) {
4304
+ return this.#modifiers.find(m => m.id === id);
4305
+ }
4208
4306
  getOpacity() {
4209
- 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;
4307
+ 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;
4210
4308
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4211
4309
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4212
4310
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -4219,7 +4317,7 @@
4219
4317
  return this.#cachedPosition;
4220
4318
  }
4221
4319
  getRadius() {
4222
- return this.bubble.radius ?? this.size.value;
4320
+ return this.#applyModifiers(this.size.value, m => m.radius);
4223
4321
  }
4224
4322
  getRotateData() {
4225
4323
  const angle = this.getAngle();
@@ -4228,7 +4326,7 @@
4228
4326
  return this.#cachedRotateData;
4229
4327
  }
4230
4328
  getStrokeColor() {
4231
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
4329
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
4232
4330
  }
4233
4331
  getTransformData(externalTransform) {
4234
4332
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -4248,13 +4346,6 @@
4248
4346
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
4249
4347
  container.retina.initParticle(this);
4250
4348
  runUpdaterPreInit(container.particleUpdaters, this);
4251
- this.bubble = {
4252
- inRange: false,
4253
- };
4254
- this.slow = {
4255
- inRange: false,
4256
- factor: 1,
4257
- };
4258
4349
  this.#initPosition(position);
4259
4350
  this.initialVelocity = this.#calculateVelocity();
4260
4351
  this.velocity = this.initialVelocity.copy();
@@ -4294,11 +4385,29 @@
4294
4385
  isVisible() {
4295
4386
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
4296
4387
  }
4388
+ removeModifier(id) {
4389
+ const idx = this.#modifiers.findIndex(m => m.id === id);
4390
+ if (idx >= defaultAngle) {
4391
+ this.#modifiers.splice(idx, identity);
4392
+ }
4393
+ }
4297
4394
  reset() {
4298
4395
  for (const updater of this.#container.particleUpdaters) {
4299
4396
  updater.reset?.(this);
4300
4397
  }
4301
4398
  }
4399
+ #applyModifiers(base, getter) {
4400
+ let value = base;
4401
+ for (const mod of this.#modifiers) {
4402
+ if (mod.enabled) {
4403
+ const override = getter(mod);
4404
+ if (override !== undefined) {
4405
+ value = override;
4406
+ }
4407
+ }
4408
+ }
4409
+ return value;
4410
+ }
4302
4411
  #calcPosition(position, zIndex) {
4303
4412
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
4304
4413
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -5400,6 +5509,7 @@
5400
5509
  });
5401
5510
 
5402
5511
  class BlendPluginInstance {
5512
+ layer = DrawLayer.CanvasSetup;
5403
5513
  #container;
5404
5514
  #defaultCompositeValue;
5405
5515
  constructor(container) {
@@ -5545,7 +5655,8 @@
5545
5655
  particle.lastPathTime -= pathDelay;
5546
5656
  }
5547
5657
  function getProximitySpeedFactor(particle) {
5548
- return particle.slow.inRange ? particle.slow.factor : identity;
5658
+ const mod = particle.getModifier("slow");
5659
+ return mod?.enabled ? (mod.speedFactor ?? identity) : identity;
5549
5660
  }
5550
5661
  function initSpin(container, particle) {
5551
5662
  const options = particle.options, spinOptions = options.move.spin;