@tsparticles/slim 4.2.1 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* tsParticles v4.2.1 */
2
+ /* tsParticles v4.3.1 */
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
5
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -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.1";
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$2, 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$2, 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$3, 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$3, 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$3).toString()})`;
2002
2035
  }
2003
2036
  function getStyleFromHsl(color, hdr, opacity) {
2004
- const op = opacity ?? defaultOpacity$3, 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$3, 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 {
@@ -2220,7 +2253,7 @@
2220
2253
  }
2221
2254
 
2222
2255
  async function loadBlendPlugin(engine) {
2223
- engine.checkVersion("4.2.1");
2256
+ engine.checkVersion("4.3.1");
2224
2257
  await engine.pluginManager.register(e => {
2225
2258
  e.pluginManager.addPlugin(new BlendPlugin());
2226
2259
  });
@@ -2257,7 +2290,7 @@
2257
2290
  }
2258
2291
 
2259
2292
  async function loadCircleShape(engine) {
2260
- engine.checkVersion("4.2.1");
2293
+ engine.checkVersion("4.3.1");
2261
2294
  await engine.pluginManager.register(e => {
2262
2295
  e.pluginManager.addShape(["circle"], () => {
2263
2296
  return Promise.resolve(new CircleDrawer());
@@ -2305,7 +2338,7 @@
2305
2338
  }
2306
2339
 
2307
2340
  async function loadHexColorPlugin(engine) {
2308
- engine.checkVersion("4.2.1");
2341
+ engine.checkVersion("4.3.1");
2309
2342
  await engine.pluginManager.register(e => {
2310
2343
  e.pluginManager.addColorManager("hex", new HexColorManager());
2311
2344
  });
@@ -2358,7 +2391,7 @@
2358
2391
  }
2359
2392
 
2360
2393
  async function loadHslColorPlugin(engine) {
2361
- engine.checkVersion("4.2.1");
2394
+ engine.checkVersion("4.3.1");
2362
2395
  await engine.pluginManager.register(e => {
2363
2396
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2364
2397
  });
@@ -2382,7 +2415,7 @@
2382
2415
  }
2383
2416
 
2384
2417
  async function loadMovePlugin(engine) {
2385
- engine.checkVersion("4.2.1");
2418
+ engine.checkVersion("4.3.1");
2386
2419
  await engine.pluginManager.register(e => {
2387
2420
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2388
2421
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2598,7 +2631,7 @@
2598
2631
  }
2599
2632
 
2600
2633
  async function loadOpacityUpdater(engine) {
2601
- engine.checkVersion("4.2.1");
2634
+ engine.checkVersion("4.3.1");
2602
2635
  await engine.pluginManager.register(e => {
2603
2636
  e.pluginManager.addParticleUpdater("opacity", container => {
2604
2637
  return Promise.resolve(new OpacityUpdater(container));
@@ -2943,7 +2976,7 @@
2943
2976
  }
2944
2977
 
2945
2978
  async function loadOutModesUpdater(engine) {
2946
- engine.checkVersion("4.2.1");
2979
+ engine.checkVersion("4.3.1");
2947
2980
  await engine.pluginManager.register(e => {
2948
2981
  e.pluginManager.addParticleUpdater("outModes", container => {
2949
2982
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3008,13 +3041,13 @@
3008
3041
  if (!this.isEnabled(particle)) {
3009
3042
  return;
3010
3043
  }
3011
- updateColor(particle.fillColor, delta);
3012
- updateColor(particle.strokeColor, delta);
3044
+ updateColor(particle.fillColor, delta, this.#container.hdr);
3045
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
3013
3046
  }
3014
3047
  }
3015
3048
 
3016
3049
  async function loadPaintUpdater(engine) {
3017
- engine.checkVersion("4.2.1");
3050
+ engine.checkVersion("4.3.1");
3018
3051
  await engine.pluginManager.register(e => {
3019
3052
  e.pluginManager.addParticleUpdater("paint", container => {
3020
3053
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3069,7 +3102,7 @@
3069
3102
  }
3070
3103
 
3071
3104
  async function loadRgbColorPlugin(engine) {
3072
- engine.checkVersion("4.2.1");
3105
+ engine.checkVersion("4.3.1");
3073
3106
  await engine.pluginManager.register(e => {
3074
3107
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3075
3108
  });
@@ -3154,7 +3187,7 @@
3154
3187
  }
3155
3188
 
3156
3189
  async function loadSizeUpdater(engine) {
3157
- engine.checkVersion("4.2.1");
3190
+ engine.checkVersion("4.3.1");
3158
3191
  await engine.pluginManager.register(e => {
3159
3192
  e.pluginManager.addParticleUpdater("size", container => {
3160
3193
  return Promise.resolve(new SizeUpdater(container));
@@ -3163,7 +3196,7 @@
3163
3196
  }
3164
3197
 
3165
3198
  async function loadBasic(engine) {
3166
- engine.checkVersion("4.2.1");
3199
+ engine.checkVersion("4.3.1");
3167
3200
  await engine.pluginManager.register(async (e) => {
3168
3201
  await Promise.all([
3169
3202
  loadBlendPlugin(e),
@@ -3186,7 +3219,7 @@
3186
3219
  easingsFunctions.set("ease-in-out-quad", value => (value < 0.5 ? 2 * value ** 2 : 1 - (-2 * value + 2) ** 2 / 2));
3187
3220
 
3188
3221
  async function loadEasingQuadPlugin(engine) {
3189
- engine.checkVersion("4.2.1");
3222
+ engine.checkVersion("4.3.1");
3190
3223
  await engine.pluginManager.register(e => {
3191
3224
  for (const [easing, easingFn] of easingsFunctions) {
3192
3225
  e.pluginManager.addEasing(easing, easingFn);
@@ -3294,7 +3327,7 @@
3294
3327
  }
3295
3328
 
3296
3329
  async function loadEmojiShape(engine) {
3297
- engine.checkVersion("4.2.1");
3330
+ engine.checkVersion("4.3.1");
3298
3331
  await engine.pluginManager.register(e => {
3299
3332
  e.pluginManager.addShape(validTypes, () => Promise.resolve(new EmojiDrawer()));
3300
3333
  });
@@ -3531,7 +3564,7 @@
3531
3564
  }
3532
3565
 
3533
3566
  async function loadInteractivityPlugin(engine) {
3534
- engine.checkVersion("4.2.1");
3567
+ engine.checkVersion("4.3.1");
3535
3568
  await engine.pluginManager.register(e => {
3536
3569
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3537
3570
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3791,7 +3824,7 @@
3791
3824
  };
3792
3825
 
3793
3826
  async function loadExternalAttractInteraction(engine) {
3794
- engine.checkVersion("4.2.1");
3827
+ engine.checkVersion("4.3.1");
3795
3828
  await engine.pluginManager.register((e) => {
3796
3829
  ensureInteractivityPluginLoaded(e);
3797
3830
  e.pluginManager.addInteractor?.("externalAttract", container => {
@@ -3980,7 +4013,7 @@
3980
4013
  }
3981
4014
 
3982
4015
  async function loadExternalBounceInteraction(engine) {
3983
- engine.checkVersion("4.2.1");
4016
+ engine.checkVersion("4.3.1");
3984
4017
  await engine.pluginManager.register((e) => {
3985
4018
  ensureInteractivityPluginLoaded(e);
3986
4019
  e.pluginManager.addInteractor?.("externalBounce", container => {
@@ -4040,6 +4073,19 @@
4040
4073
  }
4041
4074
  }
4042
4075
 
4076
+ class BubbleModifier {
4077
+ div;
4078
+ enabled = false;
4079
+ fillColor;
4080
+ finalColor;
4081
+ id = "bubble";
4082
+ inRange = false;
4083
+ opacity;
4084
+ priority = 100;
4085
+ radius;
4086
+ strokeColor;
4087
+ }
4088
+
4043
4089
  var ProcessBubbleType;
4044
4090
  (function (ProcessBubbleType) {
4045
4091
  ProcessBubbleType["color"] = "color";
@@ -4063,6 +4109,7 @@
4063
4109
  class Bubbler extends ExternalInteractorBase {
4064
4110
  handleClickMode;
4065
4111
  #maxDistance;
4112
+ #modifiers = new WeakMap();
4066
4113
  #pluginManager;
4067
4114
  constructor(pluginManager, container) {
4068
4115
  super(container);
@@ -4081,13 +4128,21 @@
4081
4128
  return this.#maxDistance;
4082
4129
  }
4083
4130
  clear(particle, _delta, force) {
4084
- if (particle.bubble.inRange && !force) {
4131
+ const mod = this.#modifiers.get(particle);
4132
+ if (mod?.inRange && !force) {
4085
4133
  return;
4086
4134
  }
4087
- delete particle.bubble.div;
4088
- delete particle.bubble.opacity;
4089
- delete particle.bubble.radius;
4090
- delete particle.bubble.color;
4135
+ particle.removeModifier(bubbleMode);
4136
+ this.#modifiers.delete(particle);
4137
+ }
4138
+ getOrCreateModifier(particle) {
4139
+ let mod = this.#modifiers.get(particle);
4140
+ if (!mod) {
4141
+ mod = new BubbleModifier();
4142
+ this.#modifiers.set(particle, mod);
4143
+ particle.addModifier(mod);
4144
+ }
4145
+ return mod;
4091
4146
  }
4092
4147
  init() {
4093
4148
  const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
@@ -4133,7 +4188,11 @@
4133
4188
  loadOptionProperty(options, "bubble", Bubble, ...sources);
4134
4189
  }
4135
4190
  reset(_interactivityData, particle) {
4136
- particle.bubble.inRange = false;
4191
+ const mod = this.#modifiers.get(particle);
4192
+ if (mod) {
4193
+ mod.enabled = false;
4194
+ mod.inRange = false;
4195
+ }
4137
4196
  }
4138
4197
  #clickBubble(interactivityData) {
4139
4198
  const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
@@ -4150,7 +4209,9 @@
4150
4209
  if (!bubble.clicking) {
4151
4210
  continue;
4152
4211
  }
4153
- particle.bubble.inRange = !bubble.durationEnd;
4212
+ const mod = this.getOrCreateModifier(particle);
4213
+ mod.enabled = !bubble.durationEnd;
4214
+ mod.inRange = !bubble.durationEnd;
4154
4215
  const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (performance.now() - (interactivityData.mouse.clickTime ?? defaultClickTime)) / millisecondsToSeconds;
4155
4216
  if (timeSpent > bubbleOptions.duration) {
4156
4217
  bubble.durationEnd = true;
@@ -4162,7 +4223,7 @@
4162
4223
  const sizeData = {
4163
4224
  bubbleObj: {
4164
4225
  optValue: container.retina.bubbleModeSize,
4165
- value: particle.bubble.radius,
4226
+ value: mod.radius,
4166
4227
  },
4167
4228
  particlesObj: {
4168
4229
  optValue: particle.size.max,
@@ -4174,7 +4235,7 @@
4174
4235
  const opacityData = {
4175
4236
  bubbleObj: {
4176
4237
  optValue: bubbleOptions.opacity,
4177
- value: particle.bubble.opacity,
4238
+ value: mod.opacity,
4178
4239
  },
4179
4240
  particlesObj: {
4180
4241
  optValue: particle.opacity?.max ?? defaultOpacity$1,
@@ -4187,7 +4248,8 @@
4187
4248
  this.#hoverBubbleColor(particle, distMouse);
4188
4249
  }
4189
4250
  else {
4190
- delete particle.bubble.color;
4251
+ mod.fillColor = undefined;
4252
+ mod.strokeColor = undefined;
4191
4253
  }
4192
4254
  }
4193
4255
  }
@@ -4198,7 +4260,9 @@
4198
4260
  }
4199
4261
  const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
4200
4262
  for (const particle of query) {
4201
- particle.bubble.inRange = true;
4263
+ const mod = this.getOrCreateModifier(particle);
4264
+ mod.enabled = true;
4265
+ mod.inRange = true;
4202
4266
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
4203
4267
  if (pointDistance <= distance) {
4204
4268
  if (ratio >= minRatio && interactivityData.status === mouseMoveEvent) {
@@ -4216,30 +4280,38 @@
4216
4280
  }
4217
4281
  }
4218
4282
  #hoverBubbleColor(particle, ratio, divBubble) {
4219
- const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;
4283
+ const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble, mod = this.getOrCreateModifier(particle);
4220
4284
  if (!bubbleOptions) {
4221
4285
  return;
4222
4286
  }
4223
- if (!particle.bubble.finalColor) {
4287
+ if (!mod.finalColor) {
4224
4288
  const modeColor = bubbleOptions.color;
4225
4289
  if (!modeColor) {
4226
4290
  return;
4227
4291
  }
4228
4292
  const bubbleColor = itemFromSingleOrMultiple(modeColor);
4229
- particle.bubble.finalColor = rangeColorToHsl(this.#pluginManager, bubbleColor);
4293
+ mod.finalColor = rangeColorToHsl(this.#pluginManager, bubbleColor);
4230
4294
  }
4231
- if (!particle.bubble.finalColor) {
4295
+ if (!mod.finalColor) {
4232
4296
  return;
4233
4297
  }
4234
4298
  if (bubbleOptions.mix) {
4235
- particle.bubble.color = undefined;
4299
+ mod.fillColor = undefined;
4300
+ mod.strokeColor = undefined;
4236
4301
  const pColor = particle.getFillColor();
4237
- particle.bubble.color = pColor
4238
- ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio))
4239
- : particle.bubble.finalColor;
4302
+ if (pColor) {
4303
+ const mixedColor = rgbToHsl(colorMix(pColor, mod.finalColor, ratioOffset - ratio, ratio));
4304
+ mod.fillColor = mixedColor;
4305
+ mod.strokeColor = mixedColor;
4306
+ }
4307
+ else {
4308
+ mod.fillColor = mod.finalColor;
4309
+ mod.strokeColor = mod.finalColor;
4310
+ }
4240
4311
  }
4241
4312
  else {
4242
- particle.bubble.color = particle.bubble.finalColor;
4313
+ mod.fillColor = mod.finalColor;
4314
+ mod.strokeColor = mod.finalColor;
4243
4315
  }
4244
4316
  }
4245
4317
  #hoverBubbleOpacity(particle, ratio, divBubble) {
@@ -4249,7 +4321,8 @@
4249
4321
  }
4250
4322
  const pOpacity = particle.opacity?.value ?? defaultOpacity$1, opacity = calculateBubbleValue(pOpacity, modeOpacity, particle.opacity?.max ?? defaultOpacity$1, ratio);
4251
4323
  if (opacity !== undefined) {
4252
- particle.bubble.opacity = opacity;
4324
+ const mod = this.getOrCreateModifier(particle);
4325
+ mod.opacity = opacity;
4253
4326
  }
4254
4327
  }
4255
4328
  #hoverBubbleSize(particle, ratio, divBubble) {
@@ -4259,7 +4332,8 @@
4259
4332
  }
4260
4333
  const pSize = particle.size.value, size = calculateBubbleValue(pSize, modeSize, particle.size.max, ratio);
4261
4334
  if (size !== undefined) {
4262
- particle.bubble.radius = size;
4335
+ const mod = this.getOrCreateModifier(particle);
4336
+ mod.radius = size;
4263
4337
  }
4264
4338
  }
4265
4339
  #process(particle, distMouse, timeSpent, data) {
@@ -4272,13 +4346,14 @@
4272
4346
  return;
4273
4347
  }
4274
4348
  container.bubble ??= {};
4349
+ const mod = this.getOrCreateModifier(particle);
4275
4350
  if (container.bubble.durationEnd) {
4276
4351
  if (pObjBubble) {
4277
4352
  if (type === ProcessBubbleType.size) {
4278
- delete particle.bubble.radius;
4353
+ mod.radius = undefined;
4279
4354
  }
4280
4355
  if (type === ProcessBubbleType.opacity) {
4281
- delete particle.bubble.opacity;
4356
+ mod.opacity = undefined;
4282
4357
  }
4283
4358
  }
4284
4359
  }
@@ -4288,19 +4363,19 @@
4288
4363
  if (obj !== bubbleParam) {
4289
4364
  const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
4290
4365
  if (type === ProcessBubbleType.size) {
4291
- particle.bubble.radius = value;
4366
+ mod.radius = value;
4292
4367
  }
4293
4368
  if (type === ProcessBubbleType.opacity) {
4294
- particle.bubble.opacity = value;
4369
+ mod.opacity = value;
4295
4370
  }
4296
4371
  }
4297
4372
  }
4298
4373
  else {
4299
4374
  if (type === ProcessBubbleType.size) {
4300
- delete particle.bubble.radius;
4375
+ mod.radius = undefined;
4301
4376
  }
4302
4377
  if (type === ProcessBubbleType.opacity) {
4303
- delete particle.bubble.opacity;
4378
+ mod.opacity = undefined;
4304
4379
  }
4305
4380
  }
4306
4381
  }
@@ -4321,11 +4396,13 @@
4321
4396
  if (!area.contains(particle.getPosition())) {
4322
4397
  continue;
4323
4398
  }
4324
- particle.bubble.inRange = true;
4399
+ const mod = this.getOrCreateModifier(particle);
4400
+ mod.enabled = true;
4401
+ mod.inRange = true;
4325
4402
  const divs = bubble.divs, divBubble = divMode(divs, elem);
4326
- if (!particle.bubble.div || particle.bubble.div !== elem) {
4403
+ if (!mod.div || mod.div !== elem) {
4327
4404
  this.clear(particle, delta, true);
4328
- particle.bubble.div = elem;
4405
+ mod.div = elem;
4329
4406
  }
4330
4407
  this.#hoverBubbleSize(particle, defaultRatio, divBubble);
4331
4408
  this.#hoverBubbleOpacity(particle, defaultRatio, divBubble);
@@ -4336,7 +4413,7 @@
4336
4413
  }
4337
4414
 
4338
4415
  async function loadExternalBubbleInteraction(engine) {
4339
- engine.checkVersion("4.2.1");
4416
+ engine.checkVersion("4.3.1");
4340
4417
  await engine.pluginManager.register((e) => {
4341
4418
  ensureInteractivityPluginLoaded(e);
4342
4419
  e.pluginManager.addInteractor?.("externalBubble", container => {
@@ -4464,7 +4541,7 @@
4464
4541
  }
4465
4542
 
4466
4543
  async function loadExternalConnectInteraction(engine) {
4467
- engine.checkVersion("4.2.1");
4544
+ engine.checkVersion("4.3.1");
4468
4545
  await engine.pluginManager.register((e) => {
4469
4546
  ensureInteractivityPluginLoaded(e);
4470
4547
  e.pluginManager.addInteractor?.("externalConnect", container => {
@@ -4568,7 +4645,7 @@
4568
4645
  }
4569
4646
 
4570
4647
  async function loadExternalDestroyInteraction(engine) {
4571
- engine.checkVersion("4.2.1");
4648
+ engine.checkVersion("4.3.1");
4572
4649
  await engine.pluginManager.register((e) => {
4573
4650
  ensureInteractivityPluginLoaded(e);
4574
4651
  e.pluginManager.addInteractor?.("externalDestroy", async (container) => {
@@ -4692,7 +4769,7 @@
4692
4769
  }
4693
4770
 
4694
4771
  async function loadExternalGrabInteraction(engine) {
4695
- engine.checkVersion("4.2.1");
4772
+ engine.checkVersion("4.3.1");
4696
4773
  await engine.pluginManager.register((e) => {
4697
4774
  ensureInteractivityPluginLoaded(e);
4698
4775
  e.pluginManager.addInteractor?.("externalGrab", container => {
@@ -4762,7 +4839,7 @@
4762
4839
  }
4763
4840
 
4764
4841
  async function loadExternalParallaxInteraction(engine) {
4765
- engine.checkVersion("4.2.1");
4842
+ engine.checkVersion("4.3.1");
4766
4843
  await engine.pluginManager.register((e) => {
4767
4844
  ensureInteractivityPluginLoaded(e);
4768
4845
  e.pluginManager.addInteractor?.("externalParallax", container => {
@@ -4805,7 +4882,7 @@
4805
4882
  }
4806
4883
 
4807
4884
  async function loadExternalPauseInteraction(engine) {
4808
- engine.checkVersion("4.2.1");
4885
+ engine.checkVersion("4.3.1");
4809
4886
  await engine.pluginManager.register((e) => {
4810
4887
  ensureInteractivityPluginLoaded(e);
4811
4888
  e.pluginManager.addInteractor?.("externalPause", container => {
@@ -4877,7 +4954,7 @@
4877
4954
  }
4878
4955
 
4879
4956
  async function loadExternalPushInteraction(engine) {
4880
- engine.checkVersion("4.2.1");
4957
+ engine.checkVersion("4.3.1");
4881
4958
  await engine.pluginManager.register((e) => {
4882
4959
  ensureInteractivityPluginLoaded(e);
4883
4960
  e.pluginManager.addInteractor?.("externalPush", container => {
@@ -4931,7 +5008,7 @@
4931
5008
  }
4932
5009
 
4933
5010
  async function loadExternalRemoveInteraction(engine) {
4934
- engine.checkVersion("4.2.1");
5011
+ engine.checkVersion("4.3.1");
4935
5012
  await engine.pluginManager.register((e) => {
4936
5013
  ensureInteractivityPluginLoaded(e);
4937
5014
  e.pluginManager.addInteractor?.("externalRemove", container => {
@@ -5237,7 +5314,7 @@
5237
5314
  }
5238
5315
 
5239
5316
  async function loadExternalRepulseInteraction(engine) {
5240
- engine.checkVersion("4.2.1");
5317
+ engine.checkVersion("4.3.1");
5241
5318
  await engine.pluginManager.register((e) => {
5242
5319
  ensureInteractivityPluginLoaded(e);
5243
5320
  const pluginManager = e.pluginManager;
@@ -5259,9 +5336,17 @@
5259
5336
  }
5260
5337
  }
5261
5338
 
5339
+ class SlowModifier {
5340
+ enabled = false;
5341
+ id = "slow";
5342
+ priority = 100;
5343
+ speedFactor = 1;
5344
+ }
5345
+
5262
5346
  const slowMode = "slow", minRadius = 0;
5263
5347
  class Slower extends ExternalInteractorBase {
5264
5348
  #maxDistance;
5349
+ #modifiers = new WeakMap();
5265
5350
  constructor(container) {
5266
5351
  super(container);
5267
5352
  this.#maxDistance = 0;
@@ -5270,10 +5355,21 @@
5270
5355
  return this.#maxDistance;
5271
5356
  }
5272
5357
  clear(particle, _delta, force) {
5273
- if (particle.slow.inRange && !force) {
5358
+ const mod = this.#modifiers.get(particle);
5359
+ if (mod?.enabled && !force) {
5274
5360
  return;
5275
5361
  }
5276
- particle.slow.factor = 1;
5362
+ particle.removeModifier(slowMode);
5363
+ this.#modifiers.delete(particle);
5364
+ }
5365
+ getOrCreateModifier(particle) {
5366
+ let mod = this.#modifiers.get(particle);
5367
+ if (!mod) {
5368
+ mod = new SlowModifier();
5369
+ this.#modifiers.set(particle, mod);
5370
+ particle.addModifier(mod);
5371
+ }
5372
+ return mod;
5277
5373
  }
5278
5374
  init() {
5279
5375
  const container = this.container, slow = container.actualOptions.interactivity?.modes.slow;
@@ -5293,22 +5389,26 @@
5293
5389
  loadOptionProperty(options, "slow", Slow, ...sources);
5294
5390
  }
5295
5391
  reset(interactivityData, particle) {
5296
- particle.slow.inRange = false;
5392
+ const mod = this.#modifiers.get(particle);
5393
+ if (mod) {
5394
+ mod.enabled = false;
5395
+ }
5297
5396
  const container = this.container, options = container.actualOptions, mousePos = interactivityData.mouse.position, radius = container.retina.slowModeRadius, slowOptions = options.interactivity?.modes.slow;
5298
5397
  if (!slowOptions || !radius || radius < minRadius || !mousePos) {
5299
5398
  return;
5300
5399
  }
5301
- const particlePos = particle.getPosition(), dist = getDistance(mousePos, particlePos), proximityFactor = dist / radius, slowFactor = slowOptions.factor, { slow } = particle;
5400
+ const particlePos = particle.getPosition(), dist = getDistance(mousePos, particlePos), proximityFactor = dist / radius, slowFactor = slowOptions.factor;
5302
5401
  if (dist > radius) {
5303
5402
  return;
5304
5403
  }
5305
- slow.inRange = true;
5306
- slow.factor = proximityFactor / slowFactor;
5404
+ const activeMod = this.getOrCreateModifier(particle);
5405
+ activeMod.enabled = true;
5406
+ activeMod.speedFactor = proximityFactor / slowFactor;
5307
5407
  }
5308
5408
  }
5309
5409
 
5310
5410
  async function loadExternalSlowInteraction(engine) {
5311
- engine.checkVersion("4.2.1");
5411
+ engine.checkVersion("4.3.1");
5312
5412
  await engine.pluginManager.register((e) => {
5313
5413
  ensureInteractivityPluginLoaded(e);
5314
5414
  e.pluginManager.addInteractor?.("externalSlow", container => {
@@ -5370,7 +5470,6 @@
5370
5470
  function replaceImageColor(image, imageData, color, particle, hdr = false) {
5371
5471
  const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity, hdr), imageRes = {
5372
5472
  color,
5373
- gif: imageData.gif,
5374
5473
  data: {
5375
5474
  ...image,
5376
5475
  svgData: svgColoredData,
@@ -5405,495 +5504,6 @@
5405
5504
  });
5406
5505
  }
5407
5506
 
5408
- const InterlaceOffsets = [0, 4, 2, 1];
5409
- const InterlaceSteps = [8, 8, 4, 2];
5410
-
5411
- class ByteStream {
5412
- data;
5413
- pos;
5414
- constructor(bytes) {
5415
- this.pos = 0;
5416
- this.data = new Uint8ClampedArray(bytes);
5417
- }
5418
- getString(count) {
5419
- const slice = this.data.slice(this.pos, this.pos + count);
5420
- this.pos += slice.length;
5421
- return slice.reduce((acc, curr) => acc + String.fromCharCode(curr), "");
5422
- }
5423
- nextByte() {
5424
- return this.data[this.pos++];
5425
- }
5426
- nextTwoBytes() {
5427
- const increment = 2, previous = 1, shift = 8;
5428
- this.pos += increment;
5429
- return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
5430
- }
5431
- readSubBlocks() {
5432
- let blockString = "", size;
5433
- const minCount = 0, emptySize = 0;
5434
- do {
5435
- size = this.data[this.pos++];
5436
- for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
5437
- }
5438
- } while (size !== emptySize);
5439
- return blockString;
5440
- }
5441
- readSubBlocksBin() {
5442
- let size = this.data[this.pos], len = 0;
5443
- const emptySize = 0, increment = 1;
5444
- for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
5445
- len += size;
5446
- }
5447
- const blockData = new Uint8Array(len);
5448
- size = this.data[this.pos++];
5449
- for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
5450
- for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
5451
- }
5452
- }
5453
- return blockData;
5454
- }
5455
- skipSubBlocks() {
5456
- for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
5457
- }
5458
- this.pos++;
5459
- }
5460
- }
5461
-
5462
- var DisposalMethod;
5463
- (function (DisposalMethod) {
5464
- DisposalMethod[DisposalMethod["Replace"] = 0] = "Replace";
5465
- DisposalMethod[DisposalMethod["Combine"] = 1] = "Combine";
5466
- DisposalMethod[DisposalMethod["RestoreBackground"] = 2] = "RestoreBackground";
5467
- DisposalMethod[DisposalMethod["RestorePrevious"] = 3] = "RestorePrevious";
5468
- DisposalMethod[DisposalMethod["UndefinedA"] = 4] = "UndefinedA";
5469
- DisposalMethod[DisposalMethod["UndefinedB"] = 5] = "UndefinedB";
5470
- DisposalMethod[DisposalMethod["UndefinedC"] = 6] = "UndefinedC";
5471
- DisposalMethod[DisposalMethod["UndefinedD"] = 7] = "UndefinedD";
5472
- })(DisposalMethod || (DisposalMethod = {}));
5473
-
5474
- var GIFDataHeaders;
5475
- (function (GIFDataHeaders) {
5476
- GIFDataHeaders[GIFDataHeaders["Extension"] = 33] = "Extension";
5477
- GIFDataHeaders[GIFDataHeaders["ApplicationExtension"] = 255] = "ApplicationExtension";
5478
- GIFDataHeaders[GIFDataHeaders["GraphicsControlExtension"] = 249] = "GraphicsControlExtension";
5479
- GIFDataHeaders[GIFDataHeaders["PlainTextExtension"] = 1] = "PlainTextExtension";
5480
- GIFDataHeaders[GIFDataHeaders["CommentExtension"] = 254] = "CommentExtension";
5481
- GIFDataHeaders[GIFDataHeaders["Image"] = 44] = "Image";
5482
- GIFDataHeaders[GIFDataHeaders["EndOfFile"] = 59] = "EndOfFile";
5483
- })(GIFDataHeaders || (GIFDataHeaders = {}));
5484
-
5485
- const defaultFrame = 0, initialTime = 0, firstIndex = 0, defaultLoopCount = 0;
5486
- function parseColorTable(byteStream, count) {
5487
- const colors = [];
5488
- for (let i = 0; i < count; i++) {
5489
- colors.push({
5490
- r: byteStream.data[byteStream.pos],
5491
- g: byteStream.data[byteStream.pos + 1],
5492
- b: byteStream.data[byteStream.pos + 2],
5493
- });
5494
- byteStream.pos += 3;
5495
- }
5496
- return colors;
5497
- }
5498
- function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
5499
- switch (byteStream.nextByte()) {
5500
- case GIFDataHeaders.GraphicsControlExtension: {
5501
- const frame = gif.frames[getFrameIndex(false)];
5502
- byteStream.pos++;
5503
- const packedByte = byteStream.nextByte();
5504
- frame.GCreserved = (packedByte & 0xe0) >>> 5;
5505
- frame.disposalMethod = (packedByte & 0x1c) >>> 2;
5506
- frame.userInputDelayFlag = (packedByte & 2) === 2;
5507
- const transparencyFlag = (packedByte & 1) === 1;
5508
- frame.delayTime = byteStream.nextTwoBytes() * 0xa;
5509
- const transparencyIndex = byteStream.nextByte();
5510
- if (transparencyFlag) {
5511
- getTransparencyIndex(transparencyIndex);
5512
- }
5513
- byteStream.pos++;
5514
- break;
5515
- }
5516
- case GIFDataHeaders.ApplicationExtension: {
5517
- byteStream.pos++;
5518
- const applicationExtension = {
5519
- identifier: byteStream.getString(8),
5520
- authenticationCode: byteStream.getString(3),
5521
- data: byteStream.readSubBlocksBin(),
5522
- };
5523
- gif.applicationExtensions.push(applicationExtension);
5524
- break;
5525
- }
5526
- case GIFDataHeaders.CommentExtension: {
5527
- gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);
5528
- break;
5529
- }
5530
- case GIFDataHeaders.PlainTextExtension: {
5531
- if (gif.globalColorTable.length === 0) {
5532
- throw new EvalError("plain text extension without global color table");
5533
- }
5534
- byteStream.pos++;
5535
- gif.frames[getFrameIndex(false)].plainTextData = {
5536
- left: byteStream.nextTwoBytes(),
5537
- top: byteStream.nextTwoBytes(),
5538
- width: byteStream.nextTwoBytes(),
5539
- height: byteStream.nextTwoBytes(),
5540
- charSize: {
5541
- width: byteStream.nextTwoBytes(),
5542
- height: byteStream.nextTwoBytes(),
5543
- },
5544
- foregroundColor: byteStream.nextByte(),
5545
- backgroundColor: byteStream.nextByte(),
5546
- text: byteStream.readSubBlocks(),
5547
- };
5548
- break;
5549
- }
5550
- default:
5551
- byteStream.skipSubBlocks();
5552
- break;
5553
- }
5554
- }
5555
- function readBits(imageData, pos, len) {
5556
- const bytePos = pos >>> 3, bitPos = pos & 7;
5557
- return (((imageData[bytePos] + (imageData[bytePos + 1] << 8) + (imageData[bytePos + 2] << 16)) &
5558
- (((1 << len) - 1) << bitPos)) >>>
5559
- bitPos);
5560
- }
5561
- async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
5562
- const frame = gif.frames[getFrameIndex(true)];
5563
- frame.left = byteStream.nextTwoBytes();
5564
- frame.top = byteStream.nextTwoBytes();
5565
- frame.width = byteStream.nextTwoBytes();
5566
- frame.height = byteStream.nextTwoBytes();
5567
- const packedByte = byteStream.nextByte(), localColorTableFlag = (packedByte & 0x80) === 0x80, interlacedFlag = (packedByte & 0x40) === 0x40;
5568
- frame.sortFlag = (packedByte & 0x20) === 0x20;
5569
- frame.reserved = (packedByte & 0x18) >>> 3;
5570
- const localColorCount = 1 << ((packedByte & 7) + 1);
5571
- if (localColorTableFlag) {
5572
- frame.localColorTable = parseColorTable(byteStream, localColorCount);
5573
- }
5574
- const getColor = (index) => {
5575
- const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
5576
- if (index !== getTransparencyIndex(null)) {
5577
- return { r, g, b, a: 255 };
5578
- }
5579
- return { r, g, b, a: avgAlpha ? Math.trunc((r + g + b) / 3) : 0 };
5580
- }, image = (() => {
5581
- try {
5582
- return new ImageData(frame.width, frame.height, canvasSettings);
5583
- }
5584
- catch (error) {
5585
- if (error instanceof DOMException && error.name === "IndexSizeError") {
5586
- return null;
5587
- }
5588
- throw error;
5589
- }
5590
- })();
5591
- if (image == null) {
5592
- throw new EvalError("GIF frame size is to large");
5593
- }
5594
- const minCodeSize = byteStream.nextByte(), imageData = byteStream.readSubBlocksBin(), clearCode = 1 << minCodeSize;
5595
- if (interlacedFlag) {
5596
- for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
5597
- if (InterlaceOffsets[pass] < frame.height) {
5598
- let pixelPos = 0, lineIndex = 0, exit = false;
5599
- while (!exit) {
5600
- const last = code;
5601
- code = readBits(imageData, pos, size);
5602
- pos += size + 1;
5603
- if (code === clearCode) {
5604
- size = minCodeSize + 1;
5605
- dic.length = clearCode + 2;
5606
- for (let i = 0; i < dic.length; i++) {
5607
- dic[i] = i < clearCode ? [i] : [];
5608
- }
5609
- }
5610
- else {
5611
- if (code >= dic.length) {
5612
- dic.push(dic[last].concat(dic[last][0]));
5613
- }
5614
- else if (last !== clearCode) {
5615
- dic.push(dic[last].concat(dic[code][0]));
5616
- }
5617
- for (const item of dic[code]) {
5618
- const { r, g, b, a } = getColor(item);
5619
- image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width +
5620
- InterlaceSteps[pass] * lineIndex +
5621
- (pixelPos % (frame.width * 4)));
5622
- pixelPos += 4;
5623
- }
5624
- if (dic.length === 1 << size && size < 0xc) {
5625
- size++;
5626
- }
5627
- }
5628
- if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
5629
- lineIndex++;
5630
- if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
5631
- exit = true;
5632
- }
5633
- }
5634
- }
5635
- }
5636
- }
5637
- frame.image = image;
5638
- frame.bitmap = await createImageBitmap(image);
5639
- }
5640
- else {
5641
- let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4;
5642
- const dic = [[0]];
5643
- for (;;) {
5644
- const last = code;
5645
- code = readBits(imageData, pos, size);
5646
- pos += size;
5647
- if (code === clearCode) {
5648
- size = minCodeSize + 1;
5649
- dic.length = clearCode + 2;
5650
- for (let i = 0; i < dic.length; i++) {
5651
- dic[i] = i < clearCode ? [i] : [];
5652
- }
5653
- }
5654
- else {
5655
- if (code === clearCode + 1) {
5656
- break;
5657
- }
5658
- if (code >= dic.length) {
5659
- dic.push(dic[last].concat(dic[last][0]));
5660
- }
5661
- else if (last !== clearCode) {
5662
- dic.push(dic[last].concat(dic[code][0]));
5663
- }
5664
- for (const item of dic[code]) {
5665
- const { r, g, b, a } = getColor(item);
5666
- pixelPos += 4;
5667
- image.data.set([r, g, b, a], pixelPos);
5668
- }
5669
- if (dic.length >= 1 << size && size < 0xc) {
5670
- size++;
5671
- }
5672
- }
5673
- }
5674
- frame.image = image;
5675
- frame.bitmap = await createImageBitmap(image);
5676
- }
5677
- }
5678
- async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
5679
- switch (byteStream.nextByte()) {
5680
- case GIFDataHeaders.EndOfFile:
5681
- return true;
5682
- case GIFDataHeaders.Image:
5683
- await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings);
5684
- break;
5685
- case GIFDataHeaders.Extension:
5686
- parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
5687
- break;
5688
- default:
5689
- throw new EvalError("undefined block found");
5690
- }
5691
- return false;
5692
- }
5693
- function getGIFLoopAmount(gif) {
5694
- for (const extension of gif.applicationExtensions) {
5695
- if (extension.identifier + extension.authenticationCode !== "NETSCAPE2.0") {
5696
- continue;
5697
- }
5698
- return extension.data[1] + (extension.data[2] << 8);
5699
- }
5700
- return Number.NaN;
5701
- }
5702
- async function decodeGIF(gifURL, canvasSettings, progressCallback, avgAlpha) {
5703
- avgAlpha ??= false;
5704
- const res = await fetch(gifURL);
5705
- if (!res.ok && res.status === 404) {
5706
- throw new EvalError("file not found");
5707
- }
5708
- const buffer = await res.arrayBuffer(), gif = {
5709
- width: 0,
5710
- height: 0,
5711
- totalTime: 0,
5712
- colorRes: 0,
5713
- pixelAspectRatio: 0,
5714
- frames: [],
5715
- sortFlag: false,
5716
- globalColorTable: [],
5717
- backgroundImage: new ImageData(1, 1, canvasSettings),
5718
- comments: [],
5719
- applicationExtensions: [],
5720
- }, byteStream = new ByteStream(new Uint8ClampedArray(buffer));
5721
- if (byteStream.getString(6) !== "GIF89a") {
5722
- throw new Error("not a supported GIF file");
5723
- }
5724
- gif.width = byteStream.nextTwoBytes();
5725
- gif.height = byteStream.nextTwoBytes();
5726
- const packedByte = byteStream.nextByte(), globalColorTableFlag = (packedByte & 0x80) === 0x80;
5727
- gif.colorRes = (packedByte & 0x70) >>> 4;
5728
- gif.sortFlag = (packedByte & 8) === 8;
5729
- const globalColorCount = 1 << ((packedByte & 7) + 1), backgroundColorIndex = byteStream.nextByte();
5730
- gif.pixelAspectRatio = byteStream.nextByte();
5731
- if (gif.pixelAspectRatio !== 0) {
5732
- gif.pixelAspectRatio = (gif.pixelAspectRatio + 0xf) / 0x40;
5733
- }
5734
- if (globalColorTableFlag) {
5735
- gif.globalColorTable = parseColorTable(byteStream, globalColorCount);
5736
- }
5737
- const backgroundImage = (() => {
5738
- try {
5739
- return new ImageData(gif.width, gif.height, canvasSettings);
5740
- }
5741
- catch (error) {
5742
- if (error instanceof DOMException && error.name === "IndexSizeError") {
5743
- return null;
5744
- }
5745
- throw error;
5746
- }
5747
- })();
5748
- if (backgroundImage == null) {
5749
- throw new Error("GIF frame size is to large");
5750
- }
5751
- const { r, g, b } = gif.globalColorTable[backgroundColorIndex];
5752
- backgroundImage.data.set(globalColorTableFlag ? [r, g, b, 255] : [0, 0, 0, 0]);
5753
- for (let i = 4; i < backgroundImage.data.length; i *= 2) {
5754
- backgroundImage.data.copyWithin(i, 0, i);
5755
- }
5756
- gif.backgroundImage = backgroundImage;
5757
- let frameIndex = -1, incrementFrameIndex = true, transparencyIndex = -1;
5758
- const getframeIndex = (increment) => {
5759
- if (increment) {
5760
- incrementFrameIndex = true;
5761
- }
5762
- return frameIndex;
5763
- }, getTransparencyIndex = (newValue) => {
5764
- if (newValue != null) {
5765
- transparencyIndex = newValue;
5766
- }
5767
- return transparencyIndex;
5768
- };
5769
- try {
5770
- do {
5771
- if (incrementFrameIndex) {
5772
- gif.frames.push({
5773
- left: 0,
5774
- top: 0,
5775
- width: 0,
5776
- height: 0,
5777
- disposalMethod: DisposalMethod.Replace,
5778
- image: new ImageData(1, 1, canvasSettings),
5779
- plainTextData: null,
5780
- userInputDelayFlag: false,
5781
- delayTime: 0,
5782
- sortFlag: false,
5783
- localColorTable: [],
5784
- reserved: 0,
5785
- GCreserved: 0,
5786
- });
5787
- frameIndex++;
5788
- transparencyIndex = -1;
5789
- incrementFrameIndex = false;
5790
- }
5791
- } while (!(await parseBlock(byteStream, gif, avgAlpha, getframeIndex, getTransparencyIndex, canvasSettings, progressCallback)));
5792
- gif.frames.length--;
5793
- for (const frame of gif.frames) {
5794
- if (frame.userInputDelayFlag && frame.delayTime === 0) {
5795
- gif.totalTime = Infinity;
5796
- break;
5797
- }
5798
- gif.totalTime += frame.delayTime;
5799
- }
5800
- return gif;
5801
- }
5802
- catch (error) {
5803
- if (error instanceof EvalError) {
5804
- throw new Error(`error while parsing frame ${frameIndex.toString()} "${error.message}"`, { cause: error });
5805
- }
5806
- throw error;
5807
- }
5808
- }
5809
- function drawGif(data, canvasSettings) {
5810
- const { context, radius, particle, delta } = data, image = particle.image;
5811
- if (!image?.gifData || !image.gif) {
5812
- return;
5813
- }
5814
- const offscreenCanvas = new OffscreenCanvas(image.gifData.width, image.gifData.height), offscreenContext = offscreenCanvas.getContext("2d", canvasSettings);
5815
- if (!offscreenContext) {
5816
- throw new Error("could not create offscreen canvas context");
5817
- }
5818
- offscreenContext.imageSmoothingQuality = "low";
5819
- offscreenContext.imageSmoothingEnabled = false;
5820
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
5821
- particle.gifLoopCount ??= image.gifLoopCount ?? defaultLoopCount;
5822
- let frameIndex = particle.gifFrame ?? defaultFrame;
5823
- const pos = { x: -image.gifData.width * half, y: -image.gifData.height * half }, frame = image.gifData.frames[frameIndex];
5824
- particle.gifTime ??= initialTime;
5825
- if (!frame.bitmap) {
5826
- return;
5827
- }
5828
- context.scale(radius / image.gifData.width, radius / image.gifData.height);
5829
- switch (frame.disposalMethod) {
5830
- case DisposalMethod.UndefinedA:
5831
- case DisposalMethod.UndefinedB:
5832
- case DisposalMethod.UndefinedC:
5833
- case DisposalMethod.UndefinedD:
5834
- case DisposalMethod.Replace:
5835
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
5836
- context.drawImage(offscreenCanvas, pos.x, pos.y);
5837
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
5838
- break;
5839
- case DisposalMethod.Combine:
5840
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
5841
- context.drawImage(offscreenCanvas, pos.x, pos.y);
5842
- break;
5843
- case DisposalMethod.RestoreBackground:
5844
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
5845
- context.drawImage(offscreenCanvas, pos.x, pos.y);
5846
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
5847
- if (!image.gifData.globalColorTable.length) {
5848
- offscreenContext.putImageData(image.gifData.frames[firstIndex].image, pos.x + frame.left, pos.y + frame.top);
5849
- }
5850
- else {
5851
- offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
5852
- }
5853
- break;
5854
- case DisposalMethod.RestorePrevious:
5855
- {
5856
- const previousImageData = offscreenContext.getImageData(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
5857
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
5858
- context.drawImage(offscreenCanvas, pos.x, pos.y);
5859
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
5860
- offscreenContext.putImageData(previousImageData, originPoint.x, originPoint.y);
5861
- }
5862
- break;
5863
- }
5864
- particle.gifTime += delta.value;
5865
- if (particle.gifTime > frame.delayTime) {
5866
- particle.gifTime -= frame.delayTime;
5867
- if (++frameIndex >= image.gifData.frames.length) {
5868
- if (--particle.gifLoopCount <= defaultLoopCount) {
5869
- return;
5870
- }
5871
- frameIndex = firstIndex;
5872
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
5873
- }
5874
- particle.gifFrame = frameIndex;
5875
- }
5876
- context.scale(image.gifData.width / radius, image.gifData.height / radius);
5877
- }
5878
- async function loadGifImage(image, canvasSettings) {
5879
- if (image.type !== "gif") {
5880
- await loadImage(image);
5881
- return;
5882
- }
5883
- image.loading = true;
5884
- try {
5885
- image.gifData = await decodeGIF(image.source, canvasSettings);
5886
- image.gifLoopCount = getGIFLoopAmount(image.gifData);
5887
- if (!image.gifLoopCount) {
5888
- image.gifLoopCount = Infinity;
5889
- }
5890
- }
5891
- catch {
5892
- image.error = true;
5893
- }
5894
- image.loading = false;
5895
- }
5896
-
5897
5507
  const sides$3 = 12;
5898
5508
  class ImageDrawer {
5899
5509
  #container;
@@ -5908,10 +5518,7 @@
5908
5518
  return;
5909
5519
  }
5910
5520
  context.globalAlpha = opacity;
5911
- if (image.gif && image.gifData) {
5912
- drawGif(data, this.#container.canvas.render.settings);
5913
- }
5914
- else if (element) {
5521
+ if (element) {
5915
5522
  const ratio = image.ratio, pos = {
5916
5523
  x: -radius,
5917
5524
  y: -radius,
@@ -5980,9 +5587,6 @@
5980
5587
  color,
5981
5588
  data: image,
5982
5589
  element: image.element,
5983
- gif: image.gif,
5984
- gifData: image.gifData,
5985
- gifLoopCount: image.gifLoopCount,
5986
5590
  loaded: true,
5987
5591
  ratio: imageData.width && imageData.height ? imageData.width / imageData.height : (image.ratio ?? defaultRatio$1),
5988
5592
  replaceColor: replaceColor,
@@ -6005,7 +5609,6 @@
6005
5609
  throw new Error(`Image shape not initialized`);
6006
5610
  }
6007
5611
  await this.#engine.loadImage(container, {
6008
- gif: imageShape.gif,
6009
5612
  name: imageShape.name,
6010
5613
  replaceColor: imageShape.replaceColor,
6011
5614
  src: imageShape.src,
@@ -6014,7 +5617,6 @@
6014
5617
  }
6015
5618
 
6016
5619
  class Preload {
6017
- gif = false;
6018
5620
  height;
6019
5621
  name;
6020
5622
  replaceColor;
@@ -6024,7 +5626,6 @@
6024
5626
  if (isNull(data)) {
6025
5627
  return;
6026
5628
  }
6027
- loadProperty(this, "gif", data.gif);
6028
5629
  loadProperty(this, "height", data.height);
6029
5630
  loadProperty(this, "name", data.name);
6030
5631
  loadProperty(this, "replaceColor", data.replaceColor);
@@ -6091,7 +5692,6 @@
6091
5692
  }
6092
5693
  try {
6093
5694
  const image = {
6094
- gif: data.gif,
6095
5695
  name: data.name ?? data.src,
6096
5696
  source: data.src,
6097
5697
  type: data.src.substring(data.src.length - extLength),
@@ -6103,10 +5703,7 @@
6103
5703
  containerImages.push(image);
6104
5704
  engine.images.set(container, containerImages);
6105
5705
  let imageFunc;
6106
- if (data.gif) {
6107
- imageFunc = (img) => loadGifImage(img, { colorSpace: "srgb" });
6108
- }
6109
- else if (data.replaceColor) {
5706
+ if (data.replaceColor) {
6110
5707
  imageFunc = downloadSvgImage;
6111
5708
  }
6112
5709
  else {
@@ -6120,7 +5717,7 @@
6120
5717
  };
6121
5718
  }
6122
5719
  async function loadImageShape(engine) {
6123
- engine.checkVersion("4.2.1");
5720
+ engine.checkVersion("4.3.1");
6124
5721
  await engine.pluginManager.register(e => {
6125
5722
  addLoadImageToEngine(e);
6126
5723
  e.pluginManager.addPlugin(new ImagePreloaderPlugin(e));
@@ -6265,7 +5862,7 @@
6265
5862
  }
6266
5863
 
6267
5864
  async function loadLifeUpdater(engine) {
6268
- engine.checkVersion("4.2.1");
5865
+ engine.checkVersion("4.3.1");
6269
5866
  await engine.pluginManager.register(e => {
6270
5867
  e.pluginManager.addParticleUpdater("life", container => {
6271
5868
  return Promise.resolve(new LifeUpdater(container));
@@ -6291,7 +5888,7 @@
6291
5888
  }
6292
5889
 
6293
5890
  async function loadLineShape(engine) {
6294
- engine.checkVersion("4.2.1");
5891
+ engine.checkVersion("4.3.1");
6295
5892
  await engine.pluginManager.register(e => {
6296
5893
  e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
6297
5894
  });
@@ -6375,7 +5972,7 @@
6375
5972
  }
6376
5973
 
6377
5974
  async function loadParticlesAttractInteraction(engine) {
6378
- engine.checkVersion("4.2.1");
5975
+ engine.checkVersion("4.3.1");
6379
5976
  await engine.pluginManager.register((e) => {
6380
5977
  ensureInteractivityPluginLoaded(e);
6381
5978
  e.pluginManager.addInteractor?.("particlesAttract", container => {
@@ -6585,7 +6182,7 @@
6585
6182
  }
6586
6183
 
6587
6184
  async function loadParticlesCollisionsInteraction(engine) {
6588
- engine.checkVersion("4.2.1");
6185
+ engine.checkVersion("4.3.1");
6589
6186
  await engine.pluginManager.register((e) => {
6590
6187
  ensureInteractivityPluginLoaded(e);
6591
6188
  e.pluginManager.addPlugin(new OverlapPlugin());
@@ -6839,7 +6436,7 @@
6839
6436
  }
6840
6437
 
6841
6438
  async function loadParticlesLinksInteraction(engine) {
6842
- engine.checkVersion("4.2.1");
6439
+ engine.checkVersion("4.3.1");
6843
6440
  await engine.pluginManager.register((e) => {
6844
6441
  const pluginManager = e.pluginManager;
6845
6442
  ensureInteractivityPluginLoaded(e);
@@ -6929,19 +6526,19 @@
6929
6526
  }
6930
6527
 
6931
6528
  async function loadGenericPolygonShape(engine) {
6932
- engine.checkVersion("4.2.1");
6529
+ engine.checkVersion("4.3.1");
6933
6530
  await engine.pluginManager.register(e => {
6934
6531
  e.pluginManager.addShape(["polygon"], () => Promise.resolve(new PolygonDrawer()));
6935
6532
  });
6936
6533
  }
6937
6534
  async function loadTriangleShape(engine) {
6938
- engine.checkVersion("4.2.1");
6535
+ engine.checkVersion("4.3.1");
6939
6536
  await engine.pluginManager.register(e => {
6940
6537
  e.pluginManager.addShape(["triangle"], () => Promise.resolve(new TriangleDrawer()));
6941
6538
  });
6942
6539
  }
6943
6540
  async function loadPolygonShape(engine) {
6944
- engine.checkVersion("4.2.1");
6541
+ engine.checkVersion("4.3.1");
6945
6542
  await Promise.all([
6946
6543
  loadGenericPolygonShape(engine),
6947
6544
  loadTriangleShape(engine),
@@ -7046,7 +6643,7 @@
7046
6643
  }
7047
6644
 
7048
6645
  async function loadRotateUpdater(engine) {
7049
- engine.checkVersion("4.2.1");
6646
+ engine.checkVersion("4.3.1");
7050
6647
  await engine.pluginManager.register(e => {
7051
6648
  e.pluginManager.addParticleUpdater("rotate", container => {
7052
6649
  return Promise.resolve(new RotateUpdater(container));
@@ -7070,7 +6667,7 @@
7070
6667
  }
7071
6668
 
7072
6669
  async function loadSquareShape(engine) {
7073
- engine.checkVersion("4.2.1");
6670
+ engine.checkVersion("4.3.1");
7074
6671
  await engine.pluginManager.register(e => {
7075
6672
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
7076
6673
  });
@@ -7104,14 +6701,14 @@
7104
6701
  }
7105
6702
 
7106
6703
  async function loadStarShape(engine) {
7107
- engine.checkVersion("4.2.1");
6704
+ engine.checkVersion("4.3.1");
7108
6705
  await engine.pluginManager.register(e => {
7109
6706
  e.pluginManager.addShape(["star"], () => Promise.resolve(new StarDrawer()));
7110
6707
  });
7111
6708
  }
7112
6709
 
7113
6710
  async function loadSlim(engine) {
7114
- engine.checkVersion("4.2.1");
6711
+ engine.checkVersion("4.3.1");
7115
6712
  await engine.pluginManager.register(async (e) => {
7116
6713
  const loadInteractivityForSlim = async (e) => {
7117
6714
  await loadInteractivityPlugin(e);
@@ -7162,10 +6759,10 @@
7162
6759
  }
7163
6760
  }
7164
6761
  class RenderManager {
6762
+ #backgroundElement;
6763
+ #backgroundWarnings;
7165
6764
  #canvasClearPlugins;
7166
6765
  #canvasManager;
7167
- #canvasPaintPlugins;
7168
- #clearDrawPlugins;
7169
6766
  #colorPlugins;
7170
6767
  #container;
7171
6768
  #context;
@@ -7173,9 +6770,7 @@
7173
6770
  #drawParticlePlugins;
7174
6771
  #drawParticlesCleanupPlugins;
7175
6772
  #drawParticlesSetupPlugins;
7176
- #drawPlugins;
7177
- #drawSettingsCleanupPlugins;
7178
- #drawSettingsSetupPlugins;
6773
+ #layers;
7179
6774
  #pluginManager;
7180
6775
  #postDrawUpdaters;
7181
6776
  #preDrawUpdaters;
@@ -7187,18 +6782,25 @@
7187
6782
  this.#container = container;
7188
6783
  this.#canvasManager = canvasManager;
7189
6784
  this.#context = null;
6785
+ this.#backgroundElement = null;
6786
+ this.#backgroundWarnings = new Set();
7190
6787
  this.#preDrawUpdaters = [];
7191
6788
  this.#postDrawUpdaters = [];
7192
- this.#colorPlugins = [];
7193
6789
  this.#canvasClearPlugins = [];
7194
- this.#canvasPaintPlugins = [];
7195
- this.#clearDrawPlugins = [];
6790
+ this.#colorPlugins = [];
7196
6791
  this.#drawParticlePlugins = [];
7197
6792
  this.#drawParticlesCleanupPlugins = [];
7198
6793
  this.#drawParticlesSetupPlugins = [];
7199
- this.#drawPlugins = [];
7200
- this.#drawSettingsSetupPlugins = [];
7201
- this.#drawSettingsCleanupPlugins = [];
6794
+ this.#layers = {
6795
+ 0: [],
6796
+ 1: [],
6797
+ 2: [],
6798
+ 3: [],
6799
+ 4: [],
6800
+ 5: [],
6801
+ 6: [],
6802
+ 7: [],
6803
+ };
7202
6804
  }
7203
6805
  get settings() {
7204
6806
  return this.#contextSettings;
@@ -7212,32 +6814,38 @@
7212
6814
  });
7213
6815
  }
7214
6816
  clear() {
7215
- let pluginHandled = false;
7216
6817
  for (const plugin of this.#canvasClearPlugins) {
7217
- pluginHandled = plugin.canvasClear?.() ?? false;
7218
- if (pluginHandled) {
7219
- break;
6818
+ if (plugin.canvasClear?.() ?? false) {
6819
+ return;
7220
6820
  }
7221
6821
  }
7222
- if (pluginHandled) {
7223
- return;
6822
+ for (const layer of Object.values(exports.DrawLayer)) {
6823
+ if (typeof layer === "number") {
6824
+ for (const plugin of this.#getLayerPlugins(layer)) {
6825
+ if (plugin.canvasClear?.() ?? false) {
6826
+ return;
6827
+ }
6828
+ }
6829
+ }
7224
6830
  }
7225
6831
  this.canvasClear();
7226
6832
  }
7227
6833
  destroy() {
7228
6834
  this.stop();
6835
+ this.#backgroundElement = null;
6836
+ this.#backgroundWarnings.clear();
7229
6837
  this.#preDrawUpdaters = [];
7230
6838
  this.#postDrawUpdaters = [];
7231
- this.#colorPlugins = [];
7232
6839
  this.#canvasClearPlugins = [];
7233
- this.#canvasPaintPlugins = [];
7234
- this.#clearDrawPlugins = [];
6840
+ this.#colorPlugins = [];
7235
6841
  this.#drawParticlePlugins = [];
7236
6842
  this.#drawParticlesCleanupPlugins = [];
7237
6843
  this.#drawParticlesSetupPlugins = [];
7238
- this.#drawPlugins = [];
7239
- this.#drawSettingsSetupPlugins = [];
7240
- this.#drawSettingsCleanupPlugins = [];
6844
+ for (const layer of Object.values(exports.DrawLayer)) {
6845
+ if (typeof layer === "number") {
6846
+ this.#layers[layer] = [];
6847
+ }
6848
+ }
7241
6849
  }
7242
6850
  draw(cb) {
7243
6851
  const ctx = this.#context;
@@ -7294,21 +6902,40 @@
7294
6902
  });
7295
6903
  }
7296
6904
  drawParticles(delta) {
7297
- const { particles } = this.#container;
6905
+ const { particles, actualOptions } = this.#container;
7298
6906
  this.clear();
7299
6907
  particles.update(delta);
7300
6908
  this.draw(ctx => {
7301
- for (const plugin of this.#drawSettingsSetupPlugins) {
6909
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
6910
+ if (this.#backgroundElement) {
6911
+ try {
6912
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
6913
+ }
6914
+ catch {
6915
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
6916
+ }
6917
+ }
6918
+ const background = actualOptions.background;
6919
+ if (background.draw) {
6920
+ try {
6921
+ background.draw(ctx, delta);
6922
+ }
6923
+ catch {
6924
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
6925
+ }
6926
+ }
6927
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
6928
+ plugin.canvasPaint?.();
6929
+ }
6930
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
7302
6931
  plugin.drawSettingsSetup?.(ctx, delta);
7303
6932
  }
7304
- for (const plugin of this.#drawPlugins) {
6933
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.PluginContent)) {
7305
6934
  plugin.draw?.(ctx, delta);
7306
6935
  }
7307
6936
  particles.drawParticles(delta);
7308
- for (const plugin of this.#clearDrawPlugins) {
6937
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup)) {
7309
6938
  plugin.clearDraw?.(ctx, delta);
7310
- }
7311
- for (const plugin of this.#drawSettingsCleanupPlugins) {
7312
6939
  plugin.drawSettingsCleanup?.(ctx, delta);
7313
6940
  }
7314
6941
  });
@@ -7316,29 +6943,24 @@
7316
6943
  init() {
7317
6944
  this.initUpdaters();
7318
6945
  this.initPlugins();
6946
+ this.#resolveBackgroundElement();
7319
6947
  this.paint();
7320
6948
  }
7321
6949
  initPlugins() {
7322
- this.#colorPlugins = [];
7323
6950
  this.#canvasClearPlugins = [];
7324
- this.#canvasPaintPlugins = [];
7325
- this.#clearDrawPlugins = [];
6951
+ this.#colorPlugins = [];
7326
6952
  this.#drawParticlePlugins = [];
7327
6953
  this.#drawParticlesSetupPlugins = [];
7328
6954
  this.#drawParticlesCleanupPlugins = [];
7329
- this.#drawPlugins = [];
7330
- this.#drawSettingsSetupPlugins = [];
7331
- this.#drawSettingsCleanupPlugins = [];
6955
+ for (const layer of Object.values(exports.DrawLayer)) {
6956
+ if (typeof layer === "number") {
6957
+ this.#layers[layer] = [];
6958
+ }
6959
+ }
7332
6960
  for (const plugin of this.#container.plugins) {
7333
6961
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
7334
6962
  this.#colorPlugins.push(plugin);
7335
6963
  }
7336
- if (plugin.canvasClear) {
7337
- this.#canvasClearPlugins.push(plugin);
7338
- }
7339
- if (plugin.canvasPaint) {
7340
- this.#canvasPaintPlugins.push(plugin);
7341
- }
7342
6964
  if (plugin.drawParticle) {
7343
6965
  this.#drawParticlePlugins.push(plugin);
7344
6966
  }
@@ -7348,17 +6970,20 @@
7348
6970
  if (plugin.drawParticleCleanup) {
7349
6971
  this.#drawParticlesCleanupPlugins.push(plugin);
7350
6972
  }
7351
- if (plugin.draw) {
7352
- this.#drawPlugins.push(plugin);
6973
+ if (plugin.canvasClear) {
6974
+ this.#canvasClearPlugins.push(plugin);
6975
+ }
6976
+ if (plugin.canvasPaint) {
6977
+ this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
7353
6978
  }
7354
6979
  if (plugin.drawSettingsSetup) {
7355
- this.#drawSettingsSetupPlugins.push(plugin);
6980
+ this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
7356
6981
  }
7357
- if (plugin.drawSettingsCleanup) {
7358
- this.#drawSettingsCleanupPlugins.push(plugin);
6982
+ if (plugin.draw) {
6983
+ this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
7359
6984
  }
7360
- if (plugin.clearDraw) {
7361
- this.#clearDrawPlugins.push(plugin);
6985
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
6986
+ this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
7362
6987
  }
7363
6988
  }
7364
6989
  }
@@ -7376,7 +7001,7 @@
7376
7001
  }
7377
7002
  paint() {
7378
7003
  let handled = false;
7379
- for (const plugin of this.#canvasPaintPlugins) {
7004
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
7380
7005
  handled = plugin.canvasPaint?.() ?? false;
7381
7006
  if (handled) {
7382
7007
  break;
@@ -7549,6 +7174,9 @@
7549
7174
  }
7550
7175
  drawer.beforeDraw(data);
7551
7176
  }
7177
+ #getLayerPlugins(layer) {
7178
+ return this.#layers[layer];
7179
+ }
7552
7180
  #getPluginParticleColors(particle) {
7553
7181
  let fColor, sColor;
7554
7182
  for (const plugin of this.#colorPlugins) {
@@ -7566,6 +7194,39 @@
7566
7194
  this.#reusablePluginColors[sColorIndex] = sColor;
7567
7195
  return this.#reusablePluginColors;
7568
7196
  }
7197
+ #resolveBackgroundElement() {
7198
+ const background = this.#container.actualOptions.background;
7199
+ this.#backgroundElement = null;
7200
+ if (!background.element) {
7201
+ return;
7202
+ }
7203
+ if (typeof background.element === "string") {
7204
+ if (typeof document !== "undefined") {
7205
+ const node = document.querySelector(background.element);
7206
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
7207
+ this.#backgroundElement = node;
7208
+ }
7209
+ else if (node) {
7210
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
7211
+ }
7212
+ else {
7213
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
7214
+ }
7215
+ }
7216
+ }
7217
+ else if (background.element instanceof HTMLCanvasElement ||
7218
+ background.element instanceof OffscreenCanvas ||
7219
+ background.element instanceof HTMLVideoElement ||
7220
+ background.element instanceof HTMLImageElement) {
7221
+ this.#backgroundElement = background.element;
7222
+ }
7223
+ }
7224
+ #warnOnce(key, message) {
7225
+ if (!this.#backgroundWarnings.has(key)) {
7226
+ this.#backgroundWarnings.add(key);
7227
+ getLogger().warning(message);
7228
+ }
7229
+ }
7569
7230
  }
7570
7231
 
7571
7232
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -8142,7 +7803,6 @@
8142
7803
  }
8143
7804
  class Particle {
8144
7805
  backColor;
8145
- bubble;
8146
7806
  destroyed;
8147
7807
  direction;
8148
7808
  effect;
@@ -8176,7 +7836,6 @@
8176
7836
  shapeData;
8177
7837
  sides;
8178
7838
  size;
8179
- slow;
8180
7839
  spawning;
8181
7840
  strokeColor;
8182
7841
  strokeOpacity;
@@ -8198,18 +7857,25 @@
8198
7857
  d: 1,
8199
7858
  };
8200
7859
  #container;
7860
+ #modifiers = [];
8201
7861
  #pluginManager;
8202
7862
  constructor(pluginManager, container) {
8203
7863
  this.#pluginManager = pluginManager;
8204
7864
  this.#container = container;
8205
7865
  }
7866
+ addModifier(modifier) {
7867
+ this.#modifiers.push(modifier);
7868
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
7869
+ }
7870
+ clearModifiers() {
7871
+ this.#modifiers.length = 0;
7872
+ }
8206
7873
  destroy(override) {
8207
7874
  if (this.unbreakable || this.destroyed) {
8208
7875
  return;
8209
7876
  }
8210
7877
  this.destroyed = true;
8211
- this.bubble.inRange = false;
8212
- this.slow.inRange = false;
7878
+ this.clearModifiers();
8213
7879
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
8214
7880
  shapeDrawer?.particleDestroy?.(this);
8215
7881
  for (const plugin of container.particleDestroyedPlugins) {
@@ -8231,13 +7897,16 @@
8231
7897
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
8232
7898
  }
8233
7899
  getFillColor() {
8234
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
7900
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
8235
7901
  }
8236
7902
  getMass() {
8237
7903
  return this.getRadius() ** squareExp * Math.PI * half;
8238
7904
  }
7905
+ getModifier(id) {
7906
+ return this.#modifiers.find(m => m.id === id);
7907
+ }
8239
7908
  getOpacity() {
8240
- const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, opacity = this.bubble.opacity ?? getRangeValue(this.opacity?.value ?? defaultOpacity$3), fillOpacity = this.fillOpacity ?? defaultOpacity$3, strokeOpacity = this.strokeOpacity ?? defaultOpacity$3;
7909
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$3), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$3, strokeOpacity = this.strokeOpacity ?? defaultOpacity$3;
8241
7910
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
8242
7911
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
8243
7912
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -8250,7 +7919,7 @@
8250
7919
  return this.#cachedPosition;
8251
7920
  }
8252
7921
  getRadius() {
8253
- return this.bubble.radius ?? this.size.value;
7922
+ return this.#applyModifiers(this.size.value, m => m.radius);
8254
7923
  }
8255
7924
  getRotateData() {
8256
7925
  const angle = this.getAngle();
@@ -8259,7 +7928,7 @@
8259
7928
  return this.#cachedRotateData;
8260
7929
  }
8261
7930
  getStrokeColor() {
8262
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
7931
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
8263
7932
  }
8264
7933
  getTransformData(externalTransform) {
8265
7934
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -8279,13 +7948,6 @@
8279
7948
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
8280
7949
  container.retina.initParticle(this);
8281
7950
  runUpdaterPreInit(container.particleUpdaters, this);
8282
- this.bubble = {
8283
- inRange: false,
8284
- };
8285
- this.slow = {
8286
- inRange: false,
8287
- factor: 1,
8288
- };
8289
7951
  this.#initPosition(position);
8290
7952
  this.initialVelocity = this.#calculateVelocity();
8291
7953
  this.velocity = this.initialVelocity.copy();
@@ -8325,11 +7987,29 @@
8325
7987
  isVisible() {
8326
7988
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
8327
7989
  }
7990
+ removeModifier(id) {
7991
+ const idx = this.#modifiers.findIndex(m => m.id === id);
7992
+ if (idx >= defaultAngle) {
7993
+ this.#modifiers.splice(idx, identity$2);
7994
+ }
7995
+ }
8328
7996
  reset() {
8329
7997
  for (const updater of this.#container.particleUpdaters) {
8330
7998
  updater.reset?.(this);
8331
7999
  }
8332
8000
  }
8001
+ #applyModifiers(base, getter) {
8002
+ let value = base;
8003
+ for (const mod of this.#modifiers) {
8004
+ if (mod.enabled) {
8005
+ const override = getter(mod);
8006
+ if (override !== undefined) {
8007
+ value = override;
8008
+ }
8009
+ }
8010
+ }
8011
+ return value;
8012
+ }
8333
8013
  #calcPosition(position, zIndex) {
8334
8014
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
8335
8015
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -9431,6 +9111,7 @@
9431
9111
  });
9432
9112
 
9433
9113
  class BlendPluginInstance {
9114
+ layer = exports.DrawLayer.CanvasSetup;
9434
9115
  #container;
9435
9116
  #defaultCompositeValue;
9436
9117
  constructor(container) {
@@ -9576,7 +9257,8 @@
9576
9257
  particle.lastPathTime -= pathDelay;
9577
9258
  }
9578
9259
  function getProximitySpeedFactor(particle) {
9579
- return particle.slow.inRange ? particle.slow.factor : identity$2;
9260
+ const mod = particle.getModifier("slow");
9261
+ return mod?.enabled ? (mod.speedFactor ?? identity$2) : identity$2;
9580
9262
  }
9581
9263
  function initSpin(container, particle) {
9582
9264
  const options = particle.options, spinOptions = options.move.spin;
@@ -10568,6 +10250,7 @@
10568
10250
  exports.hPhase = hPhase;
10569
10251
  exports.half = half;
10570
10252
  exports.hslToRgb = hslToRgb;
10253
+ exports.hslToRgbFloat = hslToRgbFloat;
10571
10254
  exports.hslaToRgba = hslaToRgba;
10572
10255
  exports.identity = identity$2;
10573
10256
  exports.inverseFactorNumerator = inverseFactorNumerator;