@tsparticles/preset-confetti-cannon 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* Preset v4.2.0 */
2
+ /* Preset v4.3.0 */
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
5
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -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.0";
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$2, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
1918
+ function getRandomRgbColor(min, hdr) {
1919
+ const fixedMin = defaultRgbMin;
1920
+ const fixedMax = rgbMax + identity$2, 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.0");
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.0");
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.0");
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.0");
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.0");
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();
@@ -2450,7 +2476,7 @@
2450
2476
  }
2451
2477
 
2452
2478
  async function loadOpacityUpdater(engine) {
2453
- engine.checkVersion("4.2.0");
2479
+ engine.checkVersion("4.3.0");
2454
2480
  await engine.pluginManager.register(e => {
2455
2481
  e.pluginManager.addParticleUpdater("opacity", container => {
2456
2482
  return Promise.resolve(new OpacityUpdater(container));
@@ -2795,7 +2821,7 @@
2795
2821
  }
2796
2822
 
2797
2823
  async function loadOutModesUpdater(engine) {
2798
- engine.checkVersion("4.2.0");
2824
+ engine.checkVersion("4.3.0");
2799
2825
  await engine.pluginManager.register(e => {
2800
2826
  e.pluginManager.addParticleUpdater("outModes", container => {
2801
2827
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2860,13 +2886,13 @@
2860
2886
  if (!this.isEnabled(particle)) {
2861
2887
  return;
2862
2888
  }
2863
- updateColor(particle.fillColor, delta);
2864
- updateColor(particle.strokeColor, delta);
2889
+ updateColor(particle.fillColor, delta, this.#container.hdr);
2890
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
2865
2891
  }
2866
2892
  }
2867
2893
 
2868
2894
  async function loadPaintUpdater(engine) {
2869
- engine.checkVersion("4.2.0");
2895
+ engine.checkVersion("4.3.0");
2870
2896
  await engine.pluginManager.register(e => {
2871
2897
  e.pluginManager.addParticleUpdater("paint", container => {
2872
2898
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2921,7 +2947,7 @@
2921
2947
  }
2922
2948
 
2923
2949
  async function loadRgbColorPlugin(engine) {
2924
- engine.checkVersion("4.2.0");
2950
+ engine.checkVersion("4.3.0");
2925
2951
  await engine.pluginManager.register(e => {
2926
2952
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2927
2953
  });
@@ -3006,7 +3032,7 @@
3006
3032
  }
3007
3033
 
3008
3034
  async function loadSizeUpdater(engine) {
3009
- engine.checkVersion("4.2.0");
3035
+ engine.checkVersion("4.3.0");
3010
3036
  await engine.pluginManager.register(e => {
3011
3037
  e.pluginManager.addParticleUpdater("size", container => {
3012
3038
  return Promise.resolve(new SizeUpdater(container));
@@ -3015,7 +3041,7 @@
3015
3041
  }
3016
3042
 
3017
3043
  async function loadBasic(engine) {
3018
- engine.checkVersion("4.2.0");
3044
+ engine.checkVersion("4.3.0");
3019
3045
  await engine.pluginManager.register(async (e) => {
3020
3046
  await Promise.all([
3021
3047
  loadBlendPlugin(e),
@@ -3246,7 +3272,7 @@
3246
3272
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3247
3273
 
3248
3274
  async function loadInteractivityPlugin(engine) {
3249
- engine.checkVersion("4.2.0");
3275
+ engine.checkVersion("4.3.0");
3250
3276
  await engine.pluginManager.register(e => {
3251
3277
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3252
3278
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3425,7 +3451,7 @@
3425
3451
  }
3426
3452
 
3427
3453
  async function loadExternalCannonInteraction(engine) {
3428
- engine.checkVersion("4.2.0");
3454
+ engine.checkVersion("4.3.0");
3429
3455
  await engine.pluginManager.register((e) => {
3430
3456
  ensureInteractivityPluginLoaded(e);
3431
3457
  e.pluginManager.addInteractor?.("externalCannon", container => {
@@ -3571,7 +3597,7 @@
3571
3597
  }
3572
3598
 
3573
3599
  async function loadLifeUpdater(engine) {
3574
- engine.checkVersion("4.2.0");
3600
+ engine.checkVersion("4.3.0");
3575
3601
  await engine.pluginManager.register(e => {
3576
3602
  e.pluginManager.addParticleUpdater("life", container => {
3577
3603
  return Promise.resolve(new LifeUpdater(container));
@@ -3625,7 +3651,7 @@
3625
3651
  }
3626
3652
 
3627
3653
  async function loadMotionPlugin(engine) {
3628
- engine.checkVersion("4.2.0");
3654
+ engine.checkVersion("4.3.0");
3629
3655
  await engine.pluginManager.register(e => {
3630
3656
  e.pluginManager.addPlugin(new MotionPlugin());
3631
3657
  });
@@ -3758,7 +3784,7 @@
3758
3784
  }
3759
3785
 
3760
3786
  async function loadRollUpdater(engine) {
3761
- engine.checkVersion("4.2.0");
3787
+ engine.checkVersion("4.3.0");
3762
3788
  await engine.pluginManager.register(e => {
3763
3789
  e.pluginManager.addParticleUpdater("roll", () => {
3764
3790
  return Promise.resolve(new RollUpdater(e.pluginManager));
@@ -3864,7 +3890,7 @@
3864
3890
  }
3865
3891
 
3866
3892
  async function loadRotateUpdater(engine) {
3867
- engine.checkVersion("4.2.0");
3893
+ engine.checkVersion("4.3.0");
3868
3894
  await engine.pluginManager.register(e => {
3869
3895
  e.pluginManager.addParticleUpdater("rotate", container => {
3870
3896
  return Promise.resolve(new RotateUpdater(container));
@@ -3888,7 +3914,7 @@
3888
3914
  }
3889
3915
 
3890
3916
  async function loadSquareShape(engine) {
3891
- engine.checkVersion("4.2.0");
3917
+ engine.checkVersion("4.3.0");
3892
3918
  await engine.pluginManager.register(e => {
3893
3919
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
3894
3920
  });
@@ -3997,7 +4023,7 @@
3997
4023
  }
3998
4024
 
3999
4025
  async function loadTiltUpdater(engine) {
4000
- engine.checkVersion("4.2.0");
4026
+ engine.checkVersion("4.3.0");
4001
4027
  await engine.pluginManager.register(e => {
4002
4028
  e.pluginManager.addParticleUpdater("tilt", container => {
4003
4029
  return Promise.resolve(new TiltUpdater(container));
@@ -4099,7 +4125,7 @@
4099
4125
  }
4100
4126
 
4101
4127
  async function loadWobbleUpdater(engine) {
4102
- engine.checkVersion("4.2.0");
4128
+ engine.checkVersion("4.3.0");
4103
4129
  await engine.pluginManager.register(e => {
4104
4130
  e.pluginManager.addParticleUpdater("wobble", container => {
4105
4131
  return Promise.resolve(new WobbleUpdater(container));
@@ -4254,10 +4280,10 @@
4254
4280
  }
4255
4281
  }
4256
4282
  class RenderManager {
4283
+ #backgroundElement;
4284
+ #backgroundWarnings;
4257
4285
  #canvasClearPlugins;
4258
4286
  #canvasManager;
4259
- #canvasPaintPlugins;
4260
- #clearDrawPlugins;
4261
4287
  #colorPlugins;
4262
4288
  #container;
4263
4289
  #context;
@@ -4265,9 +4291,7 @@
4265
4291
  #drawParticlePlugins;
4266
4292
  #drawParticlesCleanupPlugins;
4267
4293
  #drawParticlesSetupPlugins;
4268
- #drawPlugins;
4269
- #drawSettingsCleanupPlugins;
4270
- #drawSettingsSetupPlugins;
4294
+ #layers;
4271
4295
  #pluginManager;
4272
4296
  #postDrawUpdaters;
4273
4297
  #preDrawUpdaters;
@@ -4279,18 +4303,25 @@
4279
4303
  this.#container = container;
4280
4304
  this.#canvasManager = canvasManager;
4281
4305
  this.#context = null;
4306
+ this.#backgroundElement = null;
4307
+ this.#backgroundWarnings = new Set();
4282
4308
  this.#preDrawUpdaters = [];
4283
4309
  this.#postDrawUpdaters = [];
4284
- this.#colorPlugins = [];
4285
4310
  this.#canvasClearPlugins = [];
4286
- this.#canvasPaintPlugins = [];
4287
- this.#clearDrawPlugins = [];
4311
+ this.#colorPlugins = [];
4288
4312
  this.#drawParticlePlugins = [];
4289
4313
  this.#drawParticlesCleanupPlugins = [];
4290
4314
  this.#drawParticlesSetupPlugins = [];
4291
- this.#drawPlugins = [];
4292
- this.#drawSettingsSetupPlugins = [];
4293
- this.#drawSettingsCleanupPlugins = [];
4315
+ this.#layers = {
4316
+ 0: [],
4317
+ 1: [],
4318
+ 2: [],
4319
+ 3: [],
4320
+ 4: [],
4321
+ 5: [],
4322
+ 6: [],
4323
+ 7: [],
4324
+ };
4294
4325
  }
4295
4326
  get settings() {
4296
4327
  return this.#contextSettings;
@@ -4304,32 +4335,38 @@
4304
4335
  });
4305
4336
  }
4306
4337
  clear() {
4307
- let pluginHandled = false;
4308
4338
  for (const plugin of this.#canvasClearPlugins) {
4309
- pluginHandled = plugin.canvasClear?.() ?? false;
4310
- if (pluginHandled) {
4311
- break;
4339
+ if (plugin.canvasClear?.() ?? false) {
4340
+ return;
4312
4341
  }
4313
4342
  }
4314
- if (pluginHandled) {
4315
- return;
4343
+ for (const layer of Object.values(DrawLayer)) {
4344
+ if (typeof layer === "number") {
4345
+ for (const plugin of this.#getLayerPlugins(layer)) {
4346
+ if (plugin.canvasClear?.() ?? false) {
4347
+ return;
4348
+ }
4349
+ }
4350
+ }
4316
4351
  }
4317
4352
  this.canvasClear();
4318
4353
  }
4319
4354
  destroy() {
4320
4355
  this.stop();
4356
+ this.#backgroundElement = null;
4357
+ this.#backgroundWarnings.clear();
4321
4358
  this.#preDrawUpdaters = [];
4322
4359
  this.#postDrawUpdaters = [];
4323
- this.#colorPlugins = [];
4324
4360
  this.#canvasClearPlugins = [];
4325
- this.#canvasPaintPlugins = [];
4326
- this.#clearDrawPlugins = [];
4361
+ this.#colorPlugins = [];
4327
4362
  this.#drawParticlePlugins = [];
4328
4363
  this.#drawParticlesCleanupPlugins = [];
4329
4364
  this.#drawParticlesSetupPlugins = [];
4330
- this.#drawPlugins = [];
4331
- this.#drawSettingsSetupPlugins = [];
4332
- this.#drawSettingsCleanupPlugins = [];
4365
+ for (const layer of Object.values(DrawLayer)) {
4366
+ if (typeof layer === "number") {
4367
+ this.#layers[layer] = [];
4368
+ }
4369
+ }
4333
4370
  }
4334
4371
  draw(cb) {
4335
4372
  const ctx = this.#context;
@@ -4386,21 +4423,40 @@
4386
4423
  });
4387
4424
  }
4388
4425
  drawParticles(delta) {
4389
- const { particles } = this.#container;
4426
+ const { particles, actualOptions } = this.#container;
4390
4427
  this.clear();
4391
4428
  particles.update(delta);
4392
4429
  this.draw(ctx => {
4393
- for (const plugin of this.#drawSettingsSetupPlugins) {
4430
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
4431
+ if (this.#backgroundElement) {
4432
+ try {
4433
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
4434
+ }
4435
+ catch {
4436
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
4437
+ }
4438
+ }
4439
+ const background = actualOptions.background;
4440
+ if (background.draw) {
4441
+ try {
4442
+ background.draw(ctx, delta);
4443
+ }
4444
+ catch {
4445
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
4446
+ }
4447
+ }
4448
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
4449
+ plugin.canvasPaint?.();
4450
+ }
4451
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
4394
4452
  plugin.drawSettingsSetup?.(ctx, delta);
4395
4453
  }
4396
- for (const plugin of this.#drawPlugins) {
4454
+ for (const plugin of this.#getLayerPlugins(DrawLayer.PluginContent)) {
4397
4455
  plugin.draw?.(ctx, delta);
4398
4456
  }
4399
4457
  particles.drawParticles(delta);
4400
- for (const plugin of this.#clearDrawPlugins) {
4458
+ for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasCleanup)) {
4401
4459
  plugin.clearDraw?.(ctx, delta);
4402
- }
4403
- for (const plugin of this.#drawSettingsCleanupPlugins) {
4404
4460
  plugin.drawSettingsCleanup?.(ctx, delta);
4405
4461
  }
4406
4462
  });
@@ -4408,29 +4464,24 @@
4408
4464
  init() {
4409
4465
  this.initUpdaters();
4410
4466
  this.initPlugins();
4467
+ this.#resolveBackgroundElement();
4411
4468
  this.paint();
4412
4469
  }
4413
4470
  initPlugins() {
4414
- this.#colorPlugins = [];
4415
4471
  this.#canvasClearPlugins = [];
4416
- this.#canvasPaintPlugins = [];
4417
- this.#clearDrawPlugins = [];
4472
+ this.#colorPlugins = [];
4418
4473
  this.#drawParticlePlugins = [];
4419
4474
  this.#drawParticlesSetupPlugins = [];
4420
4475
  this.#drawParticlesCleanupPlugins = [];
4421
- this.#drawPlugins = [];
4422
- this.#drawSettingsSetupPlugins = [];
4423
- this.#drawSettingsCleanupPlugins = [];
4476
+ for (const layer of Object.values(DrawLayer)) {
4477
+ if (typeof layer === "number") {
4478
+ this.#layers[layer] = [];
4479
+ }
4480
+ }
4424
4481
  for (const plugin of this.#container.plugins) {
4425
4482
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4426
4483
  this.#colorPlugins.push(plugin);
4427
4484
  }
4428
- if (plugin.canvasClear) {
4429
- this.#canvasClearPlugins.push(plugin);
4430
- }
4431
- if (plugin.canvasPaint) {
4432
- this.#canvasPaintPlugins.push(plugin);
4433
- }
4434
4485
  if (plugin.drawParticle) {
4435
4486
  this.#drawParticlePlugins.push(plugin);
4436
4487
  }
@@ -4440,17 +4491,20 @@
4440
4491
  if (plugin.drawParticleCleanup) {
4441
4492
  this.#drawParticlesCleanupPlugins.push(plugin);
4442
4493
  }
4443
- if (plugin.draw) {
4444
- this.#drawPlugins.push(plugin);
4494
+ if (plugin.canvasClear) {
4495
+ this.#canvasClearPlugins.push(plugin);
4496
+ }
4497
+ if (plugin.canvasPaint) {
4498
+ this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
4445
4499
  }
4446
4500
  if (plugin.drawSettingsSetup) {
4447
- this.#drawSettingsSetupPlugins.push(plugin);
4501
+ this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
4448
4502
  }
4449
- if (plugin.drawSettingsCleanup) {
4450
- this.#drawSettingsCleanupPlugins.push(plugin);
4503
+ if (plugin.draw) {
4504
+ this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
4451
4505
  }
4452
- if (plugin.clearDraw) {
4453
- this.#clearDrawPlugins.push(plugin);
4506
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
4507
+ this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
4454
4508
  }
4455
4509
  }
4456
4510
  }
@@ -4468,7 +4522,7 @@
4468
4522
  }
4469
4523
  paint() {
4470
4524
  let handled = false;
4471
- for (const plugin of this.#canvasPaintPlugins) {
4525
+ for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
4472
4526
  handled = plugin.canvasPaint?.() ?? false;
4473
4527
  if (handled) {
4474
4528
  break;
@@ -4641,6 +4695,9 @@
4641
4695
  }
4642
4696
  drawer.beforeDraw(data);
4643
4697
  }
4698
+ #getLayerPlugins(layer) {
4699
+ return this.#layers[layer];
4700
+ }
4644
4701
  #getPluginParticleColors(particle) {
4645
4702
  let fColor, sColor;
4646
4703
  for (const plugin of this.#colorPlugins) {
@@ -4658,6 +4715,39 @@
4658
4715
  this.#reusablePluginColors[sColorIndex] = sColor;
4659
4716
  return this.#reusablePluginColors;
4660
4717
  }
4718
+ #resolveBackgroundElement() {
4719
+ const background = this.#container.actualOptions.background;
4720
+ this.#backgroundElement = null;
4721
+ if (!background.element) {
4722
+ return;
4723
+ }
4724
+ if (typeof background.element === "string") {
4725
+ if (typeof document !== "undefined") {
4726
+ const node = document.querySelector(background.element);
4727
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4728
+ this.#backgroundElement = node;
4729
+ }
4730
+ else if (node) {
4731
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
4732
+ }
4733
+ else {
4734
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
4735
+ }
4736
+ }
4737
+ }
4738
+ else if (background.element instanceof HTMLCanvasElement ||
4739
+ background.element instanceof OffscreenCanvas ||
4740
+ background.element instanceof HTMLVideoElement ||
4741
+ background.element instanceof HTMLImageElement) {
4742
+ this.#backgroundElement = background.element;
4743
+ }
4744
+ }
4745
+ #warnOnce(key, message) {
4746
+ if (!this.#backgroundWarnings.has(key)) {
4747
+ this.#backgroundWarnings.add(key);
4748
+ getLogger().warning(message);
4749
+ }
4750
+ }
4661
4751
  }
4662
4752
 
4663
4753
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -5234,7 +5324,6 @@
5234
5324
  }
5235
5325
  class Particle {
5236
5326
  backColor;
5237
- bubble;
5238
5327
  destroyed;
5239
5328
  direction;
5240
5329
  effect;
@@ -5268,7 +5357,6 @@
5268
5357
  shapeData;
5269
5358
  sides;
5270
5359
  size;
5271
- slow;
5272
5360
  spawning;
5273
5361
  strokeColor;
5274
5362
  strokeOpacity;
@@ -5290,18 +5378,25 @@
5290
5378
  d: 1,
5291
5379
  };
5292
5380
  #container;
5381
+ #modifiers = [];
5293
5382
  #pluginManager;
5294
5383
  constructor(pluginManager, container) {
5295
5384
  this.#pluginManager = pluginManager;
5296
5385
  this.#container = container;
5297
5386
  }
5387
+ addModifier(modifier) {
5388
+ this.#modifiers.push(modifier);
5389
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
5390
+ }
5391
+ clearModifiers() {
5392
+ this.#modifiers.length = 0;
5393
+ }
5298
5394
  destroy(override) {
5299
5395
  if (this.unbreakable || this.destroyed) {
5300
5396
  return;
5301
5397
  }
5302
5398
  this.destroyed = true;
5303
- this.bubble.inRange = false;
5304
- this.slow.inRange = false;
5399
+ this.clearModifiers();
5305
5400
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
5306
5401
  shapeDrawer?.particleDestroy?.(this);
5307
5402
  for (const plugin of container.particleDestroyedPlugins) {
@@ -5323,13 +5418,16 @@
5323
5418
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
5324
5419
  }
5325
5420
  getFillColor() {
5326
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
5421
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
5327
5422
  }
5328
5423
  getMass() {
5329
5424
  return this.getRadius() ** squareExp * Math.PI * half;
5330
5425
  }
5426
+ getModifier(id) {
5427
+ return this.#modifiers.find(m => m.id === id);
5428
+ }
5331
5429
  getOpacity() {
5332
- 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;
5430
+ 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;
5333
5431
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5334
5432
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5335
5433
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -5342,7 +5440,7 @@
5342
5440
  return this.#cachedPosition;
5343
5441
  }
5344
5442
  getRadius() {
5345
- return this.bubble.radius ?? this.size.value;
5443
+ return this.#applyModifiers(this.size.value, m => m.radius);
5346
5444
  }
5347
5445
  getRotateData() {
5348
5446
  const angle = this.getAngle();
@@ -5351,7 +5449,7 @@
5351
5449
  return this.#cachedRotateData;
5352
5450
  }
5353
5451
  getStrokeColor() {
5354
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
5452
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
5355
5453
  }
5356
5454
  getTransformData(externalTransform) {
5357
5455
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -5371,13 +5469,6 @@
5371
5469
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
5372
5470
  container.retina.initParticle(this);
5373
5471
  runUpdaterPreInit(container.particleUpdaters, this);
5374
- this.bubble = {
5375
- inRange: false,
5376
- };
5377
- this.slow = {
5378
- inRange: false,
5379
- factor: 1,
5380
- };
5381
5472
  this.#initPosition(position);
5382
5473
  this.initialVelocity = this.#calculateVelocity();
5383
5474
  this.velocity = this.initialVelocity.copy();
@@ -5417,11 +5508,29 @@
5417
5508
  isVisible() {
5418
5509
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
5419
5510
  }
5511
+ removeModifier(id) {
5512
+ const idx = this.#modifiers.findIndex(m => m.id === id);
5513
+ if (idx >= defaultAngle) {
5514
+ this.#modifiers.splice(idx, identity$2);
5515
+ }
5516
+ }
5420
5517
  reset() {
5421
5518
  for (const updater of this.#container.particleUpdaters) {
5422
5519
  updater.reset?.(this);
5423
5520
  }
5424
5521
  }
5522
+ #applyModifiers(base, getter) {
5523
+ let value = base;
5524
+ for (const mod of this.#modifiers) {
5525
+ if (mod.enabled) {
5526
+ const override = getter(mod);
5527
+ if (override !== undefined) {
5528
+ value = override;
5529
+ }
5530
+ }
5531
+ }
5532
+ return value;
5533
+ }
5425
5534
  #calcPosition(position, zIndex) {
5426
5535
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
5427
5536
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -6523,6 +6632,7 @@
6523
6632
  });
6524
6633
 
6525
6634
  class BlendPluginInstance {
6635
+ layer = DrawLayer.CanvasSetup;
6526
6636
  #container;
6527
6637
  #defaultCompositeValue;
6528
6638
  constructor(container) {
@@ -6668,7 +6778,8 @@
6668
6778
  particle.lastPathTime -= pathDelay;
6669
6779
  }
6670
6780
  function getProximitySpeedFactor(particle) {
6671
- return particle.slow.inRange ? particle.slow.factor : identity$2;
6781
+ const mod = particle.getModifier("slow");
6782
+ return mod?.enabled ? (mod.speedFactor ?? identity$2) : identity$2;
6672
6783
  }
6673
6784
  function initSpin(container, particle) {
6674
6785
  const options = particle.options, spinOptions = options.move.spin;