@tsparticles/ribbons 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$1
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$1, 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$1, 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$1).toString()})`;
2002
2035
  }
2003
2036
  function getStyleFromHsl(color, hdr, opacity) {
2004
- const op = opacity ?? defaultOpacity$1, 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$1, 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.0");
2256
+ engine.checkVersion("4.3.0");
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.0");
2293
+ engine.checkVersion("4.3.0");
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.0");
2341
+ engine.checkVersion("4.3.0");
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.0");
2394
+ engine.checkVersion("4.3.0");
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.0");
2418
+ engine.checkVersion("4.3.0");
2386
2419
  await engine.pluginManager.register(e => {
2387
2420
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2388
2421
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2592,7 +2625,7 @@
2592
2625
  }
2593
2626
 
2594
2627
  async function loadOpacityUpdater(engine) {
2595
- engine.checkVersion("4.2.0");
2628
+ engine.checkVersion("4.3.0");
2596
2629
  await engine.pluginManager.register(e => {
2597
2630
  e.pluginManager.addParticleUpdater("opacity", container => {
2598
2631
  return Promise.resolve(new OpacityUpdater(container));
@@ -2937,7 +2970,7 @@
2937
2970
  }
2938
2971
 
2939
2972
  async function loadOutModesUpdater(engine) {
2940
- engine.checkVersion("4.2.0");
2973
+ engine.checkVersion("4.3.0");
2941
2974
  await engine.pluginManager.register(e => {
2942
2975
  e.pluginManager.addParticleUpdater("outModes", container => {
2943
2976
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3002,13 +3035,13 @@
3002
3035
  if (!this.isEnabled(particle)) {
3003
3036
  return;
3004
3037
  }
3005
- updateColor(particle.fillColor, delta);
3006
- updateColor(particle.strokeColor, delta);
3038
+ updateColor(particle.fillColor, delta, this.#container.hdr);
3039
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
3007
3040
  }
3008
3041
  }
3009
3042
 
3010
3043
  async function loadPaintUpdater(engine) {
3011
- engine.checkVersion("4.2.0");
3044
+ engine.checkVersion("4.3.0");
3012
3045
  await engine.pluginManager.register(e => {
3013
3046
  e.pluginManager.addParticleUpdater("paint", container => {
3014
3047
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3063,7 +3096,7 @@
3063
3096
  }
3064
3097
 
3065
3098
  async function loadRgbColorPlugin(engine) {
3066
- engine.checkVersion("4.2.0");
3099
+ engine.checkVersion("4.3.0");
3067
3100
  await engine.pluginManager.register(e => {
3068
3101
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3069
3102
  });
@@ -3148,7 +3181,7 @@
3148
3181
  }
3149
3182
 
3150
3183
  async function loadSizeUpdater(engine) {
3151
- engine.checkVersion("4.2.0");
3184
+ engine.checkVersion("4.3.0");
3152
3185
  await engine.pluginManager.register(e => {
3153
3186
  e.pluginManager.addParticleUpdater("size", container => {
3154
3187
  return Promise.resolve(new SizeUpdater(container));
@@ -3157,7 +3190,7 @@
3157
3190
  }
3158
3191
 
3159
3192
  async function loadBasic(engine) {
3160
- engine.checkVersion("4.2.0");
3193
+ engine.checkVersion("4.3.0");
3161
3194
  await engine.pluginManager.register(async (e) => {
3162
3195
  await Promise.all([
3163
3196
  loadBlendPlugin(e),
@@ -3397,7 +3430,7 @@
3397
3430
  })(EmitterClickMode || (EmitterClickMode = {}));
3398
3431
 
3399
3432
  async function loadEmittersPluginSimple(engine) {
3400
- engine.checkVersion("4.2.0");
3433
+ engine.checkVersion("4.3.0");
3401
3434
  await engine.pluginManager.register(async (e) => {
3402
3435
  const instancesManager = await getEmittersInstancesManager(e);
3403
3436
  await addEmittersShapesManager(e);
@@ -3485,7 +3518,7 @@
3485
3518
  }
3486
3519
 
3487
3520
  async function loadEmittersShapeSquare(engine) {
3488
- engine.checkVersion("4.2.0");
3521
+ engine.checkVersion("4.3.0");
3489
3522
  await engine.pluginManager.register((e) => {
3490
3523
  ensureEmittersPluginLoaded(e);
3491
3524
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -3629,7 +3662,7 @@
3629
3662
  }
3630
3663
 
3631
3664
  async function loadLifeUpdater(engine) {
3632
- engine.checkVersion("4.2.0");
3665
+ engine.checkVersion("4.3.0");
3633
3666
  await engine.pluginManager.register(e => {
3634
3667
  e.pluginManager.addParticleUpdater("life", container => {
3635
3668
  return Promise.resolve(new LifeUpdater(container));
@@ -3683,7 +3716,7 @@
3683
3716
  }
3684
3717
 
3685
3718
  async function loadMotionPlugin(engine) {
3686
- engine.checkVersion("4.2.0");
3719
+ engine.checkVersion("4.3.0");
3687
3720
  await engine.pluginManager.register(e => {
3688
3721
  e.pluginManager.addPlugin(new MotionPlugin());
3689
3722
  });
@@ -4081,7 +4114,7 @@
4081
4114
  }
4082
4115
 
4083
4116
  async function loadRibbonShape(engine) {
4084
- engine.checkVersion("4.2.0");
4117
+ engine.checkVersion("4.3.0");
4085
4118
  await engine.pluginManager.register(e => {
4086
4119
  e.pluginManager.addShape(["ribbon"], (container) => Promise.resolve(new RibbonDrawer(container)));
4087
4120
  });
@@ -4095,7 +4128,6 @@
4095
4128
  positionX;
4096
4129
  ribbonOptions;
4097
4130
  scalar;
4098
- ticks;
4099
4131
  zIndex;
4100
4132
  constructor() {
4101
4133
  this.count = 5;
@@ -4104,7 +4136,6 @@
4104
4136
  height: 0,
4105
4137
  };
4106
4138
  this.positionX = 50;
4107
- this.ticks = 200;
4108
4139
  this.colors = ["#FF0055", "#00D1FF", "#FFD23F", "#61FF7E", "#B284FF"];
4109
4140
  this.ribbonOptions = {
4110
4141
  angle: 45,
@@ -4165,7 +4196,6 @@
4165
4196
  if (count !== undefined) {
4166
4197
  this.count = count;
4167
4198
  }
4168
- loadProperty(this, "ticks", data.ticks);
4169
4199
  if (data.emitterSize) {
4170
4200
  if (data.emitterSize.width !== undefined) {
4171
4201
  this.emitterSize.width = data.emitterSize.width;
@@ -4404,7 +4434,7 @@
4404
4434
 
4405
4435
  let initPromise = null;
4406
4436
  async function doInitPlugins(engine) {
4407
- engine.checkVersion("4.2.0");
4437
+ engine.checkVersion("4.3.0");
4408
4438
  await engine.pluginManager.register(async (e) => {
4409
4439
  const emittersRegister = async (engine) => {
4410
4440
  await loadEmittersPluginSimple(engine);
@@ -4471,7 +4501,7 @@
4471
4501
  ribbons.init = async () => {
4472
4502
  await initPlugins(tsParticles);
4473
4503
  };
4474
- ribbons.version = "4.2.0";
4504
+ ribbons.version = "4.3.0";
4475
4505
  globalThis.ribbons = ribbons;
4476
4506
 
4477
4507
  const globalObject = globalThis;
@@ -4486,10 +4516,10 @@
4486
4516
  }
4487
4517
  }
4488
4518
  class RenderManager {
4519
+ #backgroundElement;
4520
+ #backgroundWarnings;
4489
4521
  #canvasClearPlugins;
4490
4522
  #canvasManager;
4491
- #canvasPaintPlugins;
4492
- #clearDrawPlugins;
4493
4523
  #colorPlugins;
4494
4524
  #container;
4495
4525
  #context;
@@ -4497,9 +4527,7 @@
4497
4527
  #drawParticlePlugins;
4498
4528
  #drawParticlesCleanupPlugins;
4499
4529
  #drawParticlesSetupPlugins;
4500
- #drawPlugins;
4501
- #drawSettingsCleanupPlugins;
4502
- #drawSettingsSetupPlugins;
4530
+ #layers;
4503
4531
  #pluginManager;
4504
4532
  #postDrawUpdaters;
4505
4533
  #preDrawUpdaters;
@@ -4511,18 +4539,25 @@
4511
4539
  this.#container = container;
4512
4540
  this.#canvasManager = canvasManager;
4513
4541
  this.#context = null;
4542
+ this.#backgroundElement = null;
4543
+ this.#backgroundWarnings = new Set();
4514
4544
  this.#preDrawUpdaters = [];
4515
4545
  this.#postDrawUpdaters = [];
4516
- this.#colorPlugins = [];
4517
4546
  this.#canvasClearPlugins = [];
4518
- this.#canvasPaintPlugins = [];
4519
- this.#clearDrawPlugins = [];
4547
+ this.#colorPlugins = [];
4520
4548
  this.#drawParticlePlugins = [];
4521
4549
  this.#drawParticlesCleanupPlugins = [];
4522
4550
  this.#drawParticlesSetupPlugins = [];
4523
- this.#drawPlugins = [];
4524
- this.#drawSettingsSetupPlugins = [];
4525
- this.#drawSettingsCleanupPlugins = [];
4551
+ this.#layers = {
4552
+ 0: [],
4553
+ 1: [],
4554
+ 2: [],
4555
+ 3: [],
4556
+ 4: [],
4557
+ 5: [],
4558
+ 6: [],
4559
+ 7: [],
4560
+ };
4526
4561
  }
4527
4562
  get settings() {
4528
4563
  return this.#contextSettings;
@@ -4536,32 +4571,38 @@
4536
4571
  });
4537
4572
  }
4538
4573
  clear() {
4539
- let pluginHandled = false;
4540
4574
  for (const plugin of this.#canvasClearPlugins) {
4541
- pluginHandled = plugin.canvasClear?.() ?? false;
4542
- if (pluginHandled) {
4543
- break;
4575
+ if (plugin.canvasClear?.() ?? false) {
4576
+ return;
4544
4577
  }
4545
4578
  }
4546
- if (pluginHandled) {
4547
- return;
4579
+ for (const layer of Object.values(exports.DrawLayer)) {
4580
+ if (typeof layer === "number") {
4581
+ for (const plugin of this.#getLayerPlugins(layer)) {
4582
+ if (plugin.canvasClear?.() ?? false) {
4583
+ return;
4584
+ }
4585
+ }
4586
+ }
4548
4587
  }
4549
4588
  this.canvasClear();
4550
4589
  }
4551
4590
  destroy() {
4552
4591
  this.stop();
4592
+ this.#backgroundElement = null;
4593
+ this.#backgroundWarnings.clear();
4553
4594
  this.#preDrawUpdaters = [];
4554
4595
  this.#postDrawUpdaters = [];
4555
- this.#colorPlugins = [];
4556
4596
  this.#canvasClearPlugins = [];
4557
- this.#canvasPaintPlugins = [];
4558
- this.#clearDrawPlugins = [];
4597
+ this.#colorPlugins = [];
4559
4598
  this.#drawParticlePlugins = [];
4560
4599
  this.#drawParticlesCleanupPlugins = [];
4561
4600
  this.#drawParticlesSetupPlugins = [];
4562
- this.#drawPlugins = [];
4563
- this.#drawSettingsSetupPlugins = [];
4564
- this.#drawSettingsCleanupPlugins = [];
4601
+ for (const layer of Object.values(exports.DrawLayer)) {
4602
+ if (typeof layer === "number") {
4603
+ this.#layers[layer] = [];
4604
+ }
4605
+ }
4565
4606
  }
4566
4607
  draw(cb) {
4567
4608
  const ctx = this.#context;
@@ -4618,21 +4659,40 @@
4618
4659
  });
4619
4660
  }
4620
4661
  drawParticles(delta) {
4621
- const { particles } = this.#container;
4662
+ const { particles, actualOptions } = this.#container;
4622
4663
  this.clear();
4623
4664
  particles.update(delta);
4624
4665
  this.draw(ctx => {
4625
- for (const plugin of this.#drawSettingsSetupPlugins) {
4666
+ const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
4667
+ if (this.#backgroundElement) {
4668
+ try {
4669
+ ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
4670
+ }
4671
+ catch {
4672
+ this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
4673
+ }
4674
+ }
4675
+ const background = actualOptions.background;
4676
+ if (background.draw) {
4677
+ try {
4678
+ background.draw(ctx, delta);
4679
+ }
4680
+ catch {
4681
+ this.#warnOnce("background-draw-error", "Error in background.draw callback");
4682
+ }
4683
+ }
4684
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
4685
+ plugin.canvasPaint?.();
4686
+ }
4687
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
4626
4688
  plugin.drawSettingsSetup?.(ctx, delta);
4627
4689
  }
4628
- for (const plugin of this.#drawPlugins) {
4690
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.PluginContent)) {
4629
4691
  plugin.draw?.(ctx, delta);
4630
4692
  }
4631
4693
  particles.drawParticles(delta);
4632
- for (const plugin of this.#clearDrawPlugins) {
4694
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup)) {
4633
4695
  plugin.clearDraw?.(ctx, delta);
4634
- }
4635
- for (const plugin of this.#drawSettingsCleanupPlugins) {
4636
4696
  plugin.drawSettingsCleanup?.(ctx, delta);
4637
4697
  }
4638
4698
  });
@@ -4640,29 +4700,24 @@
4640
4700
  init() {
4641
4701
  this.initUpdaters();
4642
4702
  this.initPlugins();
4703
+ this.#resolveBackgroundElement();
4643
4704
  this.paint();
4644
4705
  }
4645
4706
  initPlugins() {
4646
- this.#colorPlugins = [];
4647
4707
  this.#canvasClearPlugins = [];
4648
- this.#canvasPaintPlugins = [];
4649
- this.#clearDrawPlugins = [];
4708
+ this.#colorPlugins = [];
4650
4709
  this.#drawParticlePlugins = [];
4651
4710
  this.#drawParticlesSetupPlugins = [];
4652
4711
  this.#drawParticlesCleanupPlugins = [];
4653
- this.#drawPlugins = [];
4654
- this.#drawSettingsSetupPlugins = [];
4655
- this.#drawSettingsCleanupPlugins = [];
4712
+ for (const layer of Object.values(exports.DrawLayer)) {
4713
+ if (typeof layer === "number") {
4714
+ this.#layers[layer] = [];
4715
+ }
4716
+ }
4656
4717
  for (const plugin of this.#container.plugins) {
4657
4718
  if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4658
4719
  this.#colorPlugins.push(plugin);
4659
4720
  }
4660
- if (plugin.canvasClear) {
4661
- this.#canvasClearPlugins.push(plugin);
4662
- }
4663
- if (plugin.canvasPaint) {
4664
- this.#canvasPaintPlugins.push(plugin);
4665
- }
4666
4721
  if (plugin.drawParticle) {
4667
4722
  this.#drawParticlePlugins.push(plugin);
4668
4723
  }
@@ -4672,17 +4727,20 @@
4672
4727
  if (plugin.drawParticleCleanup) {
4673
4728
  this.#drawParticlesCleanupPlugins.push(plugin);
4674
4729
  }
4675
- if (plugin.draw) {
4676
- this.#drawPlugins.push(plugin);
4730
+ if (plugin.canvasClear) {
4731
+ this.#canvasClearPlugins.push(plugin);
4732
+ }
4733
+ if (plugin.canvasPaint) {
4734
+ this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
4677
4735
  }
4678
4736
  if (plugin.drawSettingsSetup) {
4679
- this.#drawSettingsSetupPlugins.push(plugin);
4737
+ this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
4680
4738
  }
4681
- if (plugin.drawSettingsCleanup) {
4682
- this.#drawSettingsCleanupPlugins.push(plugin);
4739
+ if (plugin.draw) {
4740
+ this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
4683
4741
  }
4684
- if (plugin.clearDraw) {
4685
- this.#clearDrawPlugins.push(plugin);
4742
+ if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
4743
+ this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
4686
4744
  }
4687
4745
  }
4688
4746
  }
@@ -4700,7 +4758,7 @@
4700
4758
  }
4701
4759
  paint() {
4702
4760
  let handled = false;
4703
- for (const plugin of this.#canvasPaintPlugins) {
4761
+ for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
4704
4762
  handled = plugin.canvasPaint?.() ?? false;
4705
4763
  if (handled) {
4706
4764
  break;
@@ -4873,6 +4931,9 @@
4873
4931
  }
4874
4932
  drawer.beforeDraw(data);
4875
4933
  }
4934
+ #getLayerPlugins(layer) {
4935
+ return this.#layers[layer];
4936
+ }
4876
4937
  #getPluginParticleColors(particle) {
4877
4938
  let fColor, sColor;
4878
4939
  for (const plugin of this.#colorPlugins) {
@@ -4890,6 +4951,39 @@
4890
4951
  this.#reusablePluginColors[sColorIndex] = sColor;
4891
4952
  return this.#reusablePluginColors;
4892
4953
  }
4954
+ #resolveBackgroundElement() {
4955
+ const background = this.#container.actualOptions.background;
4956
+ this.#backgroundElement = null;
4957
+ if (!background.element) {
4958
+ return;
4959
+ }
4960
+ if (typeof background.element === "string") {
4961
+ if (typeof document !== "undefined") {
4962
+ const node = document.querySelector(background.element);
4963
+ if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4964
+ this.#backgroundElement = node;
4965
+ }
4966
+ else if (node) {
4967
+ this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
4968
+ }
4969
+ else {
4970
+ this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
4971
+ }
4972
+ }
4973
+ }
4974
+ else if (background.element instanceof HTMLCanvasElement ||
4975
+ background.element instanceof OffscreenCanvas ||
4976
+ background.element instanceof HTMLVideoElement ||
4977
+ background.element instanceof HTMLImageElement) {
4978
+ this.#backgroundElement = background.element;
4979
+ }
4980
+ }
4981
+ #warnOnce(key, message) {
4982
+ if (!this.#backgroundWarnings.has(key)) {
4983
+ this.#backgroundWarnings.add(key);
4984
+ getLogger().warning(message);
4985
+ }
4986
+ }
4893
4987
  }
4894
4988
 
4895
4989
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -5466,7 +5560,6 @@
5466
5560
  }
5467
5561
  class Particle {
5468
5562
  backColor;
5469
- bubble;
5470
5563
  destroyed;
5471
5564
  direction;
5472
5565
  effect;
@@ -5500,7 +5593,6 @@
5500
5593
  shapeData;
5501
5594
  sides;
5502
5595
  size;
5503
- slow;
5504
5596
  spawning;
5505
5597
  strokeColor;
5506
5598
  strokeOpacity;
@@ -5522,18 +5614,25 @@
5522
5614
  d: 1,
5523
5615
  };
5524
5616
  #container;
5617
+ #modifiers = [];
5525
5618
  #pluginManager;
5526
5619
  constructor(pluginManager, container) {
5527
5620
  this.#pluginManager = pluginManager;
5528
5621
  this.#container = container;
5529
5622
  }
5623
+ addModifier(modifier) {
5624
+ this.#modifiers.push(modifier);
5625
+ this.#modifiers.sort((a, b) => a.priority - b.priority);
5626
+ }
5627
+ clearModifiers() {
5628
+ this.#modifiers.length = 0;
5629
+ }
5530
5630
  destroy(override) {
5531
5631
  if (this.unbreakable || this.destroyed) {
5532
5632
  return;
5533
5633
  }
5534
5634
  this.destroyed = true;
5535
- this.bubble.inRange = false;
5536
- this.slow.inRange = false;
5635
+ this.clearModifiers();
5537
5636
  const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
5538
5637
  shapeDrawer?.particleDestroy?.(this);
5539
5638
  for (const plugin of container.particleDestroyedPlugins) {
@@ -5555,13 +5654,16 @@
5555
5654
  return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle$1);
5556
5655
  }
5557
5656
  getFillColor() {
5558
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.fillColor));
5657
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
5559
5658
  }
5560
5659
  getMass() {
5561
5660
  return this.getRadius() ** squareExp * Math.PI * half$1;
5562
5661
  }
5662
+ getModifier(id) {
5663
+ return this.#modifiers.find(m => m.id === id);
5664
+ }
5563
5665
  getOpacity() {
5564
- const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, opacity = this.bubble.opacity ?? getRangeValue(this.opacity?.value ?? defaultOpacity$1), fillOpacity = this.fillOpacity ?? defaultOpacity$1, strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5666
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$1, strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5565
5667
  this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5566
5668
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5567
5669
  this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
@@ -5574,7 +5676,7 @@
5574
5676
  return this.#cachedPosition;
5575
5677
  }
5576
5678
  getRadius() {
5577
- return this.bubble.radius ?? this.size.value;
5679
+ return this.#applyModifiers(this.size.value, m => m.radius);
5578
5680
  }
5579
5681
  getRotateData() {
5580
5682
  const angle = this.getAngle();
@@ -5583,7 +5685,7 @@
5583
5685
  return this.#cachedRotateData;
5584
5686
  }
5585
5687
  getStrokeColor() {
5586
- return this.#getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
5688
+ return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
5587
5689
  }
5588
5690
  getTransformData(externalTransform) {
5589
5691
  const rotateData = this.getRotateData(), rotating = this.isRotating;
@@ -5603,13 +5705,6 @@
5603
5705
  this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
5604
5706
  container.retina.initParticle(this);
5605
5707
  runUpdaterPreInit(container.particleUpdaters, this);
5606
- this.bubble = {
5607
- inRange: false,
5608
- };
5609
- this.slow = {
5610
- inRange: false,
5611
- factor: 1,
5612
- };
5613
5708
  this.#initPosition(position);
5614
5709
  this.initialVelocity = this.#calculateVelocity();
5615
5710
  this.velocity = this.initialVelocity.copy();
@@ -5649,11 +5744,29 @@
5649
5744
  isVisible() {
5650
5745
  return !this.destroyed && !this.spawning && this.isInsideCanvas();
5651
5746
  }
5747
+ removeModifier(id) {
5748
+ const idx = this.#modifiers.findIndex(m => m.id === id);
5749
+ if (idx >= defaultAngle$1) {
5750
+ this.#modifiers.splice(idx, identity$2);
5751
+ }
5752
+ }
5652
5753
  reset() {
5653
5754
  for (const updater of this.#container.particleUpdaters) {
5654
5755
  updater.reset?.(this);
5655
5756
  }
5656
5757
  }
5758
+ #applyModifiers(base, getter) {
5759
+ let value = base;
5760
+ for (const mod of this.#modifiers) {
5761
+ if (mod.enabled) {
5762
+ const override = getter(mod);
5763
+ if (override !== undefined) {
5764
+ value = override;
5765
+ }
5766
+ }
5767
+ }
5768
+ return value;
5769
+ }
5657
5770
  #calcPosition(position, zIndex) {
5658
5771
  let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
5659
5772
  const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
@@ -6755,6 +6868,7 @@
6755
6868
  });
6756
6869
 
6757
6870
  class BlendPluginInstance {
6871
+ layer = exports.DrawLayer.CanvasSetup;
6758
6872
  #container;
6759
6873
  #defaultCompositeValue;
6760
6874
  constructor(container) {
@@ -6900,7 +7014,8 @@
6900
7014
  particle.lastPathTime -= pathDelay;
6901
7015
  }
6902
7016
  function getProximitySpeedFactor(particle) {
6903
- return particle.slow.inRange ? particle.slow.factor : identity$2;
7017
+ const mod = particle.getModifier("slow");
7018
+ return mod?.enabled ? (mod.speedFactor ?? identity$2) : identity$2;
6904
7019
  }
6905
7020
  function initSpin(container, particle) {
6906
7021
  const options = particle.options, spinOptions = options.move.spin;
@@ -7685,6 +7800,7 @@
7685
7800
  exports.hPhase = hPhase;
7686
7801
  exports.half = half$1;
7687
7802
  exports.hslToRgb = hslToRgb;
7803
+ exports.hslToRgbFloat = hslToRgbFloat;
7688
7804
  exports.hslaToRgba = hslaToRgba;
7689
7805
  exports.identity = identity$2;
7690
7806
  exports.inverseFactorNumerator = inverseFactorNumerator;