@tsparticles/particles 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
- /* tsParticles v4.2.1 */
2
+ /* tsParticles 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) :
@@ -398,29 +398,27 @@
398
398
  }
399
399
  }
400
400
  else if (!isObject(destination) || Array.isArray(destination)) {
401
- destination = {};
401
+ destination = Object.create(null);
402
402
  }
403
- const sourceKeys = Object.keys(source), dangerousKeys = new Set(["__proto__", "constructor", "prototype"]), hasNested = sourceKeys.some(k => {
403
+ const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
404
404
  const v = source[k];
405
405
  return isObject(v) || Array.isArray(v);
406
406
  });
407
407
  if (!hasNested) {
408
408
  const sourceDict = source, destDict = destination;
409
409
  for (const key of sourceKeys) {
410
- if (dangerousKeys.has(key)) {
410
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
411
411
  continue;
412
412
  }
413
- if (key in sourceDict) {
414
- const v = sourceDict[key];
415
- if (v !== undefined) {
416
- destDict[key] = v;
417
- }
413
+ const v = sourceDict[key];
414
+ if (v !== undefined) {
415
+ destDict[key] = v;
418
416
  }
419
417
  }
420
418
  continue;
421
419
  }
422
420
  for (const key of sourceKeys) {
423
- if (dangerousKeys.has(key)) {
421
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
424
422
  continue;
425
423
  }
426
424
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -879,7 +877,7 @@
879
877
  return this.#domArray;
880
878
  }
881
879
  get version() {
882
- return "4.2.1";
880
+ return "4.3.0";
883
881
  }
884
882
  addEventListener(type, listener) {
885
883
  this.#eventDispatcher.addEventListener(type, listener);
@@ -1112,6 +1110,18 @@
1112
1110
  AnimationStatus["decreasing"] = "decreasing";
1113
1111
  })(exports.AnimationStatus || (exports.AnimationStatus = {}));
1114
1112
 
1113
+ exports.DrawLayer = void 0;
1114
+ (function (DrawLayer) {
1115
+ DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
1116
+ DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
1117
+ DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
1118
+ DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
1119
+ DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
1120
+ DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
1121
+ DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
1122
+ DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1123
+ })(exports.DrawLayer || (exports.DrawLayer = {}));
1124
+
1115
1125
  class OptionLoader {
1116
1126
  load(data) {
1117
1127
  if (isNull(data)) {
@@ -1270,6 +1280,8 @@
1270
1280
 
1271
1281
  class Background extends OptionLoader {
1272
1282
  color;
1283
+ draw;
1284
+ element;
1273
1285
  image = "";
1274
1286
  opacity = 1;
1275
1287
  position = "";
@@ -1284,6 +1296,8 @@
1284
1296
  if (data.color !== undefined) {
1285
1297
  this.color = OptionsColor.create(this.color, data.color);
1286
1298
  }
1299
+ loadProperty(this, "element", data.element);
1300
+ loadProperty(this, "draw", data.draw);
1287
1301
  loadProperty(this, "image", data.image);
1288
1302
  loadProperty(this, "position", data.position);
1289
1303
  loadProperty(this, "repeat", data.repeat);
@@ -1829,7 +1843,7 @@
1829
1843
  }
1830
1844
  }
1831
1845
 
1832
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
1846
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1833
1847
  function getCachedStyle(key, generator) {
1834
1848
  let cached = styleCache.get(key);
1835
1849
  if (!cached) {
@@ -1972,6 +1986,17 @@
1972
1986
  : 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));
1973
1987
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1974
1988
  }
1989
+ function hslToRgbFloat(hsl) {
1990
+ 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;
1991
+ if (s === sMin) {
1992
+ const grayscaleValue = lNormalized * rgbMax;
1993
+ return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1994
+ }
1995
+ const temp1 = lNormalized < half
1996
+ ? lNormalized * (sNormalizedOffset + sNormalized)
1997
+ : 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));
1998
+ return { r: red, g: green, b: blue };
1999
+ }
1975
2000
  function hslaToRgba(hsla) {
1976
2001
  const rgbResult = hslToRgb(hsla);
1977
2002
  return {
@@ -1981,8 +2006,16 @@
1981
2006
  r: rgbResult.r,
1982
2007
  };
1983
2008
  }
1984
- function getRandomRgbColor(min) {
1985
- const fixedMin = min ?? defaultRgbMin, fixedMax = rgbMax + identity, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
2009
+ function getRandomRgbColor(min, hdr) {
2010
+ const fixedMin = min ?? defaultRgbMin;
2011
+ if (hdr) {
2012
+ return {
2013
+ r: getRandomInRange(fixedMin, rgbMax),
2014
+ g: getRandomInRange(fixedMin, rgbMax),
2015
+ b: getRandomInRange(fixedMin, rgbMax),
2016
+ };
2017
+ }
2018
+ const fixedMax = rgbMax + identity, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1986
2019
  return {
1987
2020
  b: getRgbInRangeValue(),
1988
2021
  g: getRgbInRangeValue(),
@@ -1990,7 +2023,7 @@
1990
2023
  };
1991
2024
  }
1992
2025
  function getStyleFromRgb(color, hdr, opacity) {
1993
- const op = opacity ?? defaultOpacity$2, key = `rgb-${color.r.toFixed(rgbFixedPrecision)}-${color.g.toFixed(rgbFixedPrecision)}-${color.b.toFixed(rgbFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2026
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$2, key = `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1994
2027
  return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
1995
2028
  }
1996
2029
  function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
@@ -2001,9 +2034,9 @@
2001
2034
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$2).toString()})`;
2002
2035
  }
2003
2036
  function getStyleFromHsl(color, hdr, opacity) {
2004
- const op = opacity ?? defaultOpacity$2, key = `hsl-${color.h.toFixed(hslFixedPrecision)}-${color.s.toFixed(hslFixedPrecision)}-${color.l.toFixed(hslFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2037
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$2, key = `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2005
2038
  return getCachedStyle(key, () => hdr
2006
- ? getStyleFromRgb(hslToRgb(color), true, opacity)
2039
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2007
2040
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
2008
2041
  }
2009
2042
  function colorMix(color1, color2, size1, size2) {
@@ -2123,7 +2156,7 @@
2123
2156
  colorValue.velocity = defaultVelocity;
2124
2157
  }
2125
2158
  }
2126
- function updateColorValue(data, decrease, delta) {
2159
+ function updateColorValue(data, decrease, delta, hdr) {
2127
2160
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2128
2161
  if (!data.enable ||
2129
2162
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2136,7 +2169,7 @@
2136
2169
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2137
2170
  return;
2138
2171
  }
2139
- 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;
2172
+ 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;
2140
2173
  if (!decrease || data.status === exports.AnimationStatus.increasing) {
2141
2174
  data.value += velocity;
2142
2175
  if (data.value > max) {
@@ -2163,14 +2196,14 @@
2163
2196
  }
2164
2197
  data.value = clamp(data.value, min, max);
2165
2198
  }
2166
- function updateColor(color, delta) {
2199
+ function updateColor(color, delta, hdr) {
2167
2200
  if (!color) {
2168
2201
  return;
2169
2202
  }
2170
2203
  const { h, s, l } = color;
2171
- updateColorValue(h, false, delta);
2172
- updateColorValue(s, true, delta);
2173
- updateColorValue(l, true, delta);
2204
+ updateColorValue(h, false, delta, hdr);
2205
+ updateColorValue(s, true, delta, hdr);
2206
+ updateColorValue(l, true, delta, hdr);
2174
2207
  }
2175
2208
  function alterHsl(color, type, value) {
2176
2209
  return {
@@ -2286,7 +2319,7 @@
2286
2319
  }
2287
2320
 
2288
2321
  async function loadBlendPlugin(engine) {
2289
- engine.checkVersion("4.2.1");
2322
+ engine.checkVersion("4.3.0");
2290
2323
  await engine.pluginManager.register(e => {
2291
2324
  e.pluginManager.addPlugin(new BlendPlugin());
2292
2325
  });
@@ -2323,7 +2356,7 @@
2323
2356
  }
2324
2357
 
2325
2358
  async function loadCircleShape(engine) {
2326
- engine.checkVersion("4.2.1");
2359
+ engine.checkVersion("4.3.0");
2327
2360
  await engine.pluginManager.register(e => {
2328
2361
  e.pluginManager.addShape(["circle"], () => {
2329
2362
  return Promise.resolve(new CircleDrawer());
@@ -2371,7 +2404,7 @@
2371
2404
  }
2372
2405
 
2373
2406
  async function loadHexColorPlugin(engine) {
2374
- engine.checkVersion("4.2.1");
2407
+ engine.checkVersion("4.3.0");
2375
2408
  await engine.pluginManager.register(e => {
2376
2409
  e.pluginManager.addColorManager("hex", new HexColorManager());
2377
2410
  });
@@ -2424,7 +2457,7 @@
2424
2457
  }
2425
2458
 
2426
2459
  async function loadHslColorPlugin(engine) {
2427
- engine.checkVersion("4.2.1");
2460
+ engine.checkVersion("4.3.0");
2428
2461
  await engine.pluginManager.register(e => {
2429
2462
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2430
2463
  });
@@ -2448,7 +2481,7 @@
2448
2481
  }
2449
2482
 
2450
2483
  async function loadMovePlugin(engine) {
2451
- engine.checkVersion("4.2.1");
2484
+ engine.checkVersion("4.3.0");
2452
2485
  await engine.pluginManager.register(e => {
2453
2486
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2454
2487
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2658,7 +2691,7 @@
2658
2691
  }
2659
2692
 
2660
2693
  async function loadOpacityUpdater(engine) {
2661
- engine.checkVersion("4.2.1");
2694
+ engine.checkVersion("4.3.0");
2662
2695
  await engine.pluginManager.register(e => {
2663
2696
  e.pluginManager.addParticleUpdater("opacity", container => {
2664
2697
  return Promise.resolve(new OpacityUpdater(container));
@@ -3003,7 +3036,7 @@
3003
3036
  }
3004
3037
 
3005
3038
  async function loadOutModesUpdater(engine) {
3006
- engine.checkVersion("4.2.1");
3039
+ engine.checkVersion("4.3.0");
3007
3040
  await engine.pluginManager.register(e => {
3008
3041
  e.pluginManager.addParticleUpdater("outModes", container => {
3009
3042
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3068,13 +3101,13 @@
3068
3101
  if (!this.isEnabled(particle)) {
3069
3102
  return;
3070
3103
  }
3071
- updateColor(particle.fillColor, delta);
3072
- updateColor(particle.strokeColor, delta);
3104
+ updateColor(particle.fillColor, delta, this.#container.hdr);
3105
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
3073
3106
  }
3074
3107
  }
3075
3108
 
3076
3109
  async function loadPaintUpdater(engine) {
3077
- engine.checkVersion("4.2.1");
3110
+ engine.checkVersion("4.3.0");
3078
3111
  await engine.pluginManager.register(e => {
3079
3112
  e.pluginManager.addParticleUpdater("paint", container => {
3080
3113
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3129,7 +3162,7 @@
3129
3162
  }
3130
3163
 
3131
3164
  async function loadRgbColorPlugin(engine) {
3132
- engine.checkVersion("4.2.1");
3165
+ engine.checkVersion("4.3.0");
3133
3166
  await engine.pluginManager.register(e => {
3134
3167
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3135
3168
  });
@@ -3214,7 +3247,7 @@
3214
3247
  }
3215
3248
 
3216
3249
  async function loadSizeUpdater(engine) {
3217
- engine.checkVersion("4.2.1");
3250
+ engine.checkVersion("4.3.0");
3218
3251
  await engine.pluginManager.register(e => {
3219
3252
  e.pluginManager.addParticleUpdater("size", container => {
3220
3253
  return Promise.resolve(new SizeUpdater(container));
@@ -3223,7 +3256,7 @@
3223
3256
  }
3224
3257
 
3225
3258
  async function loadBasic(engine) {
3226
- engine.checkVersion("4.2.1");
3259
+ engine.checkVersion("4.3.0");
3227
3260
  await engine.pluginManager.register(async (e) => {
3228
3261
  await Promise.all([
3229
3262
  loadBlendPlugin(e),
@@ -3424,7 +3457,7 @@
3424
3457
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3425
3458
 
3426
3459
  async function loadInteractivityPlugin(engine) {
3427
- engine.checkVersion("4.2.1");
3460
+ engine.checkVersion("4.3.0");
3428
3461
  await engine.pluginManager.register(e => {
3429
3462
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3430
3463
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3658,7 +3691,7 @@
3658
3691
  }
3659
3692
 
3660
3693
  async function loadParticlesCollisionsInteraction(engine) {
3661
- engine.checkVersion("4.2.1");
3694
+ engine.checkVersion("4.3.0");
3662
3695
  await engine.pluginManager.register((e) => {
3663
3696
  ensureInteractivityPluginLoaded(e);
3664
3697
  e.pluginManager.addPlugin(new OverlapPlugin());
@@ -3912,7 +3945,7 @@
3912
3945
  }
3913
3946
 
3914
3947
  async function loadParticlesLinksInteraction(engine) {
3915
- engine.checkVersion("4.2.1");
3948
+ engine.checkVersion("4.3.0");
3916
3949
  await engine.pluginManager.register((e) => {
3917
3950
  const pluginManager = e.pluginManager;
3918
3951
  ensureInteractivityPluginLoaded(e);
@@ -3925,7 +3958,7 @@
3925
3958
 
3926
3959
  let initPromise = null;
3927
3960
  async function doInitPlugins(engine) {
3928
- engine.checkVersion("4.2.1");
3961
+ engine.checkVersion("4.3.0");
3929
3962
  await engine.pluginManager.register(async (e) => {
3930
3963
  const loadParticlesInteractivity = async (e) => {
3931
3964
  await loadInteractivityPlugin(e);
@@ -3968,7 +4001,7 @@
3968
4001
  particles.init = async () => {
3969
4002
  await initPlugins(tsParticles);
3970
4003
  };
3971
- particles.version = "4.2.1";
4004
+ particles.version = "4.3.0";
3972
4005
  globalThis.particles = particles;
3973
4006
 
3974
4007
  const globalObject = globalThis;
@@ -3983,10 +4016,10 @@
3983
4016
  }
3984
4017
  }
3985
4018
  class RenderManager {
4019
+ #backgroundElement;
4020
+ #backgroundWarnings;
3986
4021
  #canvasClearPlugins;
3987
4022
  #canvasManager;
3988
- #canvasPaintPlugins;
3989
- #clearDrawPlugins;
3990
4023
  #colorPlugins;
3991
4024
  #container;
3992
4025
  #context;
@@ -3994,9 +4027,7 @@
3994
4027
  #drawParticlePlugins;
3995
4028
  #drawParticlesCleanupPlugins;
3996
4029
  #drawParticlesSetupPlugins;
3997
- #drawPlugins;
3998
- #drawSettingsCleanupPlugins;
3999
- #drawSettingsSetupPlugins;
4030
+ #layers;
4000
4031
  #pluginManager;
4001
4032
  #postDrawUpdaters;
4002
4033
  #preDrawUpdaters;
@@ -4008,18 +4039,25 @@
4008
4039
  this.#container = container;
4009
4040
  this.#canvasManager = canvasManager;
4010
4041
  this.#context = null;
4042
+ this.#backgroundElement = null;
4043
+ this.#backgroundWarnings = new Set();
4011
4044
  this.#preDrawUpdaters = [];
4012
4045
  this.#postDrawUpdaters = [];
4013
- this.#colorPlugins = [];
4014
4046
  this.#canvasClearPlugins = [];
4015
- this.#canvasPaintPlugins = [];
4016
- this.#clearDrawPlugins = [];
4047
+ this.#colorPlugins = [];
4017
4048
  this.#drawParticlePlugins = [];
4018
4049
  this.#drawParticlesCleanupPlugins = [];
4019
4050
  this.#drawParticlesSetupPlugins = [];
4020
- this.#drawPlugins = [];
4021
- this.#drawSettingsSetupPlugins = [];
4022
- this.#drawSettingsCleanupPlugins = [];
4051
+ this.#layers = {
4052
+ 0: [],
4053
+ 1: [],
4054
+ 2: [],
4055
+ 3: [],
4056
+ 4: [],
4057
+ 5: [],
4058
+ 6: [],
4059
+ 7: [],
4060
+ };
4023
4061
  }
4024
4062
  get settings() {
4025
4063
  return this.#contextSettings;
@@ -4033,32 +4071,38 @@
4033
4071
  });
4034
4072
  }
4035
4073
  clear() {
4036
- let pluginHandled = false;
4037
4074
  for (const plugin of this.#canvasClearPlugins) {
4038
- pluginHandled = plugin.canvasClear?.() ?? false;
4039
- if (pluginHandled) {
4040
- break;
4075
+ if (plugin.canvasClear?.() ?? false) {
4076
+ return;
4041
4077
  }
4042
4078
  }
4043
- if (pluginHandled) {
4044
- return;
4079
+ for (const layer of Object.values(exports.DrawLayer)) {
4080
+ if (typeof layer === "number") {
4081
+ for (const plugin of this.#getLayerPlugins(layer)) {
4082
+ if (plugin.canvasClear?.() ?? false) {
4083
+ return;
4084
+ }
4085
+ }
4086
+ }
4045
4087
  }
4046
4088
  this.canvasClear();
4047
4089
  }
4048
4090
  destroy() {
4049
4091
  this.stop();
4092
+ this.#backgroundElement = null;
4093
+ this.#backgroundWarnings.clear();
4050
4094
  this.#preDrawUpdaters = [];
4051
4095
  this.#postDrawUpdaters = [];
4052
- this.#colorPlugins = [];
4053
4096
  this.#canvasClearPlugins = [];
4054
- this.#canvasPaintPlugins = [];
4055
- this.#clearDrawPlugins = [];
4097
+ this.#colorPlugins = [];
4056
4098
  this.#drawParticlePlugins = [];
4057
4099
  this.#drawParticlesCleanupPlugins = [];
4058
4100
  this.#drawParticlesSetupPlugins = [];
4059
- this.#drawPlugins = [];
4060
- this.#drawSettingsSetupPlugins = [];
4061
- this.#drawSettingsCleanupPlugins = [];
4101
+ for (const layer of Object.values(exports.DrawLayer)) {
4102
+ if (typeof layer === "number") {
4103
+ this.#layers[layer] = [];
4104
+ }
4105
+ }
4062
4106
  }
4063
4107
  draw(cb) {
4064
4108
  const ctx = this.#context;
@@ -4115,21 +4159,40 @@
4115
4159
  });
4116
4160
  }
4117
4161
  drawParticles(delta) {
4118
- const { particles } = this.#container;
4162
+ const { particles, actualOptions } = this.#container;
4119
4163
  this.clear();
4120
4164
  particles.update(delta);
4121
4165
  this.draw(ctx => {
4122
- for (const plugin of this.#drawSettingsSetupPlugins) {
4166
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
4167
+ if (this.#backgroundElement) {
4168
+ try {
4169
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
4170
+ }
4171
+ catch {
4172
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
4173
+ }
4174
+ }
4175
+ const background = actualOptions.background;
4176
+ if (background.draw) {
4177
+ try {
4178
+ background.draw(ctx, delta);
4179
+ }
4180
+ catch {
4181
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
4182
+ }
4183
+ }
4184
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
4185
+ plugin.canvasPaint?.();
4186
+ }
4187
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
4123
4188
  plugin.drawSettingsSetup?.(ctx, delta);
4124
4189
  }
4125
- for (const plugin of this.#drawPlugins) {
4190
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.PluginContent)) {
4126
4191
  plugin.draw?.(ctx, delta);
4127
4192
  }
4128
4193
  particles.drawParticles(delta);
4129
- for (const plugin of this.#clearDrawPlugins) {
4194
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup)) {
4130
4195
  plugin.clearDraw?.(ctx, delta);
4131
- }
4132
- for (const plugin of this.#drawSettingsCleanupPlugins) {
4133
4196
  plugin.drawSettingsCleanup?.(ctx, delta);
4134
4197
  }
4135
4198
  });
@@ -4137,29 +4200,24 @@
4137
4200
  init() {
4138
4201
  this.initUpdaters();
4139
4202
  this.initPlugins();
4203
+ this.#resolveBackgroundElement();
4140
4204
  this.paint();
4141
4205
  }
4142
4206
  initPlugins() {
4143
- this.#colorPlugins = [];
4144
4207
  this.#canvasClearPlugins = [];
4145
- this.#canvasPaintPlugins = [];
4146
- this.#clearDrawPlugins = [];
4208
+ this.#colorPlugins = [];
4147
4209
  this.#drawParticlePlugins = [];
4148
4210
  this.#drawParticlesSetupPlugins = [];
4149
4211
  this.#drawParticlesCleanupPlugins = [];
4150
- this.#drawPlugins = [];
4151
- this.#drawSettingsSetupPlugins = [];
4152
- this.#drawSettingsCleanupPlugins = [];
4212
+ for (const layer of Object.values(exports.DrawLayer)) {
4213
+ if (typeof layer === "number") {
4214
+ this.#layers[layer] = [];
4215
+ }
4216
+ }
4153
4217
  for (const plugin of this.#container.plugins) {
4154
4218
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4155
4219
  this.#colorPlugins.push(plugin);
4156
4220
  }
4157
- if (plugin.canvasClear) {
4158
- this.#canvasClearPlugins.push(plugin);
4159
- }
4160
- if (plugin.canvasPaint) {
4161
- this.#canvasPaintPlugins.push(plugin);
4162
- }
4163
4221
  if (plugin.drawParticle) {
4164
4222
  this.#drawParticlePlugins.push(plugin);
4165
4223
  }
@@ -4169,17 +4227,20 @@
4169
4227
  if (plugin.drawParticleCleanup) {
4170
4228
  this.#drawParticlesCleanupPlugins.push(plugin);
4171
4229
  }
4172
- if (plugin.draw) {
4173
- this.#drawPlugins.push(plugin);
4230
+ if (plugin.canvasClear) {
4231
+ this.#canvasClearPlugins.push(plugin);
4232
+ }
4233
+ if (plugin.canvasPaint) {
4234
+ this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
4174
4235
  }
4175
4236
  if (plugin.drawSettingsSetup) {
4176
- this.#drawSettingsSetupPlugins.push(plugin);
4237
+ this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
4177
4238
  }
4178
- if (plugin.drawSettingsCleanup) {
4179
- this.#drawSettingsCleanupPlugins.push(plugin);
4239
+ if (plugin.draw) {
4240
+ this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
4180
4241
  }
4181
- if (plugin.clearDraw) {
4182
- this.#clearDrawPlugins.push(plugin);
4242
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
4243
+ this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
4183
4244
  }
4184
4245
  }
4185
4246
  }
@@ -4197,7 +4258,7 @@
4197
4258
  }
4198
4259
  paint() {
4199
4260
  let handled = false;
4200
- for (const plugin of this.#canvasPaintPlugins) {
4261
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
4201
4262
  handled = plugin.canvasPaint?.() ?? false;
4202
4263
  if (handled) {
4203
4264
  break;
@@ -4370,6 +4431,9 @@
4370
4431
  }
4371
4432
  drawer.beforeDraw(data);
4372
4433
  }
4434
+ #getLayerPlugins(layer) {
4435
+ return this.#layers[layer];
4436
+ }
4373
4437
  #getPluginParticleColors(particle) {
4374
4438
  let fColor, sColor;
4375
4439
  for (const plugin of this.#colorPlugins) {
@@ -4387,6 +4451,39 @@
4387
4451
  this.#reusablePluginColors[sColorIndex] = sColor;
4388
4452
  return this.#reusablePluginColors;
4389
4453
  }
4454
+ #resolveBackgroundElement() {
4455
+ const background = this.#container.actualOptions.background;
4456
+ this.#backgroundElement = null;
4457
+ if (!background.element) {
4458
+ return;
4459
+ }
4460
+ if (typeof background.element === "string") {
4461
+ if (typeof document !== "undefined") {
4462
+ const node = document.querySelector(background.element);
4463
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4464
+ this.#backgroundElement = node;
4465
+ }
4466
+ else if (node) {
4467
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
4468
+ }
4469
+ else {
4470
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
4471
+ }
4472
+ }
4473
+ }
4474
+ else if (background.element instanceof HTMLCanvasElement ||
4475
+ background.element instanceof OffscreenCanvas ||
4476
+ background.element instanceof HTMLVideoElement ||
4477
+ background.element instanceof HTMLImageElement) {
4478
+ this.#backgroundElement = background.element;
4479
+ }
4480
+ }
4481
+ #warnOnce(key, message) {
4482
+ if (!this.#backgroundWarnings.has(key)) {
4483
+ this.#backgroundWarnings.add(key);
4484
+ getLogger().warning(message);
4485
+ }
4486
+ }
4390
4487
  }
4391
4488
 
4392
4489
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -4963,7 +5060,6 @@
4963
5060
  }
4964
5061
  class Particle {
4965
5062
  backColor;
4966
- bubble;
4967
5063
  destroyed;
4968
5064
  direction;
4969
5065
  effect;
@@ -4997,7 +5093,6 @@
4997
5093
  shapeData;
4998
5094
  sides;
4999
5095
  size;
5000
- slow;
5001
5096
  spawning;
5002
5097
  strokeColor;
5003
5098
  strokeOpacity;
@@ -5019,18 +5114,25 @@
5019
5114
  d: 1,
5020
5115
  };
5021
5116
  #container;
5117
+ #modifiers = [];
5022
5118
  #pluginManager;
5023
5119
  constructor(pluginManager, container) {
5024
5120
  this.#pluginManager = pluginManager;
5025
5121
  this.#container = container;
5026
5122
  }
5123
+ addModifier(modifier) {
5124
+ this.#modifiers.push(modifier);
5125
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
5126
+ }
5127
+ clearModifiers() {
5128
+ this.#modifiers.length = 0;
5129
+ }
5027
5130
  destroy(override) {
5028
5131
  if (this.unbreakable || this.destroyed) {
5029
5132
  return;
5030
5133
  }
5031
5134
  this.destroyed = true;
5032
- this.bubble.inRange = false;
5033
- this.slow.inRange = false;
5135
+ this.clearModifiers();
5034
5136
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
5035
5137
  shapeDrawer?.particleDestroy?.(this);
5036
5138
  for (const plugin of container.particleDestroyedPlugins) {
@@ -5052,13 +5154,16 @@
5052
5154
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
5053
5155
  }
5054
5156
  getFillColor() {
5055
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
5157
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
5056
5158
  }
5057
5159
  getMass() {
5058
5160
  return this.getRadius() ** squareExp * Math.PI * half;
5059
5161
  }
5162
+ getModifier(id) {
5163
+ return this.#modifiers.find(m => m.id === id);
5164
+ }
5060
5165
  getOpacity() {
5061
- const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, opacity = this.bubble.opacity ?? getRangeValue(this.opacity?.value ?? defaultOpacity$2), fillOpacity = this.fillOpacity ?? defaultOpacity$2, strokeOpacity = this.strokeOpacity ?? defaultOpacity$2;
5166
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$2), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$2, strokeOpacity = this.strokeOpacity ?? defaultOpacity$2;
5062
5167
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5063
5168
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5064
5169
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -5071,7 +5176,7 @@
5071
5176
  return this.#cachedPosition;
5072
5177
  }
5073
5178
  getRadius() {
5074
- return this.bubble.radius ?? this.size.value;
5179
+ return this.#applyModifiers(this.size.value, m => m.radius);
5075
5180
  }
5076
5181
  getRotateData() {
5077
5182
  const angle = this.getAngle();
@@ -5080,7 +5185,7 @@
5080
5185
  return this.#cachedRotateData;
5081
5186
  }
5082
5187
  getStrokeColor() {
5083
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
5188
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
5084
5189
  }
5085
5190
  getTransformData(externalTransform) {
5086
5191
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -5100,13 +5205,6 @@
5100
5205
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
5101
5206
  container.retina.initParticle(this);
5102
5207
  runUpdaterPreInit(container.particleUpdaters, this);
5103
- this.bubble = {
5104
- inRange: false,
5105
- };
5106
- this.slow = {
5107
- inRange: false,
5108
- factor: 1,
5109
- };
5110
5208
  this.#initPosition(position);
5111
5209
  this.initialVelocity = this.#calculateVelocity();
5112
5210
  this.velocity = this.initialVelocity.copy();
@@ -5146,11 +5244,29 @@
5146
5244
  isVisible() {
5147
5245
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
5148
5246
  }
5247
+ removeModifier(id) {
5248
+ const idx = this.#modifiers.findIndex(m => m.id === id);
5249
+ if (idx >= defaultAngle) {
5250
+ this.#modifiers.splice(idx, identity);
5251
+ }
5252
+ }
5149
5253
  reset() {
5150
5254
  for (const updater of this.#container.particleUpdaters) {
5151
5255
  updater.reset?.(this);
5152
5256
  }
5153
5257
  }
5258
+ #applyModifiers(base, getter) {
5259
+ let value = base;
5260
+ for (const mod of this.#modifiers) {
5261
+ if (mod.enabled) {
5262
+ const override = getter(mod);
5263
+ if (override !== undefined) {
5264
+ value = override;
5265
+ }
5266
+ }
5267
+ }
5268
+ return value;
5269
+ }
5154
5270
  #calcPosition(position, zIndex) {
5155
5271
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
5156
5272
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -6282,6 +6398,7 @@
6282
6398
  });
6283
6399
 
6284
6400
  class BlendPluginInstance {
6401
+ layer = exports.DrawLayer.CanvasSetup;
6285
6402
  #container;
6286
6403
  #defaultCompositeValue;
6287
6404
  constructor(container) {
@@ -6427,7 +6544,8 @@
6427
6544
  particle.lastPathTime -= pathDelay;
6428
6545
  }
6429
6546
  function getProximitySpeedFactor(particle) {
6430
- return particle.slow.inRange ? particle.slow.factor : identity;
6547
+ const mod = particle.getModifier("slow");
6548
+ return mod?.enabled ? (mod.speedFactor ?? identity) : identity;
6431
6549
  }
6432
6550
  function initSpin(container, particle) {
6433
6551
  const options = particle.options, spinOptions = options.move.spin;
@@ -7402,6 +7520,7 @@
7402
7520
  exports.hPhase = hPhase;
7403
7521
  exports.half = half;
7404
7522
  exports.hslToRgb = hslToRgb;
7523
+ exports.hslToRgbFloat = hslToRgbFloat;
7405
7524
  exports.hslaToRgba = hslaToRgba;
7406
7525
  exports.identity = identity;
7407
7526
  exports.inverseFactorNumerator = inverseFactorNumerator;