tsparticles 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
- /* tsParticles v4.2.0 */
2
+ /* tsParticles v4.3.0 */
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
5
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -398,29 +398,27 @@
398
398
  }
399
399
  }
400
400
  else if (!isObject(destination) || Array.isArray(destination)) {
401
- destination = {};
401
+ destination = Object.create(null);
402
402
  }
403
- const sourceKeys = Object.keys(source), dangerousKeys = new Set(["__proto__", "constructor", "prototype"]), hasNested = sourceKeys.some(k => {
403
+ const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
404
404
  const v = source[k];
405
405
  return isObject(v) || Array.isArray(v);
406
406
  });
407
407
  if (!hasNested) {
408
408
  const sourceDict = source, destDict = destination;
409
409
  for (const key of sourceKeys) {
410
- if (dangerousKeys.has(key)) {
410
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
411
411
  continue;
412
412
  }
413
- if (key in sourceDict) {
414
- const v = sourceDict[key];
415
- if (v !== undefined) {
416
- destDict[key] = v;
417
- }
413
+ const v = sourceDict[key];
414
+ if (v !== undefined) {
415
+ destDict[key] = v;
418
416
  }
419
417
  }
420
418
  continue;
421
419
  }
422
420
  for (const key of sourceKeys) {
423
- if (dangerousKeys.has(key)) {
421
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
424
422
  continue;
425
423
  }
426
424
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -879,7 +877,7 @@
879
877
  return this.#domArray;
880
878
  }
881
879
  get version() {
882
- return "4.2.0";
880
+ return "4.3.0";
883
881
  }
884
882
  addEventListener(type, listener) {
885
883
  this.#eventDispatcher.addEventListener(type, listener);
@@ -1112,6 +1110,18 @@
1112
1110
  AnimationStatus["decreasing"] = "decreasing";
1113
1111
  })(exports.AnimationStatus || (exports.AnimationStatus = {}));
1114
1112
 
1113
+ exports.DrawLayer = void 0;
1114
+ (function (DrawLayer) {
1115
+ DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
1116
+ DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
1117
+ DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
1118
+ DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
1119
+ DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
1120
+ DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
1121
+ DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
1122
+ DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1123
+ })(exports.DrawLayer || (exports.DrawLayer = {}));
1124
+
1115
1125
  class OptionLoader {
1116
1126
  load(data) {
1117
1127
  if (isNull(data)) {
@@ -1270,6 +1280,8 @@
1270
1280
 
1271
1281
  class Background extends OptionLoader {
1272
1282
  color;
1283
+ draw;
1284
+ element;
1273
1285
  image = "";
1274
1286
  opacity = 1;
1275
1287
  position = "";
@@ -1284,6 +1296,8 @@
1284
1296
  if (data.color !== undefined) {
1285
1297
  this.color = OptionsColor.create(this.color, data.color);
1286
1298
  }
1299
+ loadProperty(this, "element", data.element);
1300
+ loadProperty(this, "draw", data.draw);
1287
1301
  loadProperty(this, "image", data.image);
1288
1302
  loadProperty(this, "position", data.position);
1289
1303
  loadProperty(this, "repeat", data.repeat);
@@ -1829,7 +1843,7 @@
1829
1843
  }
1830
1844
  }
1831
1845
 
1832
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
1846
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1833
1847
  function getCachedStyle(key, generator) {
1834
1848
  let cached = styleCache.get(key);
1835
1849
  if (!cached) {
@@ -1972,6 +1986,17 @@
1972
1986
  : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
1973
1987
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1974
1988
  }
1989
+ function hslToRgbFloat(hsl) {
1990
+ const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
1991
+ if (s === sMin) {
1992
+ const grayscaleValue = lNormalized * rgbMax;
1993
+ return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1994
+ }
1995
+ const temp1 = lNormalized < half
1996
+ ? lNormalized * (sNormalizedOffset + sNormalized)
1997
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
1998
+ return { r: red, g: green, b: blue };
1999
+ }
1975
2000
  function hslaToRgba(hsla) {
1976
2001
  const rgbResult = hslToRgb(hsla);
1977
2002
  return {
@@ -1981,8 +2006,16 @@
1981
2006
  r: rgbResult.r,
1982
2007
  };
1983
2008
  }
1984
- function getRandomRgbColor(min) {
1985
- const fixedMin = min ?? defaultRgbMin, fixedMax = rgbMax + identity$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 {
@@ -2413,7 +2446,7 @@
2413
2446
  }
2414
2447
 
2415
2448
  async function loadInteractivityPlugin(engine) {
2416
- engine.checkVersion("4.2.0");
2449
+ engine.checkVersion("4.3.0");
2417
2450
  await engine.pluginManager.register(e => {
2418
2451
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
2419
2452
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -2653,7 +2686,7 @@
2653
2686
  }
2654
2687
 
2655
2688
  async function loadAbsorbersInteraction(engine) {
2656
- engine.checkVersion("4.2.0");
2689
+ engine.checkVersion("4.3.0");
2657
2690
  await engine.pluginManager.register(async (e) => {
2658
2691
  const pluginManager = e.pluginManager, instancesManager = await getAbsorbersInstancesManager(e);
2659
2692
  ensureInteractivityPluginLoaded(e);
@@ -2701,7 +2734,7 @@
2701
2734
  }
2702
2735
 
2703
2736
  async function loadAbsorbersPluginSimple(engine) {
2704
- engine.checkVersion("4.2.0");
2737
+ engine.checkVersion("4.3.0");
2705
2738
  await engine.pluginManager.register(async (e) => {
2706
2739
  const pluginManager = e.pluginManager, instancesManager = await getAbsorbersInstancesManager(e);
2707
2740
  pluginManager.addPlugin(new AbsorbersPlugin(instancesManager));
@@ -3027,7 +3060,7 @@
3027
3060
  }
3028
3061
 
3029
3062
  async function loadDestroyUpdater(engine) {
3030
- engine.checkVersion("4.2.0");
3063
+ engine.checkVersion("4.3.0");
3031
3064
  await engine.pluginManager.register(e => {
3032
3065
  e.pluginManager.addParticleUpdater("destroy", container => {
3033
3066
  return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
@@ -3345,7 +3378,7 @@
3345
3378
  })(EmitterClickMode || (EmitterClickMode = {}));
3346
3379
 
3347
3380
  async function loadEmittersInteraction(engine) {
3348
- engine.checkVersion("4.2.0");
3381
+ engine.checkVersion("4.3.0");
3349
3382
  await engine.pluginManager.register(async (e) => {
3350
3383
  const instancesManager = await getEmittersInstancesManager(e);
3351
3384
  ensureInteractivityPluginLoaded(e);
@@ -3388,7 +3421,7 @@
3388
3421
  }
3389
3422
 
3390
3423
  async function loadEmittersPluginSimple(engine) {
3391
- engine.checkVersion("4.2.0");
3424
+ engine.checkVersion("4.3.0");
3392
3425
  await engine.pluginManager.register(async (e) => {
3393
3426
  const instancesManager = await getEmittersInstancesManager(e);
3394
3427
  await addEmittersShapesManager(e);
@@ -3445,7 +3478,7 @@
3445
3478
  }
3446
3479
 
3447
3480
  async function loadEmittersShapeCircle(engine) {
3448
- engine.checkVersion("4.2.0");
3481
+ engine.checkVersion("4.3.0");
3449
3482
  await engine.pluginManager.register((e) => {
3450
3483
  ensureEmittersPluginLoaded(e);
3451
3484
  e.pluginManager.addEmitterShapeGenerator?.("circle", new EmittersCircleShapeGenerator());
@@ -3526,7 +3559,7 @@
3526
3559
  }
3527
3560
 
3528
3561
  async function loadEmittersShapeSquare(engine) {
3529
- engine.checkVersion("4.2.0");
3562
+ engine.checkVersion("4.3.0");
3530
3563
  await engine.pluginManager.register((e) => {
3531
3564
  ensureEmittersPluginLoaded(e);
3532
3565
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -3708,7 +3741,7 @@
3708
3741
  }
3709
3742
 
3710
3743
  async function loadExternalDragInteraction(engine) {
3711
- engine.checkVersion("4.2.0");
3744
+ engine.checkVersion("4.3.0");
3712
3745
  await engine.pluginManager.register((e) => {
3713
3746
  ensureInteractivityPluginLoaded(e);
3714
3747
  e.pluginManager.addInteractor?.("externalDrag", container => {
@@ -3881,7 +3914,7 @@
3881
3914
  }
3882
3915
 
3883
3916
  async function loadExternalTrailInteraction(engine) {
3884
- engine.checkVersion("4.2.0");
3917
+ engine.checkVersion("4.3.0");
3885
3918
  await engine.pluginManager.register((e) => {
3886
3919
  ensureInteractivityPluginLoaded(e);
3887
3920
  e.pluginManager.addInteractor?.("externalTrail", container => {
@@ -4017,7 +4050,7 @@
4017
4050
  }
4018
4051
 
4019
4052
  async function loadRollUpdater(engine) {
4020
- engine.checkVersion("4.2.0");
4053
+ engine.checkVersion("4.3.0");
4021
4054
  await engine.pluginManager.register(e => {
4022
4055
  e.pluginManager.addParticleUpdater("roll", () => {
4023
4056
  return Promise.resolve(new RollUpdater(e.pluginManager));
@@ -4063,7 +4096,7 @@
4063
4096
  }
4064
4097
 
4065
4098
  async function loadBlendPlugin(engine) {
4066
- engine.checkVersion("4.2.0");
4099
+ engine.checkVersion("4.3.0");
4067
4100
  await engine.pluginManager.register(e => {
4068
4101
  e.pluginManager.addPlugin(new BlendPlugin());
4069
4102
  });
@@ -4100,7 +4133,7 @@
4100
4133
  }
4101
4134
 
4102
4135
  async function loadCircleShape(engine) {
4103
- engine.checkVersion("4.2.0");
4136
+ engine.checkVersion("4.3.0");
4104
4137
  await engine.pluginManager.register(e => {
4105
4138
  e.pluginManager.addShape(["circle"], () => {
4106
4139
  return Promise.resolve(new CircleDrawer());
@@ -4148,7 +4181,7 @@
4148
4181
  }
4149
4182
 
4150
4183
  async function loadHexColorPlugin(engine) {
4151
- engine.checkVersion("4.2.0");
4184
+ engine.checkVersion("4.3.0");
4152
4185
  await engine.pluginManager.register(e => {
4153
4186
  e.pluginManager.addColorManager("hex", new HexColorManager());
4154
4187
  });
@@ -4201,7 +4234,7 @@
4201
4234
  }
4202
4235
 
4203
4236
  async function loadHslColorPlugin(engine) {
4204
- engine.checkVersion("4.2.0");
4237
+ engine.checkVersion("4.3.0");
4205
4238
  await engine.pluginManager.register(e => {
4206
4239
  e.pluginManager.addColorManager("hsl", new HslColorManager());
4207
4240
  });
@@ -4225,7 +4258,7 @@
4225
4258
  }
4226
4259
 
4227
4260
  async function loadMovePlugin(engine) {
4228
- engine.checkVersion("4.2.0");
4261
+ engine.checkVersion("4.3.0");
4229
4262
  await engine.pluginManager.register(e => {
4230
4263
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
4231
4264
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -4441,7 +4474,7 @@
4441
4474
  }
4442
4475
 
4443
4476
  async function loadOpacityUpdater(engine) {
4444
- engine.checkVersion("4.2.0");
4477
+ engine.checkVersion("4.3.0");
4445
4478
  await engine.pluginManager.register(e => {
4446
4479
  e.pluginManager.addParticleUpdater("opacity", container => {
4447
4480
  return Promise.resolve(new OpacityUpdater(container));
@@ -4786,7 +4819,7 @@
4786
4819
  }
4787
4820
 
4788
4821
  async function loadOutModesUpdater(engine) {
4789
- engine.checkVersion("4.2.0");
4822
+ engine.checkVersion("4.3.0");
4790
4823
  await engine.pluginManager.register(e => {
4791
4824
  e.pluginManager.addParticleUpdater("outModes", container => {
4792
4825
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -4851,13 +4884,13 @@
4851
4884
  if (!this.isEnabled(particle)) {
4852
4885
  return;
4853
4886
  }
4854
- updateColor(particle.fillColor, delta);
4855
- updateColor(particle.strokeColor, delta);
4887
+ updateColor(particle.fillColor, delta, this.#container.hdr);
4888
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
4856
4889
  }
4857
4890
  }
4858
4891
 
4859
4892
  async function loadPaintUpdater(engine) {
4860
- engine.checkVersion("4.2.0");
4893
+ engine.checkVersion("4.3.0");
4861
4894
  await engine.pluginManager.register(e => {
4862
4895
  e.pluginManager.addParticleUpdater("paint", container => {
4863
4896
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -4912,7 +4945,7 @@
4912
4945
  }
4913
4946
 
4914
4947
  async function loadRgbColorPlugin(engine) {
4915
- engine.checkVersion("4.2.0");
4948
+ engine.checkVersion("4.3.0");
4916
4949
  await engine.pluginManager.register(e => {
4917
4950
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
4918
4951
  });
@@ -4997,7 +5030,7 @@
4997
5030
  }
4998
5031
 
4999
5032
  async function loadSizeUpdater(engine) {
5000
- engine.checkVersion("4.2.0");
5033
+ engine.checkVersion("4.3.0");
5001
5034
  await engine.pluginManager.register(e => {
5002
5035
  e.pluginManager.addParticleUpdater("size", container => {
5003
5036
  return Promise.resolve(new SizeUpdater(container));
@@ -5006,7 +5039,7 @@
5006
5039
  }
5007
5040
 
5008
5041
  async function loadBasic(engine) {
5009
- engine.checkVersion("4.2.0");
5042
+ engine.checkVersion("4.3.0");
5010
5043
  await engine.pluginManager.register(async (e) => {
5011
5044
  await Promise.all([
5012
5045
  loadBlendPlugin(e),
@@ -5029,7 +5062,7 @@
5029
5062
  easingsFunctions.set("ease-in-out-quad", value => (value < 0.5 ? 2 * value ** 2 : 1 - (-2 * value + 2) ** 2 / 2));
5030
5063
 
5031
5064
  async function loadEasingQuadPlugin(engine) {
5032
- engine.checkVersion("4.2.0");
5065
+ engine.checkVersion("4.3.0");
5033
5066
  await engine.pluginManager.register(e => {
5034
5067
  for (const [easing, easingFn] of easingsFunctions) {
5035
5068
  e.pluginManager.addEasing(easing, easingFn);
@@ -5137,7 +5170,7 @@
5137
5170
  }
5138
5171
 
5139
5172
  async function loadEmojiShape(engine) {
5140
- engine.checkVersion("4.2.0");
5173
+ engine.checkVersion("4.3.0");
5141
5174
  await engine.pluginManager.register(e => {
5142
5175
  e.pluginManager.addShape(validTypes$1, () => Promise.resolve(new EmojiDrawer()));
5143
5176
  });
@@ -5370,7 +5403,7 @@
5370
5403
  };
5371
5404
 
5372
5405
  async function loadExternalAttractInteraction(engine) {
5373
- engine.checkVersion("4.2.0");
5406
+ engine.checkVersion("4.3.0");
5374
5407
  await engine.pluginManager.register((e) => {
5375
5408
  ensureInteractivityPluginLoaded(e);
5376
5409
  e.pluginManager.addInteractor?.("externalAttract", container => {
@@ -5559,7 +5592,7 @@
5559
5592
  }
5560
5593
 
5561
5594
  async function loadExternalBounceInteraction(engine) {
5562
- engine.checkVersion("4.2.0");
5595
+ engine.checkVersion("4.3.0");
5563
5596
  await engine.pluginManager.register((e) => {
5564
5597
  ensureInteractivityPluginLoaded(e);
5565
5598
  e.pluginManager.addInteractor?.("externalBounce", container => {
@@ -5619,6 +5652,19 @@
5619
5652
  }
5620
5653
  }
5621
5654
 
5655
+ class BubbleModifier {
5656
+ div;
5657
+ enabled = false;
5658
+ fillColor;
5659
+ finalColor;
5660
+ id = "bubble";
5661
+ inRange = false;
5662
+ opacity;
5663
+ priority = 100;
5664
+ radius;
5665
+ strokeColor;
5666
+ }
5667
+
5622
5668
  var ProcessBubbleType;
5623
5669
  (function (ProcessBubbleType) {
5624
5670
  ProcessBubbleType["color"] = "color";
@@ -5642,6 +5688,7 @@
5642
5688
  class Bubbler extends ExternalInteractorBase {
5643
5689
  handleClickMode;
5644
5690
  #maxDistance;
5691
+ #modifiers = new WeakMap();
5645
5692
  #pluginManager;
5646
5693
  constructor(pluginManager, container) {
5647
5694
  super(container);
@@ -5660,13 +5707,21 @@
5660
5707
  return this.#maxDistance;
5661
5708
  }
5662
5709
  clear(particle, _delta, force) {
5663
- if (particle.bubble.inRange && !force) {
5710
+ const mod = this.#modifiers.get(particle);
5711
+ if (mod?.inRange && !force) {
5664
5712
  return;
5665
5713
  }
5666
- delete particle.bubble.div;
5667
- delete particle.bubble.opacity;
5668
- delete particle.bubble.radius;
5669
- delete particle.bubble.color;
5714
+ particle.removeModifier(bubbleMode);
5715
+ this.#modifiers.delete(particle);
5716
+ }
5717
+ getOrCreateModifier(particle) {
5718
+ let mod = this.#modifiers.get(particle);
5719
+ if (!mod) {
5720
+ mod = new BubbleModifier();
5721
+ this.#modifiers.set(particle, mod);
5722
+ particle.addModifier(mod);
5723
+ }
5724
+ return mod;
5670
5725
  }
5671
5726
  init() {
5672
5727
  const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
@@ -5712,7 +5767,11 @@
5712
5767
  loadOptionProperty(options, "bubble", Bubble, ...sources);
5713
5768
  }
5714
5769
  reset(_interactivityData, particle) {
5715
- particle.bubble.inRange = false;
5770
+ const mod = this.#modifiers.get(particle);
5771
+ if (mod) {
5772
+ mod.enabled = false;
5773
+ mod.inRange = false;
5774
+ }
5716
5775
  }
5717
5776
  #clickBubble(interactivityData) {
5718
5777
  const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
@@ -5729,7 +5788,9 @@
5729
5788
  if (!bubble.clicking) {
5730
5789
  continue;
5731
5790
  }
5732
- particle.bubble.inRange = !bubble.durationEnd;
5791
+ const mod = this.getOrCreateModifier(particle);
5792
+ mod.enabled = !bubble.durationEnd;
5793
+ mod.inRange = !bubble.durationEnd;
5733
5794
  const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (performance.now() - (interactivityData.mouse.clickTime ?? defaultClickTime)) / millisecondsToSeconds;
5734
5795
  if (timeSpent > bubbleOptions.duration) {
5735
5796
  bubble.durationEnd = true;
@@ -5741,7 +5802,7 @@
5741
5802
  const sizeData = {
5742
5803
  bubbleObj: {
5743
5804
  optValue: container.retina.bubbleModeSize,
5744
- value: particle.bubble.radius,
5805
+ value: mod.radius,
5745
5806
  },
5746
5807
  particlesObj: {
5747
5808
  optValue: particle.size.max,
@@ -5753,7 +5814,7 @@
5753
5814
  const opacityData = {
5754
5815
  bubbleObj: {
5755
5816
  optValue: bubbleOptions.opacity,
5756
- value: particle.bubble.opacity,
5817
+ value: mod.opacity,
5757
5818
  },
5758
5819
  particlesObj: {
5759
5820
  optValue: particle.opacity?.max ?? defaultOpacity$1,
@@ -5766,7 +5827,8 @@
5766
5827
  this.#hoverBubbleColor(particle, distMouse);
5767
5828
  }
5768
5829
  else {
5769
- delete particle.bubble.color;
5830
+ mod.fillColor = undefined;
5831
+ mod.strokeColor = undefined;
5770
5832
  }
5771
5833
  }
5772
5834
  }
@@ -5777,7 +5839,9 @@
5777
5839
  }
5778
5840
  const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
5779
5841
  for (const particle of query) {
5780
- particle.bubble.inRange = true;
5842
+ const mod = this.getOrCreateModifier(particle);
5843
+ mod.enabled = true;
5844
+ mod.inRange = true;
5781
5845
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
5782
5846
  if (pointDistance <= distance) {
5783
5847
  if (ratio >= minRatio && interactivityData.status === mouseMoveEvent) {
@@ -5795,30 +5859,38 @@
5795
5859
  }
5796
5860
  }
5797
5861
  #hoverBubbleColor(particle, ratio, divBubble) {
5798
- const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;
5862
+ const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble, mod = this.getOrCreateModifier(particle);
5799
5863
  if (!bubbleOptions) {
5800
5864
  return;
5801
5865
  }
5802
- if (!particle.bubble.finalColor) {
5866
+ if (!mod.finalColor) {
5803
5867
  const modeColor = bubbleOptions.color;
5804
5868
  if (!modeColor) {
5805
5869
  return;
5806
5870
  }
5807
5871
  const bubbleColor = itemFromSingleOrMultiple(modeColor);
5808
- particle.bubble.finalColor = rangeColorToHsl(this.#pluginManager, bubbleColor);
5872
+ mod.finalColor = rangeColorToHsl(this.#pluginManager, bubbleColor);
5809
5873
  }
5810
- if (!particle.bubble.finalColor) {
5874
+ if (!mod.finalColor) {
5811
5875
  return;
5812
5876
  }
5813
5877
  if (bubbleOptions.mix) {
5814
- particle.bubble.color = undefined;
5878
+ mod.fillColor = undefined;
5879
+ mod.strokeColor = undefined;
5815
5880
  const pColor = particle.getFillColor();
5816
- particle.bubble.color = pColor
5817
- ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio))
5818
- : particle.bubble.finalColor;
5881
+ if (pColor) {
5882
+ const mixedColor = rgbToHsl(colorMix(pColor, mod.finalColor, ratioOffset - ratio, ratio));
5883
+ mod.fillColor = mixedColor;
5884
+ mod.strokeColor = mixedColor;
5885
+ }
5886
+ else {
5887
+ mod.fillColor = mod.finalColor;
5888
+ mod.strokeColor = mod.finalColor;
5889
+ }
5819
5890
  }
5820
5891
  else {
5821
- particle.bubble.color = particle.bubble.finalColor;
5892
+ mod.fillColor = mod.finalColor;
5893
+ mod.strokeColor = mod.finalColor;
5822
5894
  }
5823
5895
  }
5824
5896
  #hoverBubbleOpacity(particle, ratio, divBubble) {
@@ -5828,7 +5900,8 @@
5828
5900
  }
5829
5901
  const pOpacity = particle.opacity?.value ?? defaultOpacity$1, opacity = calculateBubbleValue(pOpacity, modeOpacity, particle.opacity?.max ?? defaultOpacity$1, ratio);
5830
5902
  if (opacity !== undefined) {
5831
- particle.bubble.opacity = opacity;
5903
+ const mod = this.getOrCreateModifier(particle);
5904
+ mod.opacity = opacity;
5832
5905
  }
5833
5906
  }
5834
5907
  #hoverBubbleSize(particle, ratio, divBubble) {
@@ -5838,7 +5911,8 @@
5838
5911
  }
5839
5912
  const pSize = particle.size.value, size = calculateBubbleValue(pSize, modeSize, particle.size.max, ratio);
5840
5913
  if (size !== undefined) {
5841
- particle.bubble.radius = size;
5914
+ const mod = this.getOrCreateModifier(particle);
5915
+ mod.radius = size;
5842
5916
  }
5843
5917
  }
5844
5918
  #process(particle, distMouse, timeSpent, data) {
@@ -5851,13 +5925,14 @@
5851
5925
  return;
5852
5926
  }
5853
5927
  container.bubble ??= {};
5928
+ const mod = this.getOrCreateModifier(particle);
5854
5929
  if (container.bubble.durationEnd) {
5855
5930
  if (pObjBubble) {
5856
5931
  if (type === ProcessBubbleType.size) {
5857
- delete particle.bubble.radius;
5932
+ mod.radius = undefined;
5858
5933
  }
5859
5934
  if (type === ProcessBubbleType.opacity) {
5860
- delete particle.bubble.opacity;
5935
+ mod.opacity = undefined;
5861
5936
  }
5862
5937
  }
5863
5938
  }
@@ -5867,19 +5942,19 @@
5867
5942
  if (obj !== bubbleParam) {
5868
5943
  const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
5869
5944
  if (type === ProcessBubbleType.size) {
5870
- particle.bubble.radius = value;
5945
+ mod.radius = value;
5871
5946
  }
5872
5947
  if (type === ProcessBubbleType.opacity) {
5873
- particle.bubble.opacity = value;
5948
+ mod.opacity = value;
5874
5949
  }
5875
5950
  }
5876
5951
  }
5877
5952
  else {
5878
5953
  if (type === ProcessBubbleType.size) {
5879
- delete particle.bubble.radius;
5954
+ mod.radius = undefined;
5880
5955
  }
5881
5956
  if (type === ProcessBubbleType.opacity) {
5882
- delete particle.bubble.opacity;
5957
+ mod.opacity = undefined;
5883
5958
  }
5884
5959
  }
5885
5960
  }
@@ -5900,11 +5975,13 @@
5900
5975
  if (!area.contains(particle.getPosition())) {
5901
5976
  continue;
5902
5977
  }
5903
- particle.bubble.inRange = true;
5978
+ const mod = this.getOrCreateModifier(particle);
5979
+ mod.enabled = true;
5980
+ mod.inRange = true;
5904
5981
  const divs = bubble.divs, divBubble = divMode(divs, elem);
5905
- if (!particle.bubble.div || particle.bubble.div !== elem) {
5982
+ if (!mod.div || mod.div !== elem) {
5906
5983
  this.clear(particle, delta, true);
5907
- particle.bubble.div = elem;
5984
+ mod.div = elem;
5908
5985
  }
5909
5986
  this.#hoverBubbleSize(particle, defaultRatio, divBubble);
5910
5987
  this.#hoverBubbleOpacity(particle, defaultRatio, divBubble);
@@ -5915,7 +5992,7 @@
5915
5992
  }
5916
5993
 
5917
5994
  async function loadExternalBubbleInteraction(engine) {
5918
- engine.checkVersion("4.2.0");
5995
+ engine.checkVersion("4.3.0");
5919
5996
  await engine.pluginManager.register((e) => {
5920
5997
  ensureInteractivityPluginLoaded(e);
5921
5998
  e.pluginManager.addInteractor?.("externalBubble", container => {
@@ -6043,7 +6120,7 @@
6043
6120
  }
6044
6121
 
6045
6122
  async function loadExternalConnectInteraction(engine) {
6046
- engine.checkVersion("4.2.0");
6123
+ engine.checkVersion("4.3.0");
6047
6124
  await engine.pluginManager.register((e) => {
6048
6125
  ensureInteractivityPluginLoaded(e);
6049
6126
  e.pluginManager.addInteractor?.("externalConnect", container => {
@@ -6147,7 +6224,7 @@
6147
6224
  }
6148
6225
 
6149
6226
  async function loadExternalDestroyInteraction(engine) {
6150
- engine.checkVersion("4.2.0");
6227
+ engine.checkVersion("4.3.0");
6151
6228
  await engine.pluginManager.register((e) => {
6152
6229
  ensureInteractivityPluginLoaded(e);
6153
6230
  e.pluginManager.addInteractor?.("externalDestroy", async (container) => {
@@ -6271,7 +6348,7 @@
6271
6348
  }
6272
6349
 
6273
6350
  async function loadExternalGrabInteraction(engine) {
6274
- engine.checkVersion("4.2.0");
6351
+ engine.checkVersion("4.3.0");
6275
6352
  await engine.pluginManager.register((e) => {
6276
6353
  ensureInteractivityPluginLoaded(e);
6277
6354
  e.pluginManager.addInteractor?.("externalGrab", container => {
@@ -6341,7 +6418,7 @@
6341
6418
  }
6342
6419
 
6343
6420
  async function loadExternalParallaxInteraction(engine) {
6344
- engine.checkVersion("4.2.0");
6421
+ engine.checkVersion("4.3.0");
6345
6422
  await engine.pluginManager.register((e) => {
6346
6423
  ensureInteractivityPluginLoaded(e);
6347
6424
  e.pluginManager.addInteractor?.("externalParallax", container => {
@@ -6384,7 +6461,7 @@
6384
6461
  }
6385
6462
 
6386
6463
  async function loadExternalPauseInteraction(engine) {
6387
- engine.checkVersion("4.2.0");
6464
+ engine.checkVersion("4.3.0");
6388
6465
  await engine.pluginManager.register((e) => {
6389
6466
  ensureInteractivityPluginLoaded(e);
6390
6467
  e.pluginManager.addInteractor?.("externalPause", container => {
@@ -6456,7 +6533,7 @@
6456
6533
  }
6457
6534
 
6458
6535
  async function loadExternalPushInteraction(engine) {
6459
- engine.checkVersion("4.2.0");
6536
+ engine.checkVersion("4.3.0");
6460
6537
  await engine.pluginManager.register((e) => {
6461
6538
  ensureInteractivityPluginLoaded(e);
6462
6539
  e.pluginManager.addInteractor?.("externalPush", container => {
@@ -6510,7 +6587,7 @@
6510
6587
  }
6511
6588
 
6512
6589
  async function loadExternalRemoveInteraction(engine) {
6513
- engine.checkVersion("4.2.0");
6590
+ engine.checkVersion("4.3.0");
6514
6591
  await engine.pluginManager.register((e) => {
6515
6592
  ensureInteractivityPluginLoaded(e);
6516
6593
  e.pluginManager.addInteractor?.("externalRemove", container => {
@@ -6816,7 +6893,7 @@
6816
6893
  }
6817
6894
 
6818
6895
  async function loadExternalRepulseInteraction(engine) {
6819
- engine.checkVersion("4.2.0");
6896
+ engine.checkVersion("4.3.0");
6820
6897
  await engine.pluginManager.register((e) => {
6821
6898
  ensureInteractivityPluginLoaded(e);
6822
6899
  const pluginManager = e.pluginManager;
@@ -6838,9 +6915,17 @@
6838
6915
  }
6839
6916
  }
6840
6917
 
6918
+ class SlowModifier {
6919
+ enabled = false;
6920
+ id = "slow";
6921
+ priority = 100;
6922
+ speedFactor = 1;
6923
+ }
6924
+
6841
6925
  const slowMode = "slow", minRadius$1 = 0;
6842
6926
  class Slower extends ExternalInteractorBase {
6843
6927
  #maxDistance;
6928
+ #modifiers = new WeakMap();
6844
6929
  constructor(container) {
6845
6930
  super(container);
6846
6931
  this.#maxDistance = 0;
@@ -6849,10 +6934,21 @@
6849
6934
  return this.#maxDistance;
6850
6935
  }
6851
6936
  clear(particle, _delta, force) {
6852
- if (particle.slow.inRange && !force) {
6937
+ const mod = this.#modifiers.get(particle);
6938
+ if (mod?.enabled && !force) {
6853
6939
  return;
6854
6940
  }
6855
- particle.slow.factor = 1;
6941
+ particle.removeModifier(slowMode);
6942
+ this.#modifiers.delete(particle);
6943
+ }
6944
+ getOrCreateModifier(particle) {
6945
+ let mod = this.#modifiers.get(particle);
6946
+ if (!mod) {
6947
+ mod = new SlowModifier();
6948
+ this.#modifiers.set(particle, mod);
6949
+ particle.addModifier(mod);
6950
+ }
6951
+ return mod;
6856
6952
  }
6857
6953
  init() {
6858
6954
  const container = this.container, slow = container.actualOptions.interactivity?.modes.slow;
@@ -6872,22 +6968,26 @@
6872
6968
  loadOptionProperty(options, "slow", Slow, ...sources);
6873
6969
  }
6874
6970
  reset(interactivityData, particle) {
6875
- particle.slow.inRange = false;
6971
+ const mod = this.#modifiers.get(particle);
6972
+ if (mod) {
6973
+ mod.enabled = false;
6974
+ }
6876
6975
  const container = this.container, options = container.actualOptions, mousePos = interactivityData.mouse.position, radius = container.retina.slowModeRadius, slowOptions = options.interactivity?.modes.slow;
6877
6976
  if (!slowOptions || !radius || radius < minRadius$1 || !mousePos) {
6878
6977
  return;
6879
6978
  }
6880
- const particlePos = particle.getPosition(), dist = getDistance(mousePos, particlePos), proximityFactor = dist / radius, slowFactor = slowOptions.factor, { slow } = particle;
6979
+ const particlePos = particle.getPosition(), dist = getDistance(mousePos, particlePos), proximityFactor = dist / radius, slowFactor = slowOptions.factor;
6881
6980
  if (dist > radius) {
6882
6981
  return;
6883
6982
  }
6884
- slow.inRange = true;
6885
- slow.factor = proximityFactor / slowFactor;
6983
+ const activeMod = this.getOrCreateModifier(particle);
6984
+ activeMod.enabled = true;
6985
+ activeMod.speedFactor = proximityFactor / slowFactor;
6886
6986
  }
6887
6987
  }
6888
6988
 
6889
6989
  async function loadExternalSlowInteraction(engine) {
6890
- engine.checkVersion("4.2.0");
6990
+ engine.checkVersion("4.3.0");
6891
6991
  await engine.pluginManager.register((e) => {
6892
6992
  ensureInteractivityPluginLoaded(e);
6893
6993
  e.pluginManager.addInteractor?.("externalSlow", container => {
@@ -6949,7 +7049,6 @@
6949
7049
  function replaceImageColor(image, imageData, color, particle, hdr = false) {
6950
7050
  const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity, hdr), imageRes = {
6951
7051
  color,
6952
- gif: imageData.gif,
6953
7052
  data: {
6954
7053
  ...image,
6955
7054
  svgData: svgColoredData,
@@ -6984,495 +7083,6 @@
6984
7083
  });
6985
7084
  }
6986
7085
 
6987
- const InterlaceOffsets = [0, 4, 2, 1];
6988
- const InterlaceSteps = [8, 8, 4, 2];
6989
-
6990
- class ByteStream {
6991
- data;
6992
- pos;
6993
- constructor(bytes) {
6994
- this.pos = 0;
6995
- this.data = new Uint8ClampedArray(bytes);
6996
- }
6997
- getString(count) {
6998
- const slice = this.data.slice(this.pos, this.pos + count);
6999
- this.pos += slice.length;
7000
- return slice.reduce((acc, curr) => acc + String.fromCharCode(curr), "");
7001
- }
7002
- nextByte() {
7003
- return this.data[this.pos++];
7004
- }
7005
- nextTwoBytes() {
7006
- const increment = 2, previous = 1, shift = 8;
7007
- this.pos += increment;
7008
- return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
7009
- }
7010
- readSubBlocks() {
7011
- let blockString = "", size;
7012
- const minCount = 0, emptySize = 0;
7013
- do {
7014
- size = this.data[this.pos++];
7015
- for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
7016
- }
7017
- } while (size !== emptySize);
7018
- return blockString;
7019
- }
7020
- readSubBlocksBin() {
7021
- let size = this.data[this.pos], len = 0;
7022
- const emptySize = 0, increment = 1;
7023
- for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
7024
- len += size;
7025
- }
7026
- const blockData = new Uint8Array(len);
7027
- size = this.data[this.pos++];
7028
- for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
7029
- for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
7030
- }
7031
- }
7032
- return blockData;
7033
- }
7034
- skipSubBlocks() {
7035
- for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
7036
- }
7037
- this.pos++;
7038
- }
7039
- }
7040
-
7041
- var DisposalMethod;
7042
- (function (DisposalMethod) {
7043
- DisposalMethod[DisposalMethod["Replace"] = 0] = "Replace";
7044
- DisposalMethod[DisposalMethod["Combine"] = 1] = "Combine";
7045
- DisposalMethod[DisposalMethod["RestoreBackground"] = 2] = "RestoreBackground";
7046
- DisposalMethod[DisposalMethod["RestorePrevious"] = 3] = "RestorePrevious";
7047
- DisposalMethod[DisposalMethod["UndefinedA"] = 4] = "UndefinedA";
7048
- DisposalMethod[DisposalMethod["UndefinedB"] = 5] = "UndefinedB";
7049
- DisposalMethod[DisposalMethod["UndefinedC"] = 6] = "UndefinedC";
7050
- DisposalMethod[DisposalMethod["UndefinedD"] = 7] = "UndefinedD";
7051
- })(DisposalMethod || (DisposalMethod = {}));
7052
-
7053
- var GIFDataHeaders;
7054
- (function (GIFDataHeaders) {
7055
- GIFDataHeaders[GIFDataHeaders["Extension"] = 33] = "Extension";
7056
- GIFDataHeaders[GIFDataHeaders["ApplicationExtension"] = 255] = "ApplicationExtension";
7057
- GIFDataHeaders[GIFDataHeaders["GraphicsControlExtension"] = 249] = "GraphicsControlExtension";
7058
- GIFDataHeaders[GIFDataHeaders["PlainTextExtension"] = 1] = "PlainTextExtension";
7059
- GIFDataHeaders[GIFDataHeaders["CommentExtension"] = 254] = "CommentExtension";
7060
- GIFDataHeaders[GIFDataHeaders["Image"] = 44] = "Image";
7061
- GIFDataHeaders[GIFDataHeaders["EndOfFile"] = 59] = "EndOfFile";
7062
- })(GIFDataHeaders || (GIFDataHeaders = {}));
7063
-
7064
- const defaultFrame = 0, initialTime = 0, firstIndex$2 = 0, defaultLoopCount = 0;
7065
- function parseColorTable(byteStream, count) {
7066
- const colors = [];
7067
- for (let i = 0; i < count; i++) {
7068
- colors.push({
7069
- r: byteStream.data[byteStream.pos],
7070
- g: byteStream.data[byteStream.pos + 1],
7071
- b: byteStream.data[byteStream.pos + 2],
7072
- });
7073
- byteStream.pos += 3;
7074
- }
7075
- return colors;
7076
- }
7077
- function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
7078
- switch (byteStream.nextByte()) {
7079
- case GIFDataHeaders.GraphicsControlExtension: {
7080
- const frame = gif.frames[getFrameIndex(false)];
7081
- byteStream.pos++;
7082
- const packedByte = byteStream.nextByte();
7083
- frame.GCreserved = (packedByte & 0xe0) >>> 5;
7084
- frame.disposalMethod = (packedByte & 0x1c) >>> 2;
7085
- frame.userInputDelayFlag = (packedByte & 2) === 2;
7086
- const transparencyFlag = (packedByte & 1) === 1;
7087
- frame.delayTime = byteStream.nextTwoBytes() * 0xa;
7088
- const transparencyIndex = byteStream.nextByte();
7089
- if (transparencyFlag) {
7090
- getTransparencyIndex(transparencyIndex);
7091
- }
7092
- byteStream.pos++;
7093
- break;
7094
- }
7095
- case GIFDataHeaders.ApplicationExtension: {
7096
- byteStream.pos++;
7097
- const applicationExtension = {
7098
- identifier: byteStream.getString(8),
7099
- authenticationCode: byteStream.getString(3),
7100
- data: byteStream.readSubBlocksBin(),
7101
- };
7102
- gif.applicationExtensions.push(applicationExtension);
7103
- break;
7104
- }
7105
- case GIFDataHeaders.CommentExtension: {
7106
- gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);
7107
- break;
7108
- }
7109
- case GIFDataHeaders.PlainTextExtension: {
7110
- if (gif.globalColorTable.length === 0) {
7111
- throw new EvalError("plain text extension without global color table");
7112
- }
7113
- byteStream.pos++;
7114
- gif.frames[getFrameIndex(false)].plainTextData = {
7115
- left: byteStream.nextTwoBytes(),
7116
- top: byteStream.nextTwoBytes(),
7117
- width: byteStream.nextTwoBytes(),
7118
- height: byteStream.nextTwoBytes(),
7119
- charSize: {
7120
- width: byteStream.nextTwoBytes(),
7121
- height: byteStream.nextTwoBytes(),
7122
- },
7123
- foregroundColor: byteStream.nextByte(),
7124
- backgroundColor: byteStream.nextByte(),
7125
- text: byteStream.readSubBlocks(),
7126
- };
7127
- break;
7128
- }
7129
- default:
7130
- byteStream.skipSubBlocks();
7131
- break;
7132
- }
7133
- }
7134
- function readBits(imageData, pos, len) {
7135
- const bytePos = pos >>> 3, bitPos = pos & 7;
7136
- return (((imageData[bytePos] + (imageData[bytePos + 1] << 8) + (imageData[bytePos + 2] << 16)) &
7137
- (((1 << len) - 1) << bitPos)) >>>
7138
- bitPos);
7139
- }
7140
- async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
7141
- const frame = gif.frames[getFrameIndex(true)];
7142
- frame.left = byteStream.nextTwoBytes();
7143
- frame.top = byteStream.nextTwoBytes();
7144
- frame.width = byteStream.nextTwoBytes();
7145
- frame.height = byteStream.nextTwoBytes();
7146
- const packedByte = byteStream.nextByte(), localColorTableFlag = (packedByte & 0x80) === 0x80, interlacedFlag = (packedByte & 0x40) === 0x40;
7147
- frame.sortFlag = (packedByte & 0x20) === 0x20;
7148
- frame.reserved = (packedByte & 0x18) >>> 3;
7149
- const localColorCount = 1 << ((packedByte & 7) + 1);
7150
- if (localColorTableFlag) {
7151
- frame.localColorTable = parseColorTable(byteStream, localColorCount);
7152
- }
7153
- const getColor = (index) => {
7154
- const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
7155
- if (index !== getTransparencyIndex(null)) {
7156
- return { r, g, b, a: 255 };
7157
- }
7158
- return { r, g, b, a: avgAlpha ? Math.trunc((r + g + b) / 3) : 0 };
7159
- }, image = (() => {
7160
- try {
7161
- return new ImageData(frame.width, frame.height, canvasSettings);
7162
- }
7163
- catch (error) {
7164
- if (error instanceof DOMException && error.name === "IndexSizeError") {
7165
- return null;
7166
- }
7167
- throw error;
7168
- }
7169
- })();
7170
- if (image == null) {
7171
- throw new EvalError("GIF frame size is to large");
7172
- }
7173
- const minCodeSize = byteStream.nextByte(), imageData = byteStream.readSubBlocksBin(), clearCode = 1 << minCodeSize;
7174
- if (interlacedFlag) {
7175
- for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
7176
- if (InterlaceOffsets[pass] < frame.height) {
7177
- let pixelPos = 0, lineIndex = 0, exit = false;
7178
- while (!exit) {
7179
- const last = code;
7180
- code = readBits(imageData, pos, size);
7181
- pos += size + 1;
7182
- if (code === clearCode) {
7183
- size = minCodeSize + 1;
7184
- dic.length = clearCode + 2;
7185
- for (let i = 0; i < dic.length; i++) {
7186
- dic[i] = i < clearCode ? [i] : [];
7187
- }
7188
- }
7189
- else {
7190
- if (code >= dic.length) {
7191
- dic.push(dic[last].concat(dic[last][0]));
7192
- }
7193
- else if (last !== clearCode) {
7194
- dic.push(dic[last].concat(dic[code][0]));
7195
- }
7196
- for (const item of dic[code]) {
7197
- const { r, g, b, a } = getColor(item);
7198
- image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width +
7199
- InterlaceSteps[pass] * lineIndex +
7200
- (pixelPos % (frame.width * 4)));
7201
- pixelPos += 4;
7202
- }
7203
- if (dic.length === 1 << size && size < 0xc) {
7204
- size++;
7205
- }
7206
- }
7207
- if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
7208
- lineIndex++;
7209
- if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
7210
- exit = true;
7211
- }
7212
- }
7213
- }
7214
- }
7215
- }
7216
- frame.image = image;
7217
- frame.bitmap = await createImageBitmap(image);
7218
- }
7219
- else {
7220
- let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4;
7221
- const dic = [[0]];
7222
- for (;;) {
7223
- const last = code;
7224
- code = readBits(imageData, pos, size);
7225
- pos += size;
7226
- if (code === clearCode) {
7227
- size = minCodeSize + 1;
7228
- dic.length = clearCode + 2;
7229
- for (let i = 0; i < dic.length; i++) {
7230
- dic[i] = i < clearCode ? [i] : [];
7231
- }
7232
- }
7233
- else {
7234
- if (code === clearCode + 1) {
7235
- break;
7236
- }
7237
- if (code >= dic.length) {
7238
- dic.push(dic[last].concat(dic[last][0]));
7239
- }
7240
- else if (last !== clearCode) {
7241
- dic.push(dic[last].concat(dic[code][0]));
7242
- }
7243
- for (const item of dic[code]) {
7244
- const { r, g, b, a } = getColor(item);
7245
- pixelPos += 4;
7246
- image.data.set([r, g, b, a], pixelPos);
7247
- }
7248
- if (dic.length >= 1 << size && size < 0xc) {
7249
- size++;
7250
- }
7251
- }
7252
- }
7253
- frame.image = image;
7254
- frame.bitmap = await createImageBitmap(image);
7255
- }
7256
- }
7257
- async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
7258
- switch (byteStream.nextByte()) {
7259
- case GIFDataHeaders.EndOfFile:
7260
- return true;
7261
- case GIFDataHeaders.Image:
7262
- await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings);
7263
- break;
7264
- case GIFDataHeaders.Extension:
7265
- parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
7266
- break;
7267
- default:
7268
- throw new EvalError("undefined block found");
7269
- }
7270
- return false;
7271
- }
7272
- function getGIFLoopAmount(gif) {
7273
- for (const extension of gif.applicationExtensions) {
7274
- if (extension.identifier + extension.authenticationCode !== "NETSCAPE2.0") {
7275
- continue;
7276
- }
7277
- return extension.data[1] + (extension.data[2] << 8);
7278
- }
7279
- return Number.NaN;
7280
- }
7281
- async function decodeGIF(gifURL, canvasSettings, progressCallback, avgAlpha) {
7282
- avgAlpha ??= false;
7283
- const res = await fetch(gifURL);
7284
- if (!res.ok && res.status === 404) {
7285
- throw new EvalError("file not found");
7286
- }
7287
- const buffer = await res.arrayBuffer(), gif = {
7288
- width: 0,
7289
- height: 0,
7290
- totalTime: 0,
7291
- colorRes: 0,
7292
- pixelAspectRatio: 0,
7293
- frames: [],
7294
- sortFlag: false,
7295
- globalColorTable: [],
7296
- backgroundImage: new ImageData(1, 1, canvasSettings),
7297
- comments: [],
7298
- applicationExtensions: [],
7299
- }, byteStream = new ByteStream(new Uint8ClampedArray(buffer));
7300
- if (byteStream.getString(6) !== "GIF89a") {
7301
- throw new Error("not a supported GIF file");
7302
- }
7303
- gif.width = byteStream.nextTwoBytes();
7304
- gif.height = byteStream.nextTwoBytes();
7305
- const packedByte = byteStream.nextByte(), globalColorTableFlag = (packedByte & 0x80) === 0x80;
7306
- gif.colorRes = (packedByte & 0x70) >>> 4;
7307
- gif.sortFlag = (packedByte & 8) === 8;
7308
- const globalColorCount = 1 << ((packedByte & 7) + 1), backgroundColorIndex = byteStream.nextByte();
7309
- gif.pixelAspectRatio = byteStream.nextByte();
7310
- if (gif.pixelAspectRatio !== 0) {
7311
- gif.pixelAspectRatio = (gif.pixelAspectRatio + 0xf) / 0x40;
7312
- }
7313
- if (globalColorTableFlag) {
7314
- gif.globalColorTable = parseColorTable(byteStream, globalColorCount);
7315
- }
7316
- const backgroundImage = (() => {
7317
- try {
7318
- return new ImageData(gif.width, gif.height, canvasSettings);
7319
- }
7320
- catch (error) {
7321
- if (error instanceof DOMException && error.name === "IndexSizeError") {
7322
- return null;
7323
- }
7324
- throw error;
7325
- }
7326
- })();
7327
- if (backgroundImage == null) {
7328
- throw new Error("GIF frame size is to large");
7329
- }
7330
- const { r, g, b } = gif.globalColorTable[backgroundColorIndex];
7331
- backgroundImage.data.set(globalColorTableFlag ? [r, g, b, 255] : [0, 0, 0, 0]);
7332
- for (let i = 4; i < backgroundImage.data.length; i *= 2) {
7333
- backgroundImage.data.copyWithin(i, 0, i);
7334
- }
7335
- gif.backgroundImage = backgroundImage;
7336
- let frameIndex = -1, incrementFrameIndex = true, transparencyIndex = -1;
7337
- const getframeIndex = (increment) => {
7338
- if (increment) {
7339
- incrementFrameIndex = true;
7340
- }
7341
- return frameIndex;
7342
- }, getTransparencyIndex = (newValue) => {
7343
- if (newValue != null) {
7344
- transparencyIndex = newValue;
7345
- }
7346
- return transparencyIndex;
7347
- };
7348
- try {
7349
- do {
7350
- if (incrementFrameIndex) {
7351
- gif.frames.push({
7352
- left: 0,
7353
- top: 0,
7354
- width: 0,
7355
- height: 0,
7356
- disposalMethod: DisposalMethod.Replace,
7357
- image: new ImageData(1, 1, canvasSettings),
7358
- plainTextData: null,
7359
- userInputDelayFlag: false,
7360
- delayTime: 0,
7361
- sortFlag: false,
7362
- localColorTable: [],
7363
- reserved: 0,
7364
- GCreserved: 0,
7365
- });
7366
- frameIndex++;
7367
- transparencyIndex = -1;
7368
- incrementFrameIndex = false;
7369
- }
7370
- } while (!(await parseBlock(byteStream, gif, avgAlpha, getframeIndex, getTransparencyIndex, canvasSettings, progressCallback)));
7371
- gif.frames.length--;
7372
- for (const frame of gif.frames) {
7373
- if (frame.userInputDelayFlag && frame.delayTime === 0) {
7374
- gif.totalTime = Infinity;
7375
- break;
7376
- }
7377
- gif.totalTime += frame.delayTime;
7378
- }
7379
- return gif;
7380
- }
7381
- catch (error) {
7382
- if (error instanceof EvalError) {
7383
- throw new Error(`error while parsing frame ${frameIndex.toString()} "${error.message}"`, { cause: error });
7384
- }
7385
- throw error;
7386
- }
7387
- }
7388
- function drawGif(data, canvasSettings) {
7389
- const { context, radius, particle, delta } = data, image = particle.image;
7390
- if (!image?.gifData || !image.gif) {
7391
- return;
7392
- }
7393
- const offscreenCanvas = new OffscreenCanvas(image.gifData.width, image.gifData.height), offscreenContext = offscreenCanvas.getContext("2d", canvasSettings);
7394
- if (!offscreenContext) {
7395
- throw new Error("could not create offscreen canvas context");
7396
- }
7397
- offscreenContext.imageSmoothingQuality = "low";
7398
- offscreenContext.imageSmoothingEnabled = false;
7399
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
7400
- particle.gifLoopCount ??= image.gifLoopCount ?? defaultLoopCount;
7401
- let frameIndex = particle.gifFrame ?? defaultFrame;
7402
- const pos = { x: -image.gifData.width * half, y: -image.gifData.height * half }, frame = image.gifData.frames[frameIndex];
7403
- particle.gifTime ??= initialTime;
7404
- if (!frame.bitmap) {
7405
- return;
7406
- }
7407
- context.scale(radius / image.gifData.width, radius / image.gifData.height);
7408
- switch (frame.disposalMethod) {
7409
- case DisposalMethod.UndefinedA:
7410
- case DisposalMethod.UndefinedB:
7411
- case DisposalMethod.UndefinedC:
7412
- case DisposalMethod.UndefinedD:
7413
- case DisposalMethod.Replace:
7414
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
7415
- context.drawImage(offscreenCanvas, pos.x, pos.y);
7416
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
7417
- break;
7418
- case DisposalMethod.Combine:
7419
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
7420
- context.drawImage(offscreenCanvas, pos.x, pos.y);
7421
- break;
7422
- case DisposalMethod.RestoreBackground:
7423
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
7424
- context.drawImage(offscreenCanvas, pos.x, pos.y);
7425
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
7426
- if (!image.gifData.globalColorTable.length) {
7427
- offscreenContext.putImageData(image.gifData.frames[firstIndex$2].image, pos.x + frame.left, pos.y + frame.top);
7428
- }
7429
- else {
7430
- offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
7431
- }
7432
- break;
7433
- case DisposalMethod.RestorePrevious:
7434
- {
7435
- const previousImageData = offscreenContext.getImageData(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
7436
- offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
7437
- context.drawImage(offscreenCanvas, pos.x, pos.y);
7438
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
7439
- offscreenContext.putImageData(previousImageData, originPoint.x, originPoint.y);
7440
- }
7441
- break;
7442
- }
7443
- particle.gifTime += delta.value;
7444
- if (particle.gifTime > frame.delayTime) {
7445
- particle.gifTime -= frame.delayTime;
7446
- if (++frameIndex >= image.gifData.frames.length) {
7447
- if (--particle.gifLoopCount <= defaultLoopCount) {
7448
- return;
7449
- }
7450
- frameIndex = firstIndex$2;
7451
- offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
7452
- }
7453
- particle.gifFrame = frameIndex;
7454
- }
7455
- context.scale(image.gifData.width / radius, image.gifData.height / radius);
7456
- }
7457
- async function loadGifImage(image, canvasSettings) {
7458
- if (image.type !== "gif") {
7459
- await loadImage(image);
7460
- return;
7461
- }
7462
- image.loading = true;
7463
- try {
7464
- image.gifData = await decodeGIF(image.source, canvasSettings);
7465
- image.gifLoopCount = getGIFLoopAmount(image.gifData);
7466
- if (!image.gifLoopCount) {
7467
- image.gifLoopCount = Infinity;
7468
- }
7469
- }
7470
- catch {
7471
- image.error = true;
7472
- }
7473
- image.loading = false;
7474
- }
7475
-
7476
7086
  const sides$3 = 12;
7477
7087
  class ImageDrawer {
7478
7088
  #container;
@@ -7487,10 +7097,7 @@
7487
7097
  return;
7488
7098
  }
7489
7099
  context.globalAlpha = opacity;
7490
- if (image.gif && image.gifData) {
7491
- drawGif(data, this.#container.canvas.render.settings);
7492
- }
7493
- else if (element) {
7100
+ if (element) {
7494
7101
  const ratio = image.ratio, pos = {
7495
7102
  x: -radius,
7496
7103
  y: -radius,
@@ -7559,9 +7166,6 @@
7559
7166
  color,
7560
7167
  data: image,
7561
7168
  element: image.element,
7562
- gif: image.gif,
7563
- gifData: image.gifData,
7564
- gifLoopCount: image.gifLoopCount,
7565
7169
  loaded: true,
7566
7170
  ratio: imageData.width && imageData.height ? imageData.width / imageData.height : (image.ratio ?? defaultRatio$1),
7567
7171
  replaceColor: replaceColor,
@@ -7584,7 +7188,6 @@
7584
7188
  throw new Error(`Image shape not initialized`);
7585
7189
  }
7586
7190
  await this.#engine.loadImage(container, {
7587
- gif: imageShape.gif,
7588
7191
  name: imageShape.name,
7589
7192
  replaceColor: imageShape.replaceColor,
7590
7193
  src: imageShape.src,
@@ -7593,7 +7196,6 @@
7593
7196
  }
7594
7197
 
7595
7198
  class Preload {
7596
- gif = false;
7597
7199
  height;
7598
7200
  name;
7599
7201
  replaceColor;
@@ -7603,7 +7205,6 @@
7603
7205
  if (isNull(data)) {
7604
7206
  return;
7605
7207
  }
7606
- loadProperty(this, "gif", data.gif);
7607
7208
  loadProperty(this, "height", data.height);
7608
7209
  loadProperty(this, "name", data.name);
7609
7210
  loadProperty(this, "replaceColor", data.replaceColor);
@@ -7670,7 +7271,6 @@
7670
7271
  }
7671
7272
  try {
7672
7273
  const image = {
7673
- gif: data.gif,
7674
7274
  name: data.name ?? data.src,
7675
7275
  source: data.src,
7676
7276
  type: data.src.substring(data.src.length - extLength),
@@ -7682,10 +7282,7 @@
7682
7282
  containerImages.push(image);
7683
7283
  engine.images.set(container, containerImages);
7684
7284
  let imageFunc;
7685
- if (data.gif) {
7686
- imageFunc = (img) => loadGifImage(img, { colorSpace: "srgb" });
7687
- }
7688
- else if (data.replaceColor) {
7285
+ if (data.replaceColor) {
7689
7286
  imageFunc = downloadSvgImage;
7690
7287
  }
7691
7288
  else {
@@ -7699,7 +7296,7 @@
7699
7296
  };
7700
7297
  }
7701
7298
  async function loadImageShape(engine) {
7702
- engine.checkVersion("4.2.0");
7299
+ engine.checkVersion("4.3.0");
7703
7300
  await engine.pluginManager.register(e => {
7704
7301
  addLoadImageToEngine(e);
7705
7302
  e.pluginManager.addPlugin(new ImagePreloaderPlugin(e));
@@ -7844,7 +7441,7 @@
7844
7441
  }
7845
7442
 
7846
7443
  async function loadLifeUpdater(engine) {
7847
- engine.checkVersion("4.2.0");
7444
+ engine.checkVersion("4.3.0");
7848
7445
  await engine.pluginManager.register(e => {
7849
7446
  e.pluginManager.addParticleUpdater("life", container => {
7850
7447
  return Promise.resolve(new LifeUpdater(container));
@@ -7870,7 +7467,7 @@
7870
7467
  }
7871
7468
 
7872
7469
  async function loadLineShape(engine) {
7873
- engine.checkVersion("4.2.0");
7470
+ engine.checkVersion("4.3.0");
7874
7471
  await engine.pluginManager.register(e => {
7875
7472
  e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
7876
7473
  });
@@ -7954,7 +7551,7 @@
7954
7551
  }
7955
7552
 
7956
7553
  async function loadParticlesAttractInteraction(engine) {
7957
- engine.checkVersion("4.2.0");
7554
+ engine.checkVersion("4.3.0");
7958
7555
  await engine.pluginManager.register((e) => {
7959
7556
  ensureInteractivityPluginLoaded(e);
7960
7557
  e.pluginManager.addInteractor?.("particlesAttract", container => {
@@ -8164,7 +7761,7 @@
8164
7761
  }
8165
7762
 
8166
7763
  async function loadParticlesCollisionsInteraction(engine) {
8167
- engine.checkVersion("4.2.0");
7764
+ engine.checkVersion("4.3.0");
8168
7765
  await engine.pluginManager.register((e) => {
8169
7766
  ensureInteractivityPluginLoaded(e);
8170
7767
  e.pluginManager.addPlugin(new OverlapPlugin());
@@ -8418,7 +8015,7 @@
8418
8015
  }
8419
8016
 
8420
8017
  async function loadParticlesLinksInteraction(engine) {
8421
- engine.checkVersion("4.2.0");
8018
+ engine.checkVersion("4.3.0");
8422
8019
  await engine.pluginManager.register((e) => {
8423
8020
  const pluginManager = e.pluginManager;
8424
8021
  ensureInteractivityPluginLoaded(e);
@@ -8508,19 +8105,19 @@
8508
8105
  }
8509
8106
 
8510
8107
  async function loadGenericPolygonShape(engine) {
8511
- engine.checkVersion("4.2.0");
8108
+ engine.checkVersion("4.3.0");
8512
8109
  await engine.pluginManager.register(e => {
8513
8110
  e.pluginManager.addShape(["polygon"], () => Promise.resolve(new PolygonDrawer()));
8514
8111
  });
8515
8112
  }
8516
8113
  async function loadTriangleShape(engine) {
8517
- engine.checkVersion("4.2.0");
8114
+ engine.checkVersion("4.3.0");
8518
8115
  await engine.pluginManager.register(e => {
8519
8116
  e.pluginManager.addShape(["triangle"], () => Promise.resolve(new TriangleDrawer()));
8520
8117
  });
8521
8118
  }
8522
8119
  async function loadPolygonShape(engine) {
8523
- engine.checkVersion("4.2.0");
8120
+ engine.checkVersion("4.3.0");
8524
8121
  await Promise.all([
8525
8122
  loadGenericPolygonShape(engine),
8526
8123
  loadTriangleShape(engine),
@@ -8625,7 +8222,7 @@
8625
8222
  }
8626
8223
 
8627
8224
  async function loadRotateUpdater(engine) {
8628
- engine.checkVersion("4.2.0");
8225
+ engine.checkVersion("4.3.0");
8629
8226
  await engine.pluginManager.register(e => {
8630
8227
  e.pluginManager.addParticleUpdater("rotate", container => {
8631
8228
  return Promise.resolve(new RotateUpdater(container));
@@ -8649,7 +8246,7 @@
8649
8246
  }
8650
8247
 
8651
8248
  async function loadSquareShape(engine) {
8652
- engine.checkVersion("4.2.0");
8249
+ engine.checkVersion("4.3.0");
8653
8250
  await engine.pluginManager.register(e => {
8654
8251
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
8655
8252
  });
@@ -8683,14 +8280,14 @@
8683
8280
  }
8684
8281
 
8685
8282
  async function loadStarShape(engine) {
8686
- engine.checkVersion("4.2.0");
8283
+ engine.checkVersion("4.3.0");
8687
8284
  await engine.pluginManager.register(e => {
8688
8285
  e.pluginManager.addShape(["star"], () => Promise.resolve(new StarDrawer()));
8689
8286
  });
8690
8287
  }
8691
8288
 
8692
8289
  async function loadSlim(engine) {
8693
- engine.checkVersion("4.2.0");
8290
+ engine.checkVersion("4.3.0");
8694
8291
  await engine.pluginManager.register(async (e) => {
8695
8292
  const loadInteractivityForSlim = async (e) => {
8696
8293
  await loadInteractivityPlugin(e);
@@ -8807,7 +8404,7 @@
8807
8404
  }
8808
8405
 
8809
8406
  async function loadTextShape(engine) {
8810
- engine.checkVersion("4.2.0");
8407
+ engine.checkVersion("4.3.0");
8811
8408
  await engine.pluginManager.register(e => {
8812
8409
  e.pluginManager.addShape(validTypes, () => Promise.resolve(new TextDrawer()));
8813
8410
  });
@@ -8916,7 +8513,7 @@
8916
8513
  }
8917
8514
 
8918
8515
  async function loadTiltUpdater(engine) {
8919
- engine.checkVersion("4.2.0");
8516
+ engine.checkVersion("4.3.0");
8920
8517
  await engine.pluginManager.register(e => {
8921
8518
  e.pluginManager.addParticleUpdater("tilt", container => {
8922
8519
  return Promise.resolve(new TiltUpdater(container));
@@ -9020,7 +8617,7 @@
9020
8617
  }
9021
8618
 
9022
8619
  async function loadTwinkleUpdater(engine) {
9023
- engine.checkVersion("4.2.0");
8620
+ engine.checkVersion("4.3.0");
9024
8621
  await engine.pluginManager.register(e => {
9025
8622
  e.pluginManager.addParticleUpdater("twinkle", container => {
9026
8623
  return Promise.resolve(new TwinkleUpdater(e.pluginManager, container));
@@ -9122,7 +8719,7 @@
9122
8719
  }
9123
8720
 
9124
8721
  async function loadWobbleUpdater(engine) {
9125
- engine.checkVersion("4.2.0");
8722
+ engine.checkVersion("4.3.0");
9126
8723
  await engine.pluginManager.register(e => {
9127
8724
  e.pluginManager.addParticleUpdater("wobble", container => {
9128
8725
  return Promise.resolve(new WobbleUpdater(container));
@@ -9131,7 +8728,7 @@
9131
8728
  }
9132
8729
 
9133
8730
  async function loadFull(engine) {
9134
- engine.checkVersion("4.2.0");
8731
+ engine.checkVersion("4.3.0");
9135
8732
  await engine.pluginManager.register(async (e) => {
9136
8733
  const loadEmittersPluginBundle = async (e) => {
9137
8734
  await loadEmittersPlugin(e);
@@ -9172,10 +8769,10 @@
9172
8769
  }
9173
8770
  }
9174
8771
  class RenderManager {
8772
+ #backgroundElement;
8773
+ #backgroundWarnings;
9175
8774
  #canvasClearPlugins;
9176
8775
  #canvasManager;
9177
- #canvasPaintPlugins;
9178
- #clearDrawPlugins;
9179
8776
  #colorPlugins;
9180
8777
  #container;
9181
8778
  #context;
@@ -9183,9 +8780,7 @@
9183
8780
  #drawParticlePlugins;
9184
8781
  #drawParticlesCleanupPlugins;
9185
8782
  #drawParticlesSetupPlugins;
9186
- #drawPlugins;
9187
- #drawSettingsCleanupPlugins;
9188
- #drawSettingsSetupPlugins;
8783
+ #layers;
9189
8784
  #pluginManager;
9190
8785
  #postDrawUpdaters;
9191
8786
  #preDrawUpdaters;
@@ -9197,18 +8792,25 @@
9197
8792
  this.#container = container;
9198
8793
  this.#canvasManager = canvasManager;
9199
8794
  this.#context = null;
8795
+ this.#backgroundElement = null;
8796
+ this.#backgroundWarnings = new Set();
9200
8797
  this.#preDrawUpdaters = [];
9201
8798
  this.#postDrawUpdaters = [];
9202
- this.#colorPlugins = [];
9203
8799
  this.#canvasClearPlugins = [];
9204
- this.#canvasPaintPlugins = [];
9205
- this.#clearDrawPlugins = [];
8800
+ this.#colorPlugins = [];
9206
8801
  this.#drawParticlePlugins = [];
9207
8802
  this.#drawParticlesCleanupPlugins = [];
9208
8803
  this.#drawParticlesSetupPlugins = [];
9209
- this.#drawPlugins = [];
9210
- this.#drawSettingsSetupPlugins = [];
9211
- this.#drawSettingsCleanupPlugins = [];
8804
+ this.#layers = {
8805
+ 0: [],
8806
+ 1: [],
8807
+ 2: [],
8808
+ 3: [],
8809
+ 4: [],
8810
+ 5: [],
8811
+ 6: [],
8812
+ 7: [],
8813
+ };
9212
8814
  }
9213
8815
  get settings() {
9214
8816
  return this.#contextSettings;
@@ -9222,32 +8824,38 @@
9222
8824
  });
9223
8825
  }
9224
8826
  clear() {
9225
- let pluginHandled = false;
9226
8827
  for (const plugin of this.#canvasClearPlugins) {
9227
- pluginHandled = plugin.canvasClear?.() ?? false;
9228
- if (pluginHandled) {
9229
- break;
8828
+ if (plugin.canvasClear?.() ?? false) {
8829
+ return;
9230
8830
  }
9231
8831
  }
9232
- if (pluginHandled) {
9233
- return;
8832
+ for (const layer of Object.values(exports.DrawLayer)) {
8833
+ if (typeof layer === "number") {
8834
+ for (const plugin of this.#getLayerPlugins(layer)) {
8835
+ if (plugin.canvasClear?.() ?? false) {
8836
+ return;
8837
+ }
8838
+ }
8839
+ }
9234
8840
  }
9235
8841
  this.canvasClear();
9236
8842
  }
9237
8843
  destroy() {
9238
8844
  this.stop();
8845
+ this.#backgroundElement = null;
8846
+ this.#backgroundWarnings.clear();
9239
8847
  this.#preDrawUpdaters = [];
9240
8848
  this.#postDrawUpdaters = [];
9241
- this.#colorPlugins = [];
9242
8849
  this.#canvasClearPlugins = [];
9243
- this.#canvasPaintPlugins = [];
9244
- this.#clearDrawPlugins = [];
8850
+ this.#colorPlugins = [];
9245
8851
  this.#drawParticlePlugins = [];
9246
8852
  this.#drawParticlesCleanupPlugins = [];
9247
8853
  this.#drawParticlesSetupPlugins = [];
9248
- this.#drawPlugins = [];
9249
- this.#drawSettingsSetupPlugins = [];
9250
- this.#drawSettingsCleanupPlugins = [];
8854
+ for (const layer of Object.values(exports.DrawLayer)) {
8855
+ if (typeof layer === "number") {
8856
+ this.#layers[layer] = [];
8857
+ }
8858
+ }
9251
8859
  }
9252
8860
  draw(cb) {
9253
8861
  const ctx = this.#context;
@@ -9304,21 +8912,40 @@
9304
8912
  });
9305
8913
  }
9306
8914
  drawParticles(delta) {
9307
- const { particles } = this.#container;
8915
+ const { particles, actualOptions } = this.#container;
9308
8916
  this.clear();
9309
8917
  particles.update(delta);
9310
8918
  this.draw(ctx => {
9311
- for (const plugin of this.#drawSettingsSetupPlugins) {
8919
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
8920
+ if (this.#backgroundElement) {
8921
+ try {
8922
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
8923
+ }
8924
+ catch {
8925
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
8926
+ }
8927
+ }
8928
+ const background = actualOptions.background;
8929
+ if (background.draw) {
8930
+ try {
8931
+ background.draw(ctx, delta);
8932
+ }
8933
+ catch {
8934
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
8935
+ }
8936
+ }
8937
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
8938
+ plugin.canvasPaint?.();
8939
+ }
8940
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
9312
8941
  plugin.drawSettingsSetup?.(ctx, delta);
9313
8942
  }
9314
- for (const plugin of this.#drawPlugins) {
8943
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.PluginContent)) {
9315
8944
  plugin.draw?.(ctx, delta);
9316
8945
  }
9317
8946
  particles.drawParticles(delta);
9318
- for (const plugin of this.#clearDrawPlugins) {
8947
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup)) {
9319
8948
  plugin.clearDraw?.(ctx, delta);
9320
- }
9321
- for (const plugin of this.#drawSettingsCleanupPlugins) {
9322
8949
  plugin.drawSettingsCleanup?.(ctx, delta);
9323
8950
  }
9324
8951
  });
@@ -9326,29 +8953,24 @@
9326
8953
  init() {
9327
8954
  this.initUpdaters();
9328
8955
  this.initPlugins();
8956
+ this.#resolveBackgroundElement();
9329
8957
  this.paint();
9330
8958
  }
9331
8959
  initPlugins() {
9332
- this.#colorPlugins = [];
9333
8960
  this.#canvasClearPlugins = [];
9334
- this.#canvasPaintPlugins = [];
9335
- this.#clearDrawPlugins = [];
8961
+ this.#colorPlugins = [];
9336
8962
  this.#drawParticlePlugins = [];
9337
8963
  this.#drawParticlesSetupPlugins = [];
9338
8964
  this.#drawParticlesCleanupPlugins = [];
9339
- this.#drawPlugins = [];
9340
- this.#drawSettingsSetupPlugins = [];
9341
- this.#drawSettingsCleanupPlugins = [];
8965
+ for (const layer of Object.values(exports.DrawLayer)) {
8966
+ if (typeof layer === "number") {
8967
+ this.#layers[layer] = [];
8968
+ }
8969
+ }
9342
8970
  for (const plugin of this.#container.plugins) {
9343
8971
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
9344
8972
  this.#colorPlugins.push(plugin);
9345
8973
  }
9346
- if (plugin.canvasClear) {
9347
- this.#canvasClearPlugins.push(plugin);
9348
- }
9349
- if (plugin.canvasPaint) {
9350
- this.#canvasPaintPlugins.push(plugin);
9351
- }
9352
8974
  if (plugin.drawParticle) {
9353
8975
  this.#drawParticlePlugins.push(plugin);
9354
8976
  }
@@ -9358,17 +8980,20 @@
9358
8980
  if (plugin.drawParticleCleanup) {
9359
8981
  this.#drawParticlesCleanupPlugins.push(plugin);
9360
8982
  }
9361
- if (plugin.draw) {
9362
- this.#drawPlugins.push(plugin);
8983
+ if (plugin.canvasClear) {
8984
+ this.#canvasClearPlugins.push(plugin);
8985
+ }
8986
+ if (plugin.canvasPaint) {
8987
+ this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
9363
8988
  }
9364
8989
  if (plugin.drawSettingsSetup) {
9365
- this.#drawSettingsSetupPlugins.push(plugin);
8990
+ this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
9366
8991
  }
9367
- if (plugin.drawSettingsCleanup) {
9368
- this.#drawSettingsCleanupPlugins.push(plugin);
8992
+ if (plugin.draw) {
8993
+ this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
9369
8994
  }
9370
- if (plugin.clearDraw) {
9371
- this.#clearDrawPlugins.push(plugin);
8995
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
8996
+ this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
9372
8997
  }
9373
8998
  }
9374
8999
  }
@@ -9386,7 +9011,7 @@
9386
9011
  }
9387
9012
  paint() {
9388
9013
  let handled = false;
9389
- for (const plugin of this.#canvasPaintPlugins) {
9014
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
9390
9015
  handled = plugin.canvasPaint?.() ?? false;
9391
9016
  if (handled) {
9392
9017
  break;
@@ -9559,6 +9184,9 @@
9559
9184
  }
9560
9185
  drawer.beforeDraw(data);
9561
9186
  }
9187
+ #getLayerPlugins(layer) {
9188
+ return this.#layers[layer];
9189
+ }
9562
9190
  #getPluginParticleColors(particle) {
9563
9191
  let fColor, sColor;
9564
9192
  for (const plugin of this.#colorPlugins) {
@@ -9576,6 +9204,39 @@
9576
9204
  this.#reusablePluginColors[sColorIndex] = sColor;
9577
9205
  return this.#reusablePluginColors;
9578
9206
  }
9207
+ #resolveBackgroundElement() {
9208
+ const background = this.#container.actualOptions.background;
9209
+ this.#backgroundElement = null;
9210
+ if (!background.element) {
9211
+ return;
9212
+ }
9213
+ if (typeof background.element === "string") {
9214
+ if (typeof document !== "undefined") {
9215
+ const node = document.querySelector(background.element);
9216
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
9217
+ this.#backgroundElement = node;
9218
+ }
9219
+ else if (node) {
9220
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
9221
+ }
9222
+ else {
9223
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
9224
+ }
9225
+ }
9226
+ }
9227
+ else if (background.element instanceof HTMLCanvasElement ||
9228
+ background.element instanceof OffscreenCanvas ||
9229
+ background.element instanceof HTMLVideoElement ||
9230
+ background.element instanceof HTMLImageElement) {
9231
+ this.#backgroundElement = background.element;
9232
+ }
9233
+ }
9234
+ #warnOnce(key, message) {
9235
+ if (!this.#backgroundWarnings.has(key)) {
9236
+ this.#backgroundWarnings.add(key);
9237
+ getLogger().warning(message);
9238
+ }
9239
+ }
9579
9240
  }
9580
9241
 
9581
9242
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -10152,7 +9813,6 @@
10152
9813
  }
10153
9814
  class Particle {
10154
9815
  backColor;
10155
- bubble;
10156
9816
  destroyed;
10157
9817
  direction;
10158
9818
  effect;
@@ -10186,7 +9846,6 @@
10186
9846
  shapeData;
10187
9847
  sides;
10188
9848
  size;
10189
- slow;
10190
9849
  spawning;
10191
9850
  strokeColor;
10192
9851
  strokeOpacity;
@@ -10208,18 +9867,25 @@
10208
9867
  d: 1,
10209
9868
  };
10210
9869
  #container;
9870
+ #modifiers = [];
10211
9871
  #pluginManager;
10212
9872
  constructor(pluginManager, container) {
10213
9873
  this.#pluginManager = pluginManager;
10214
9874
  this.#container = container;
10215
9875
  }
9876
+ addModifier(modifier) {
9877
+ this.#modifiers.push(modifier);
9878
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
9879
+ }
9880
+ clearModifiers() {
9881
+ this.#modifiers.length = 0;
9882
+ }
10216
9883
  destroy(override) {
10217
9884
  if (this.unbreakable || this.destroyed) {
10218
9885
  return;
10219
9886
  }
10220
9887
  this.destroyed = true;
10221
- this.bubble.inRange = false;
10222
- this.slow.inRange = false;
9888
+ this.clearModifiers();
10223
9889
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
10224
9890
  shapeDrawer?.particleDestroy?.(this);
10225
9891
  for (const plugin of container.particleDestroyedPlugins) {
@@ -10241,13 +9907,16 @@
10241
9907
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
10242
9908
  }
10243
9909
  getFillColor() {
10244
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
9910
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
10245
9911
  }
10246
9912
  getMass() {
10247
9913
  return this.getRadius() ** squareExp * Math.PI * half;
10248
9914
  }
9915
+ getModifier(id) {
9916
+ return this.#modifiers.find(m => m.id === id);
9917
+ }
10249
9918
  getOpacity() {
10250
- 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;
9919
+ 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;
10251
9920
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
10252
9921
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
10253
9922
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -10260,7 +9929,7 @@
10260
9929
  return this.#cachedPosition;
10261
9930
  }
10262
9931
  getRadius() {
10263
- return this.bubble.radius ?? this.size.value;
9932
+ return this.#applyModifiers(this.size.value, m => m.radius);
10264
9933
  }
10265
9934
  getRotateData() {
10266
9935
  const angle = this.getAngle();
@@ -10269,7 +9938,7 @@
10269
9938
  return this.#cachedRotateData;
10270
9939
  }
10271
9940
  getStrokeColor() {
10272
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
9941
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
10273
9942
  }
10274
9943
  getTransformData(externalTransform) {
10275
9944
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -10289,13 +9958,6 @@
10289
9958
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
10290
9959
  container.retina.initParticle(this);
10291
9960
  runUpdaterPreInit(container.particleUpdaters, this);
10292
- this.bubble = {
10293
- inRange: false,
10294
- };
10295
- this.slow = {
10296
- inRange: false,
10297
- factor: 1,
10298
- };
10299
9961
  this.#initPosition(position);
10300
9962
  this.initialVelocity = this.#calculateVelocity();
10301
9963
  this.velocity = this.initialVelocity.copy();
@@ -10335,11 +9997,29 @@
10335
9997
  isVisible() {
10336
9998
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
10337
9999
  }
10000
+ removeModifier(id) {
10001
+ const idx = this.#modifiers.findIndex(m => m.id === id);
10002
+ if (idx >= defaultAngle) {
10003
+ this.#modifiers.splice(idx, identity$2);
10004
+ }
10005
+ }
10338
10006
  reset() {
10339
10007
  for (const updater of this.#container.particleUpdaters) {
10340
10008
  updater.reset?.(this);
10341
10009
  }
10342
10010
  }
10011
+ #applyModifiers(base, getter) {
10012
+ let value = base;
10013
+ for (const mod of this.#modifiers) {
10014
+ if (mod.enabled) {
10015
+ const override = getter(mod);
10016
+ if (override !== undefined) {
10017
+ value = override;
10018
+ }
10019
+ }
10020
+ }
10021
+ return value;
10022
+ }
10343
10023
  #calcPosition(position, zIndex) {
10344
10024
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
10345
10025
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -12225,6 +11905,7 @@
12225
11905
  });
12226
11906
 
12227
11907
  class BlendPluginInstance {
11908
+ layer = exports.DrawLayer.CanvasSetup;
12228
11909
  #container;
12229
11910
  #defaultCompositeValue;
12230
11911
  constructor(container) {
@@ -12370,7 +12051,8 @@
12370
12051
  particle.lastPathTime -= pathDelay;
12371
12052
  }
12372
12053
  function getProximitySpeedFactor(particle) {
12373
- return particle.slow.inRange ? particle.slow.factor : identity$2;
12054
+ const mod = particle.getModifier("slow");
12055
+ return mod?.enabled ? (mod.speedFactor ?? identity$2) : identity$2;
12374
12056
  }
12375
12057
  function initSpin(container, particle) {
12376
12058
  const options = particle.options, spinOptions = options.move.spin;
@@ -13387,6 +13069,7 @@
13387
13069
  exports.hPhase = hPhase;
13388
13070
  exports.half = half;
13389
13071
  exports.hslToRgb = hslToRgb;
13072
+ exports.hslToRgbFloat = hslToRgbFloat;
13390
13073
  exports.hslaToRgba = hslaToRgba;
13391
13074
  exports.identity = identity$2;
13392
13075
  exports.inverseFactorNumerator = inverseFactorNumerator;