@tsparticles/preset-links 4.0.0-beta.16 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* Preset v4.0.0-beta.16 */
2
+ /* Preset v4.0.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) :
@@ -968,7 +968,7 @@
968
968
  }
969
969
  }
970
970
  else {
971
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases[canvasFirstIndex];
971
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
972
972
  if (foundCanvas) {
973
973
  canvasEl = foundCanvas;
974
974
  canvasEl.dataset[generatedAttribute] = generatedFalse;
@@ -1005,7 +1005,7 @@
1005
1005
  return this._domArray;
1006
1006
  }
1007
1007
  get version() {
1008
- return "4.0.0-beta.16";
1008
+ return "4.0.0";
1009
1009
  }
1010
1010
  addEventListener(type, listener) {
1011
1011
  this._eventDispatcher.addEventListener(type, listener);
@@ -1036,7 +1036,11 @@
1036
1036
  }
1037
1037
  async load(params) {
1038
1038
  await this.init();
1039
- const { Container } = await Promise.resolve().then(function () { return Container$1; }), id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor).toString()}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container({
1039
+ let domSourceElement;
1040
+ if (typeof HTMLElement !== "undefined" && params.element instanceof HTMLElement) {
1041
+ domSourceElement = params.element;
1042
+ }
1043
+ const { Container } = await Promise.resolve().then(function () { return Container$1; }), id = params.id ?? domSourceElement?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor).toString()}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container({
1040
1044
  dispatchCallback: (eventType, args) => {
1041
1045
  this.dispatchEvent(eventType, args);
1042
1046
  },
@@ -1063,8 +1067,10 @@
1063
1067
  else {
1064
1068
  items.push(newItem);
1065
1069
  }
1066
- const domContainer = getDomContainer(id, params.element), canvasEl = getCanvasFromContainer(domContainer);
1067
- newItem.canvas.loadCanvas(canvasEl);
1070
+ const sourceCanvas = typeof OffscreenCanvas !== "undefined" && params.element instanceof OffscreenCanvas
1071
+ ? params.element
1072
+ : getCanvasFromContainer(getDomContainer(id, domSourceElement));
1073
+ newItem.canvas.loadCanvas(sourceCanvas);
1068
1074
  await newItem.start();
1069
1075
  return newItem;
1070
1076
  }
@@ -2914,7 +2920,7 @@
2914
2920
  }
2915
2921
 
2916
2922
  async function loadCircleShape(engine) {
2917
- engine.checkVersion("4.0.0-beta.16");
2923
+ engine.checkVersion("4.0.0");
2918
2924
  await engine.pluginManager.register(e => {
2919
2925
  e.pluginManager.addShape(["circle"], () => {
2920
2926
  return Promise.resolve(new CircleDrawer());
@@ -2962,7 +2968,7 @@
2962
2968
  }
2963
2969
 
2964
2970
  async function loadHexColorPlugin(engine) {
2965
- engine.checkVersion("4.0.0-beta.16");
2971
+ engine.checkVersion("4.0.0");
2966
2972
  await engine.pluginManager.register(e => {
2967
2973
  e.pluginManager.addColorManager("hex", new HexColorManager());
2968
2974
  });
@@ -3015,7 +3021,7 @@
3015
3021
  }
3016
3022
 
3017
3023
  async function loadHslColorPlugin(engine) {
3018
- engine.checkVersion("4.0.0-beta.16");
3024
+ engine.checkVersion("4.0.0");
3019
3025
  await engine.pluginManager.register(e => {
3020
3026
  e.pluginManager.addColorManager("hsl", new HslColorManager());
3021
3027
  });
@@ -3039,7 +3045,7 @@
3039
3045
  }
3040
3046
 
3041
3047
  async function loadMovePlugin(engine) {
3042
- engine.checkVersion("4.0.0-beta.16");
3048
+ engine.checkVersion("4.0.0");
3043
3049
  await engine.pluginManager.register(e => {
3044
3050
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
3045
3051
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -3100,7 +3106,7 @@
3100
3106
  }
3101
3107
 
3102
3108
  async function loadOpacityUpdater(engine) {
3103
- engine.checkVersion("4.0.0-beta.16");
3109
+ engine.checkVersion("4.0.0");
3104
3110
  await engine.pluginManager.register(e => {
3105
3111
  e.pluginManager.addParticleUpdater("opacity", container => {
3106
3112
  return Promise.resolve(new OpacityUpdater(container));
@@ -3452,7 +3458,7 @@
3452
3458
  }
3453
3459
 
3454
3460
  async function loadOutModesUpdater(engine) {
3455
- engine.checkVersion("4.0.0-beta.16");
3461
+ engine.checkVersion("4.0.0");
3456
3462
  await engine.pluginManager.register(e => {
3457
3463
  e.pluginManager.addParticleUpdater("outModes", container => {
3458
3464
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3523,7 +3529,7 @@
3523
3529
  }
3524
3530
 
3525
3531
  async function loadPaintUpdater(engine) {
3526
- engine.checkVersion("4.0.0-beta.16");
3532
+ engine.checkVersion("4.0.0");
3527
3533
  await engine.pluginManager.register(e => {
3528
3534
  e.pluginManager.addParticleUpdater("paint", container => {
3529
3535
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3578,7 +3584,7 @@
3578
3584
  }
3579
3585
 
3580
3586
  async function loadRgbColorPlugin(engine) {
3581
- engine.checkVersion("4.0.0-beta.16");
3587
+ engine.checkVersion("4.0.0");
3582
3588
  await engine.pluginManager.register(e => {
3583
3589
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3584
3590
  });
@@ -3621,7 +3627,7 @@
3621
3627
  }
3622
3628
 
3623
3629
  async function loadSizeUpdater(engine) {
3624
- engine.checkVersion("4.0.0-beta.16");
3630
+ engine.checkVersion("4.0.0");
3625
3631
  await engine.pluginManager.register(e => {
3626
3632
  e.pluginManager.addParticleUpdater("size", container => {
3627
3633
  return Promise.resolve(new SizeUpdater(container));
@@ -3630,7 +3636,7 @@
3630
3636
  }
3631
3637
 
3632
3638
  async function loadBasic(engine) {
3633
- engine.checkVersion("4.0.0-beta.16");
3639
+ engine.checkVersion("4.0.0");
3634
3640
  await engine.pluginManager.register(async (e) => {
3635
3641
  await Promise.all([
3636
3642
  loadHexColorPlugin(e),
@@ -3867,7 +3873,7 @@
3867
3873
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3868
3874
 
3869
3875
  async function loadInteractivityPlugin(engine) {
3870
- engine.checkVersion("4.0.0-beta.16");
3876
+ engine.checkVersion("4.0.0");
3871
3877
  await engine.pluginManager.register(e => {
3872
3878
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3873
3879
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -4193,7 +4199,7 @@
4193
4199
  }
4194
4200
 
4195
4201
  async function loadParticlesLinksInteraction(engine) {
4196
- engine.checkVersion("4.0.0-beta.16");
4202
+ engine.checkVersion("4.0.0");
4197
4203
  await engine.pluginManager.register((e) => {
4198
4204
  const pluginManager = e.pluginManager;
4199
4205
  ensureInteractivityPluginLoaded(e);
@@ -4554,6 +4560,25 @@
4554
4560
  };
4555
4561
  }
4556
4562
 
4563
+ const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
4564
+ const transferredCanvas = transferredCanvases.get(canvas);
4565
+ if (transferredCanvas) {
4566
+ return transferredCanvas;
4567
+ }
4568
+ if (typeof canvas.transferControlToOffscreen !== "function") {
4569
+ throw new TypeError("OffscreenCanvas is required but not supported by this browser");
4570
+ }
4571
+ try {
4572
+ const offscreenCanvas = canvas.transferControlToOffscreen();
4573
+ transferredCanvases.set(canvas, offscreenCanvas);
4574
+ return offscreenCanvas;
4575
+ }
4576
+ catch {
4577
+ throw new TypeError("OffscreenCanvas transfer failed");
4578
+ }
4579
+ }, isHtmlCanvasElement = (canvas) => {
4580
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
4581
+ };
4557
4582
  function setStyle(canvas, style, important = false) {
4558
4583
  if (!style) {
4559
4584
  return;
@@ -4584,8 +4609,9 @@
4584
4609
  }
4585
4610
  }
4586
4611
  class CanvasManager {
4587
- element;
4612
+ domElement;
4588
4613
  render;
4614
+ renderCanvas;
4589
4615
  size;
4590
4616
  zoom = defaultZoom;
4591
4617
  _container;
@@ -4620,9 +4646,10 @@
4620
4646
  destroy() {
4621
4647
  this.stop();
4622
4648
  if (this._generated) {
4623
- const element = this.element;
4649
+ const element = this.domElement;
4624
4650
  element?.remove();
4625
- this.element = undefined;
4651
+ this.domElement = undefined;
4652
+ this.renderCanvas = undefined;
4626
4653
  }
4627
4654
  else {
4628
4655
  this._resetOriginalStyle();
@@ -4655,16 +4682,17 @@
4655
4682
  this._initStyle();
4656
4683
  this.initBackground();
4657
4684
  this._safeMutationObserver(obs => {
4658
- if (!this.element || !(this.element instanceof Node)) {
4685
+ const element = this.domElement;
4686
+ if (!element || !(element instanceof Node)) {
4659
4687
  return;
4660
4688
  }
4661
- obs.observe(this.element, { attributes: true });
4689
+ obs.observe(element, { attributes: true });
4662
4690
  });
4663
4691
  this.initPlugins();
4664
4692
  this.render.init();
4665
4693
  }
4666
4694
  initBackground() {
4667
- const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
4695
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.domElement;
4668
4696
  if (!element) {
4669
4697
  return;
4670
4698
  }
@@ -4689,21 +4717,30 @@
4689
4717
  }
4690
4718
  }
4691
4719
  loadCanvas(canvas) {
4692
- if (this._generated && this.element) {
4693
- this.element.remove();
4720
+ if (this._generated && this.domElement) {
4721
+ this.domElement.remove();
4722
+ }
4723
+ const container = this._container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4724
+ this.domElement = domCanvas;
4725
+ this._generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4726
+ this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
4727
+ const domElement = this.domElement;
4728
+ if (domElement) {
4729
+ domElement.ariaHidden = "true";
4730
+ this._originalStyle = cloneStyle(domElement.style);
4731
+ }
4732
+ const standardSize = this._standardSize, renderCanvas = this.renderCanvas;
4733
+ if (domElement) {
4734
+ standardSize.height = domElement.offsetHeight;
4735
+ standardSize.width = domElement.offsetWidth;
4736
+ }
4737
+ else {
4738
+ standardSize.height = renderCanvas.height;
4739
+ standardSize.width = renderCanvas.width;
4694
4740
  }
4695
- const container = this._container;
4696
- this._generated =
4697
- generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
4698
- this.element = canvas;
4699
- this.element.ariaHidden = "true";
4700
- this._originalStyle = cloneStyle(this.element.style);
4701
- const standardSize = this._standardSize;
4702
- standardSize.height = canvas.offsetHeight;
4703
- standardSize.width = canvas.offsetWidth;
4704
4741
  const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
4705
- canvas.height = retinaSize.height = standardSize.height * pxRatio;
4706
- canvas.width = retinaSize.width = standardSize.width * pxRatio;
4742
+ renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4743
+ renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4707
4744
  const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4708
4745
  this.render.setContextSettings({
4709
4746
  alpha: true,
@@ -4711,42 +4748,48 @@
4711
4748
  desynchronized: true,
4712
4749
  willReadFrequently: false,
4713
4750
  });
4714
- this.render.setContext(this.element.getContext("2d", this.render.settings));
4751
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4715
4752
  this._safeMutationObserver(obs => {
4716
4753
  obs.disconnect();
4717
4754
  });
4718
4755
  container.retina.init();
4719
4756
  this.initBackground();
4720
4757
  this._safeMutationObserver(obs => {
4721
- if (!this.element || !(this.element instanceof Node)) {
4758
+ const element = this.domElement;
4759
+ if (!element || !(element instanceof Node)) {
4722
4760
  return;
4723
4761
  }
4724
- obs.observe(this.element, { attributes: true });
4762
+ obs.observe(element, { attributes: true });
4725
4763
  });
4726
4764
  }
4727
4765
  resize() {
4728
- if (!this.element) {
4766
+ const element = this.domElement;
4767
+ if (!element) {
4768
+ return false;
4769
+ }
4770
+ const container = this._container, renderCanvas = this.renderCanvas;
4771
+ if (renderCanvas === undefined) {
4729
4772
  return false;
4730
4773
  }
4731
- const container = this._container, currentSize = container.canvas._standardSize, newSize = {
4732
- width: this.element.offsetWidth,
4733
- height: this.element.offsetHeight,
4774
+ const currentSize = container.canvas._standardSize, newSize = {
4775
+ width: element.offsetWidth,
4776
+ height: element.offsetHeight,
4734
4777
  }, pxRatio = container.retina.pixelRatio, retinaSize = {
4735
4778
  width: newSize.width * pxRatio,
4736
4779
  height: newSize.height * pxRatio,
4737
4780
  };
4738
4781
  if (newSize.height === currentSize.height &&
4739
4782
  newSize.width === currentSize.width &&
4740
- retinaSize.height === this.element.height &&
4741
- retinaSize.width === this.element.width) {
4783
+ retinaSize.height === renderCanvas.height &&
4784
+ retinaSize.width === renderCanvas.width) {
4742
4785
  return false;
4743
4786
  }
4744
4787
  const oldSize = { ...currentSize };
4745
4788
  currentSize.height = newSize.height;
4746
4789
  currentSize.width = newSize.width;
4747
4790
  const canvasSize = this.size;
4748
- this.element.width = canvasSize.width = retinaSize.width;
4749
- this.element.height = canvasSize.height = retinaSize.height;
4791
+ renderCanvas.width = canvasSize.width = retinaSize.width;
4792
+ renderCanvas.height = canvasSize.height = retinaSize.height;
4750
4793
  if (this._container.started) {
4751
4794
  container.particles.setResizeFactor({
4752
4795
  width: currentSize.width / oldSize.width,
@@ -4756,7 +4799,7 @@
4756
4799
  return true;
4757
4800
  }
4758
4801
  setPointerEvents(type) {
4759
- const element = this.element;
4802
+ const element = this.domElement;
4760
4803
  if (!element) {
4761
4804
  return;
4762
4805
  }
@@ -4775,7 +4818,7 @@
4775
4818
  this.render.stop();
4776
4819
  }
4777
4820
  async windowResize() {
4778
- if (!this.element || !this.resize()) {
4821
+ if (!this.domElement || !this.resize()) {
4779
4822
  return;
4780
4823
  }
4781
4824
  const container = this._container, needsRefresh = container.updateActualOptions();
@@ -4791,7 +4834,7 @@
4791
4834
  }
4792
4835
  };
4793
4836
  _initStyle = () => {
4794
- const element = this.element, options = this._container.actualOptions;
4837
+ const element = this.domElement, options = this._container.actualOptions;
4795
4838
  if (!element) {
4796
4839
  return;
4797
4840
  }
@@ -4813,7 +4856,7 @@
4813
4856
  }
4814
4857
  };
4815
4858
  _repairStyle = () => {
4816
- const element = this.element;
4859
+ const element = this.domElement;
4817
4860
  if (!element) {
4818
4861
  return;
4819
4862
  }
@@ -4833,7 +4876,7 @@
4833
4876
  });
4834
4877
  };
4835
4878
  _resetOriginalStyle = () => {
4836
- const element = this.element, originalStyle = this._originalStyle;
4879
+ const element = this.domElement, originalStyle = this._originalStyle;
4837
4880
  if (!element || !originalStyle) {
4838
4881
  return;
4839
4882
  }
@@ -4846,7 +4889,7 @@
4846
4889
  callback(this._mutationObserver);
4847
4890
  };
4848
4891
  _setFullScreenStyle = () => {
4849
- const element = this.element;
4892
+ const element = this.domElement;
4850
4893
  if (!element) {
4851
4894
  return;
4852
4895
  }
@@ -4920,7 +4963,7 @@
4920
4963
  manageListener(globalThis, resizeEvent, handlers.resize, add);
4921
4964
  return;
4922
4965
  }
4923
- const canvasEl = container.canvas.element;
4966
+ const canvasEl = container.canvas.domElement;
4924
4967
  if (this._resizeObserver && !add) {
4925
4968
  if (canvasEl) {
4926
4969
  this._resizeObserver.unobserve(canvasEl);
@@ -5175,8 +5218,6 @@
5175
5218
  this._initPosition(position);
5176
5219
  this.initialVelocity = this._calculateVelocity();
5177
5220
  this.velocity = this.initialVelocity.copy();
5178
- const particles = container.particles;
5179
- particles.setLastZIndex(this.position.z);
5180
5221
  this.zIndexFactor = this.position.z / container.zLayers;
5181
5222
  this.sides = 24;
5182
5223
  let effectDrawer, shapeDrawer;
@@ -5326,7 +5367,7 @@
5326
5367
  return color;
5327
5368
  };
5328
5369
  _initPosition = position => {
5329
- const container = this._container, zIndexValue = getRangeValue(this.options.zIndex.value), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5370
+ const container = this._container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5330
5371
  if (!initialPosition) {
5331
5372
  throw new Error("a valid position cannot be found for particle");
5332
5373
  }
@@ -5460,10 +5501,8 @@
5460
5501
  _container;
5461
5502
  _groupLimits;
5462
5503
  _limit;
5463
- _maxZIndex;
5464
- _minZIndex;
5465
- _needsSort;
5466
5504
  _nextId;
5505
+ _particleBuckets;
5467
5506
  _particleResetPlugins;
5468
5507
  _particleUpdatePlugins;
5469
5508
  _pluginManager;
@@ -5472,19 +5511,17 @@
5472
5511
  _postUpdatePlugins;
5473
5512
  _resizeFactor;
5474
5513
  _updatePlugins;
5475
- _zArray;
5514
+ _zBuckets;
5476
5515
  constructor(pluginManager, container) {
5477
5516
  this._pluginManager = pluginManager;
5478
5517
  this._container = container;
5479
5518
  this._nextId = 0;
5480
5519
  this._array = [];
5481
- this._zArray = [];
5482
5520
  this._pool = [];
5483
5521
  this._limit = 0;
5484
5522
  this._groupLimits = new Map();
5485
- this._needsSort = false;
5486
- this._minZIndex = 0;
5487
- this._maxZIndex = 0;
5523
+ this._particleBuckets = new Map();
5524
+ this._zBuckets = this._createBuckets(this._container.zLayers);
5488
5525
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5489
5526
  this.checkParticlePositionPlugins = [];
5490
5527
  this._particleResetPlugins = [];
@@ -5526,7 +5563,7 @@
5526
5563
  return;
5527
5564
  }
5528
5565
  this._array.push(particle);
5529
- this._zArray.push(particle);
5566
+ this._insertParticleIntoBucket(particle);
5530
5567
  this._nextId++;
5531
5568
  this._container.dispatchEvent(EventType.particleAdded, {
5532
5569
  particle,
@@ -5540,12 +5577,14 @@
5540
5577
  }
5541
5578
  clear() {
5542
5579
  this._array = [];
5543
- this._zArray = [];
5580
+ this._particleBuckets.clear();
5581
+ this._resetBuckets(this._container.zLayers);
5544
5582
  }
5545
5583
  destroy() {
5546
5584
  this._array = [];
5547
5585
  this._pool.length = 0;
5548
- this._zArray = [];
5586
+ this._particleBuckets.clear();
5587
+ this._zBuckets = [];
5549
5588
  this.checkParticlePositionPlugins = [];
5550
5589
  this._particleResetPlugins = [];
5551
5590
  this._particleUpdatePlugins = [];
@@ -5554,8 +5593,14 @@
5554
5593
  this._updatePlugins = [];
5555
5594
  }
5556
5595
  drawParticles(delta) {
5557
- for (const particle of this._zArray) {
5558
- particle.draw(delta);
5596
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
5597
+ const bucket = this._zBuckets[i];
5598
+ if (!bucket) {
5599
+ continue;
5600
+ }
5601
+ for (const particle of bucket) {
5602
+ particle.draw(delta);
5603
+ }
5559
5604
  }
5560
5605
  }
5561
5606
  filter(condition) {
@@ -5569,15 +5614,14 @@
5569
5614
  }
5570
5615
  async init() {
5571
5616
  const container = this._container, options = container.actualOptions;
5572
- this._minZIndex = 0;
5573
- this._maxZIndex = 0;
5574
- this._needsSort = false;
5575
5617
  this.checkParticlePositionPlugins = [];
5576
5618
  this._updatePlugins = [];
5577
5619
  this._particleUpdatePlugins = [];
5578
5620
  this._postUpdatePlugins = [];
5579
5621
  this._particleResetPlugins = [];
5580
5622
  this._postParticleUpdatePlugins = [];
5623
+ this._particleBuckets.clear();
5624
+ this._resetBuckets(container.zLayers);
5581
5625
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5582
5626
  for (const plugin of container.plugins) {
5583
5627
  if (plugin.redrawInit) {
@@ -5678,79 +5722,25 @@
5678
5722
  }
5679
5723
  this._applyDensity(options.particles, pluginsCount);
5680
5724
  }
5681
- setLastZIndex(zIndex) {
5682
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
5683
- }
5684
5725
  setResizeFactor(factor) {
5685
5726
  this._resizeFactor = factor;
5686
5727
  }
5687
5728
  update(delta) {
5688
- const particlesToDelete = new Set();
5689
5729
  this.grid.clear();
5690
5730
  for (const plugin of this._updatePlugins) {
5691
5731
  plugin.update?.(delta);
5692
5732
  }
5693
- const resizeFactor = this._resizeFactor;
5694
- for (const particle of this._array) {
5695
- if (resizeFactor && !particle.ignoresResizeRatio) {
5696
- particle.position.x *= resizeFactor.width;
5697
- particle.position.y *= resizeFactor.height;
5698
- particle.initialPosition.x *= resizeFactor.width;
5699
- particle.initialPosition.y *= resizeFactor.height;
5700
- }
5701
- particle.ignoresResizeRatio = false;
5702
- for (const plugin of this._particleResetPlugins) {
5703
- plugin.particleReset?.(particle);
5704
- }
5705
- for (const plugin of this._particleUpdatePlugins) {
5706
- if (particle.destroyed) {
5707
- break;
5708
- }
5709
- plugin.particleUpdate?.(particle, delta);
5710
- }
5711
- if (particle.destroyed) {
5712
- particlesToDelete.add(particle);
5713
- continue;
5714
- }
5715
- this.grid.insert(particle);
5716
- }
5733
+ const particlesToDelete = this._updateParticlesPhase1(delta);
5717
5734
  for (const plugin of this._postUpdatePlugins) {
5718
5735
  plugin.postUpdate?.(delta);
5719
5736
  }
5720
- for (const particle of this._array) {
5721
- if (particle.destroyed) {
5722
- particlesToDelete.add(particle);
5723
- continue;
5724
- }
5725
- for (const updater of this._container.particleUpdaters) {
5726
- updater.update(particle, delta);
5727
- }
5728
- if (!particle.destroyed && !particle.spawning) {
5729
- for (const plugin of this._postParticleUpdatePlugins) {
5730
- plugin.postParticleUpdate?.(particle, delta);
5731
- }
5732
- }
5733
- else if (particle.destroyed) {
5734
- particlesToDelete.add(particle);
5735
- }
5736
- }
5737
+ this._updateParticlesPhase2(delta, particlesToDelete);
5737
5738
  if (particlesToDelete.size) {
5738
5739
  for (const particle of particlesToDelete) {
5739
5740
  this.remove(particle);
5740
5741
  }
5741
5742
  }
5742
5743
  delete this._resizeFactor;
5743
- if (this._needsSort) {
5744
- const zArray = this._zArray;
5745
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
5746
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
5747
- if (!firstItem || !lastItem) {
5748
- return;
5749
- }
5750
- this._maxZIndex = firstItem.position.z;
5751
- this._minZIndex = lastItem.position.z;
5752
- this._needsSort = false;
5753
- }
5754
5744
  }
5755
5745
  _addToPool = (...particles) => {
5756
5746
  this._pool.push(...particles);
@@ -5780,13 +5770,52 @@
5780
5770
  this.removeQuantity(particlesCount - particlesNumber, group);
5781
5771
  }
5782
5772
  };
5773
+ _createBuckets = (zLayers) => {
5774
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5775
+ return Array.from({ length: bucketCount }, () => []);
5776
+ };
5777
+ _getBucketIndex = (zIndex) => {
5778
+ const maxBucketIndex = this._zBuckets.length - one;
5779
+ if (maxBucketIndex <= minIndex) {
5780
+ return minIndex;
5781
+ }
5782
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
5783
+ };
5784
+ _getParticleInsertIndex = (bucket, particleId) => {
5785
+ let start = minIndex, end = bucket.length;
5786
+ while (start < end) {
5787
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
5788
+ if (!middleParticle) {
5789
+ end = middle;
5790
+ continue;
5791
+ }
5792
+ if (middleParticle.id < particleId) {
5793
+ start = middle + one;
5794
+ }
5795
+ else {
5796
+ end = middle;
5797
+ }
5798
+ }
5799
+ return start;
5800
+ };
5783
5801
  _initDensityFactor = densityOptions => {
5784
5802
  const container = this._container;
5785
- if (!container.canvas.element || !densityOptions.enable) {
5803
+ if (!densityOptions.enable) {
5804
+ return defaultDensityFactor;
5805
+ }
5806
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
5807
+ if (!canvasSize.width || !canvasSize.height) {
5786
5808
  return defaultDensityFactor;
5787
5809
  }
5788
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
5789
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
5810
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5811
+ };
5812
+ _insertParticleIntoBucket = (particle) => {
5813
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5814
+ if (!bucket) {
5815
+ return;
5816
+ }
5817
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
5818
+ this._particleBuckets.set(particle.id, bucketIndex);
5790
5819
  };
5791
5820
  _removeParticle = (index, group, override) => {
5792
5821
  const particle = this._array[index];
@@ -5796,9 +5825,8 @@
5796
5825
  if (particle.group !== group) {
5797
5826
  return false;
5798
5827
  }
5799
- const zIdx = this._zArray.indexOf(particle);
5800
5828
  this._array.splice(index, deleteCount);
5801
- this._zArray.splice(zIdx, deleteCount);
5829
+ this._removeParticleFromBucket(particle);
5802
5830
  particle.destroy(override);
5803
5831
  this._container.dispatchEvent(EventType.particleRemoved, {
5804
5832
  particle,
@@ -5806,6 +5834,98 @@
5806
5834
  this._addToPool(particle);
5807
5835
  return true;
5808
5836
  };
5837
+ _removeParticleFromBucket = (particle) => {
5838
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5839
+ if (!bucket) {
5840
+ this._particleBuckets.delete(particle.id);
5841
+ return;
5842
+ }
5843
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
5844
+ if (bucket[particleIndex]?.id !== particle.id) {
5845
+ this._particleBuckets.delete(particle.id);
5846
+ return;
5847
+ }
5848
+ bucket.splice(particleIndex, deleteCount);
5849
+ this._particleBuckets.delete(particle.id);
5850
+ };
5851
+ _resetBuckets = (zLayers) => {
5852
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5853
+ if (this._zBuckets.length !== bucketCount) {
5854
+ this._zBuckets = this._createBuckets(bucketCount);
5855
+ return;
5856
+ }
5857
+ for (const bucket of this._zBuckets) {
5858
+ bucket.length = minIndex;
5859
+ }
5860
+ };
5861
+ _updateParticleBucket = (particle) => {
5862
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
5863
+ if (currentBucketIndex === undefined) {
5864
+ this._insertParticleIntoBucket(particle);
5865
+ return;
5866
+ }
5867
+ if (currentBucketIndex === newBucketIndex) {
5868
+ return;
5869
+ }
5870
+ const currentBucket = this._zBuckets[currentBucketIndex];
5871
+ if (currentBucket) {
5872
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
5873
+ if (currentBucket[particleIndex]?.id === particle.id) {
5874
+ currentBucket.splice(particleIndex, deleteCount);
5875
+ }
5876
+ }
5877
+ const newBucket = this._zBuckets[newBucketIndex];
5878
+ if (!newBucket) {
5879
+ this._particleBuckets.set(particle.id, newBucketIndex);
5880
+ return;
5881
+ }
5882
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
5883
+ this._particleBuckets.set(particle.id, newBucketIndex);
5884
+ };
5885
+ _updateParticlesPhase1 = (delta) => {
5886
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
5887
+ for (const particle of this._array) {
5888
+ if (resizeFactor && !particle.ignoresResizeRatio) {
5889
+ particle.position.x *= resizeFactor.width;
5890
+ particle.position.y *= resizeFactor.height;
5891
+ particle.initialPosition.x *= resizeFactor.width;
5892
+ particle.initialPosition.y *= resizeFactor.height;
5893
+ }
5894
+ particle.ignoresResizeRatio = false;
5895
+ for (const plugin of this._particleResetPlugins) {
5896
+ plugin.particleReset?.(particle);
5897
+ }
5898
+ for (const plugin of this._particleUpdatePlugins) {
5899
+ if (particle.destroyed) {
5900
+ break;
5901
+ }
5902
+ plugin.particleUpdate?.(particle, delta);
5903
+ }
5904
+ if (particle.destroyed) {
5905
+ particlesToDelete.add(particle);
5906
+ continue;
5907
+ }
5908
+ this.grid.insert(particle);
5909
+ }
5910
+ return particlesToDelete;
5911
+ };
5912
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
5913
+ for (const particle of this._array) {
5914
+ if (particle.destroyed) {
5915
+ particlesToDelete.add(particle);
5916
+ continue;
5917
+ }
5918
+ for (const updater of this._container.particleUpdaters) {
5919
+ updater.update(particle, delta);
5920
+ }
5921
+ if (!particle.spawning) {
5922
+ for (const plugin of this._postParticleUpdatePlugins) {
5923
+ plugin.postParticleUpdate?.(particle, delta);
5924
+ }
5925
+ }
5926
+ this._updateParticleBucket(particle);
5927
+ }
5928
+ };
5809
5929
  }
5810
5930
 
5811
5931
  class Retina {
@@ -5821,9 +5941,8 @@
5821
5941
  const container = this.container, options = container.actualOptions;
5822
5942
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
5823
5943
  this.reduceFactor = defaultReduceFactor;
5824
- const ratio = this.pixelRatio, canvas = container.canvas;
5825
- if (canvas.element) {
5826
- const element = canvas.element;
5944
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
5945
+ if (element) {
5827
5946
  canvas.size.width = element.offsetWidth * ratio;
5828
5947
  canvas.size.height = element.offsetHeight * ratio;
5829
5948
  }
@@ -6512,7 +6631,7 @@
6512
6631
  return;
6513
6632
  }
6514
6633
  const html = interactivityEl, canvas = container.canvas;
6515
- canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
6634
+ canvas.setPointerEvents(html === canvas.domElement ? "initial" : "none");
6516
6635
  if (add && !(options.interactivity?.events.onHover.enable || options.interactivity?.events.onClick.enable)) {
6517
6636
  return;
6518
6637
  }
@@ -6539,7 +6658,7 @@
6539
6658
  manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
6540
6659
  };
6541
6660
  _manageListeners = add => {
6542
- const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.element;
6661
+ const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.domElement;
6543
6662
  if (detectType === InteractivityDetect.window) {
6544
6663
  interactionManager.interactivityData.element = safeDocument();
6545
6664
  }
@@ -6586,7 +6705,7 @@
6586
6705
  mouse.clicking = false;
6587
6706
  };
6588
6707
  _mouseTouchMove = e => {
6589
- const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.element;
6708
+ const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.domElement;
6590
6709
  if (!interactivity.element) {
6591
6710
  return;
6592
6711
  }
@@ -6747,7 +6866,7 @@
6747
6866
  if (!lastTouch) {
6748
6867
  return;
6749
6868
  }
6750
- const element = container.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
6869
+ const element = container.canvas.domElement, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
6751
6870
  x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
6752
6871
  y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
6753
6872
  };