@tsparticles/preset-triangles 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);
@@ -4560,6 +4566,25 @@
4560
4566
  };
4561
4567
  }
4562
4568
 
4569
+ const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
4570
+ const transferredCanvas = transferredCanvases.get(canvas);
4571
+ if (transferredCanvas) {
4572
+ return transferredCanvas;
4573
+ }
4574
+ if (typeof canvas.transferControlToOffscreen !== "function") {
4575
+ throw new TypeError("OffscreenCanvas is required but not supported by this browser");
4576
+ }
4577
+ try {
4578
+ const offscreenCanvas = canvas.transferControlToOffscreen();
4579
+ transferredCanvases.set(canvas, offscreenCanvas);
4580
+ return offscreenCanvas;
4581
+ }
4582
+ catch {
4583
+ throw new TypeError("OffscreenCanvas transfer failed");
4584
+ }
4585
+ }, isHtmlCanvasElement = (canvas) => {
4586
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
4587
+ };
4563
4588
  function setStyle(canvas, style, important = false) {
4564
4589
  if (!style) {
4565
4590
  return;
@@ -4590,8 +4615,9 @@
4590
4615
  }
4591
4616
  }
4592
4617
  class CanvasManager {
4593
- element;
4618
+ domElement;
4594
4619
  render;
4620
+ renderCanvas;
4595
4621
  size;
4596
4622
  zoom = defaultZoom;
4597
4623
  _container;
@@ -4626,9 +4652,10 @@
4626
4652
  destroy() {
4627
4653
  this.stop();
4628
4654
  if (this._generated) {
4629
- const element = this.element;
4655
+ const element = this.domElement;
4630
4656
  element?.remove();
4631
- this.element = undefined;
4657
+ this.domElement = undefined;
4658
+ this.renderCanvas = undefined;
4632
4659
  }
4633
4660
  else {
4634
4661
  this._resetOriginalStyle();
@@ -4661,16 +4688,17 @@
4661
4688
  this._initStyle();
4662
4689
  this.initBackground();
4663
4690
  this._safeMutationObserver(obs => {
4664
- if (!this.element || !(this.element instanceof Node)) {
4691
+ const element = this.domElement;
4692
+ if (!element || !(element instanceof Node)) {
4665
4693
  return;
4666
4694
  }
4667
- obs.observe(this.element, { attributes: true });
4695
+ obs.observe(element, { attributes: true });
4668
4696
  });
4669
4697
  this.initPlugins();
4670
4698
  this.render.init();
4671
4699
  }
4672
4700
  initBackground() {
4673
- const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
4701
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.domElement;
4674
4702
  if (!element) {
4675
4703
  return;
4676
4704
  }
@@ -4695,21 +4723,30 @@
4695
4723
  }
4696
4724
  }
4697
4725
  loadCanvas(canvas) {
4698
- if (this._generated && this.element) {
4699
- this.element.remove();
4726
+ if (this._generated && this.domElement) {
4727
+ this.domElement.remove();
4728
+ }
4729
+ const container = this._container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4730
+ this.domElement = domCanvas;
4731
+ this._generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4732
+ this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
4733
+ const domElement = this.domElement;
4734
+ if (domElement) {
4735
+ domElement.ariaHidden = "true";
4736
+ this._originalStyle = cloneStyle(domElement.style);
4737
+ }
4738
+ const standardSize = this._standardSize, renderCanvas = this.renderCanvas;
4739
+ if (domElement) {
4740
+ standardSize.height = domElement.offsetHeight;
4741
+ standardSize.width = domElement.offsetWidth;
4742
+ }
4743
+ else {
4744
+ standardSize.height = renderCanvas.height;
4745
+ standardSize.width = renderCanvas.width;
4700
4746
  }
4701
- const container = this._container;
4702
- this._generated =
4703
- generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
4704
- this.element = canvas;
4705
- this.element.ariaHidden = "true";
4706
- this._originalStyle = cloneStyle(this.element.style);
4707
- const standardSize = this._standardSize;
4708
- standardSize.height = canvas.offsetHeight;
4709
- standardSize.width = canvas.offsetWidth;
4710
4747
  const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
4711
- canvas.height = retinaSize.height = standardSize.height * pxRatio;
4712
- canvas.width = retinaSize.width = standardSize.width * pxRatio;
4748
+ renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4749
+ renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4713
4750
  const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4714
4751
  this.render.setContextSettings({
4715
4752
  alpha: true,
@@ -4717,42 +4754,48 @@
4717
4754
  desynchronized: true,
4718
4755
  willReadFrequently: false,
4719
4756
  });
4720
- this.render.setContext(this.element.getContext("2d", this.render.settings));
4757
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4721
4758
  this._safeMutationObserver(obs => {
4722
4759
  obs.disconnect();
4723
4760
  });
4724
4761
  container.retina.init();
4725
4762
  this.initBackground();
4726
4763
  this._safeMutationObserver(obs => {
4727
- if (!this.element || !(this.element instanceof Node)) {
4764
+ const element = this.domElement;
4765
+ if (!element || !(element instanceof Node)) {
4728
4766
  return;
4729
4767
  }
4730
- obs.observe(this.element, { attributes: true });
4768
+ obs.observe(element, { attributes: true });
4731
4769
  });
4732
4770
  }
4733
4771
  resize() {
4734
- if (!this.element) {
4772
+ const element = this.domElement;
4773
+ if (!element) {
4774
+ return false;
4775
+ }
4776
+ const container = this._container, renderCanvas = this.renderCanvas;
4777
+ if (renderCanvas === undefined) {
4735
4778
  return false;
4736
4779
  }
4737
- const container = this._container, currentSize = container.canvas._standardSize, newSize = {
4738
- width: this.element.offsetWidth,
4739
- height: this.element.offsetHeight,
4780
+ const currentSize = container.canvas._standardSize, newSize = {
4781
+ width: element.offsetWidth,
4782
+ height: element.offsetHeight,
4740
4783
  }, pxRatio = container.retina.pixelRatio, retinaSize = {
4741
4784
  width: newSize.width * pxRatio,
4742
4785
  height: newSize.height * pxRatio,
4743
4786
  };
4744
4787
  if (newSize.height === currentSize.height &&
4745
4788
  newSize.width === currentSize.width &&
4746
- retinaSize.height === this.element.height &&
4747
- retinaSize.width === this.element.width) {
4789
+ retinaSize.height === renderCanvas.height &&
4790
+ retinaSize.width === renderCanvas.width) {
4748
4791
  return false;
4749
4792
  }
4750
4793
  const oldSize = { ...currentSize };
4751
4794
  currentSize.height = newSize.height;
4752
4795
  currentSize.width = newSize.width;
4753
4796
  const canvasSize = this.size;
4754
- this.element.width = canvasSize.width = retinaSize.width;
4755
- this.element.height = canvasSize.height = retinaSize.height;
4797
+ renderCanvas.width = canvasSize.width = retinaSize.width;
4798
+ renderCanvas.height = canvasSize.height = retinaSize.height;
4756
4799
  if (this._container.started) {
4757
4800
  container.particles.setResizeFactor({
4758
4801
  width: currentSize.width / oldSize.width,
@@ -4762,7 +4805,7 @@
4762
4805
  return true;
4763
4806
  }
4764
4807
  setPointerEvents(type) {
4765
- const element = this.element;
4808
+ const element = this.domElement;
4766
4809
  if (!element) {
4767
4810
  return;
4768
4811
  }
@@ -4781,7 +4824,7 @@
4781
4824
  this.render.stop();
4782
4825
  }
4783
4826
  async windowResize() {
4784
- if (!this.element || !this.resize()) {
4827
+ if (!this.domElement || !this.resize()) {
4785
4828
  return;
4786
4829
  }
4787
4830
  const container = this._container, needsRefresh = container.updateActualOptions();
@@ -4797,7 +4840,7 @@
4797
4840
  }
4798
4841
  };
4799
4842
  _initStyle = () => {
4800
- const element = this.element, options = this._container.actualOptions;
4843
+ const element = this.domElement, options = this._container.actualOptions;
4801
4844
  if (!element) {
4802
4845
  return;
4803
4846
  }
@@ -4819,7 +4862,7 @@
4819
4862
  }
4820
4863
  };
4821
4864
  _repairStyle = () => {
4822
- const element = this.element;
4865
+ const element = this.domElement;
4823
4866
  if (!element) {
4824
4867
  return;
4825
4868
  }
@@ -4839,7 +4882,7 @@
4839
4882
  });
4840
4883
  };
4841
4884
  _resetOriginalStyle = () => {
4842
- const element = this.element, originalStyle = this._originalStyle;
4885
+ const element = this.domElement, originalStyle = this._originalStyle;
4843
4886
  if (!element || !originalStyle) {
4844
4887
  return;
4845
4888
  }
@@ -4852,7 +4895,7 @@
4852
4895
  callback(this._mutationObserver);
4853
4896
  };
4854
4897
  _setFullScreenStyle = () => {
4855
- const element = this.element;
4898
+ const element = this.domElement;
4856
4899
  if (!element) {
4857
4900
  return;
4858
4901
  }
@@ -4926,7 +4969,7 @@
4926
4969
  manageListener(globalThis, resizeEvent, handlers.resize, add);
4927
4970
  return;
4928
4971
  }
4929
- const canvasEl = container.canvas.element;
4972
+ const canvasEl = container.canvas.domElement;
4930
4973
  if (this._resizeObserver && !add) {
4931
4974
  if (canvasEl) {
4932
4975
  this._resizeObserver.unobserve(canvasEl);
@@ -5181,8 +5224,6 @@
5181
5224
  this._initPosition(position);
5182
5225
  this.initialVelocity = this._calculateVelocity();
5183
5226
  this.velocity = this.initialVelocity.copy();
5184
- const particles = container.particles;
5185
- particles.setLastZIndex(this.position.z);
5186
5227
  this.zIndexFactor = this.position.z / container.zLayers;
5187
5228
  this.sides = 24;
5188
5229
  let effectDrawer, shapeDrawer;
@@ -5332,7 +5373,7 @@
5332
5373
  return color;
5333
5374
  };
5334
5375
  _initPosition = position => {
5335
- const container = this._container, zIndexValue = getRangeValue(this.options.zIndex.value), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5376
+ const container = this._container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5336
5377
  if (!initialPosition) {
5337
5378
  throw new Error("a valid position cannot be found for particle");
5338
5379
  }
@@ -5466,10 +5507,8 @@
5466
5507
  _container;
5467
5508
  _groupLimits;
5468
5509
  _limit;
5469
- _maxZIndex;
5470
- _minZIndex;
5471
- _needsSort;
5472
5510
  _nextId;
5511
+ _particleBuckets;
5473
5512
  _particleResetPlugins;
5474
5513
  _particleUpdatePlugins;
5475
5514
  _pluginManager;
@@ -5478,19 +5517,17 @@
5478
5517
  _postUpdatePlugins;
5479
5518
  _resizeFactor;
5480
5519
  _updatePlugins;
5481
- _zArray;
5520
+ _zBuckets;
5482
5521
  constructor(pluginManager, container) {
5483
5522
  this._pluginManager = pluginManager;
5484
5523
  this._container = container;
5485
5524
  this._nextId = 0;
5486
5525
  this._array = [];
5487
- this._zArray = [];
5488
5526
  this._pool = [];
5489
5527
  this._limit = 0;
5490
5528
  this._groupLimits = new Map();
5491
- this._needsSort = false;
5492
- this._minZIndex = 0;
5493
- this._maxZIndex = 0;
5529
+ this._particleBuckets = new Map();
5530
+ this._zBuckets = this._createBuckets(this._container.zLayers);
5494
5531
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5495
5532
  this.checkParticlePositionPlugins = [];
5496
5533
  this._particleResetPlugins = [];
@@ -5532,7 +5569,7 @@
5532
5569
  return;
5533
5570
  }
5534
5571
  this._array.push(particle);
5535
- this._zArray.push(particle);
5572
+ this._insertParticleIntoBucket(particle);
5536
5573
  this._nextId++;
5537
5574
  this._container.dispatchEvent(EventType.particleAdded, {
5538
5575
  particle,
@@ -5546,12 +5583,14 @@
5546
5583
  }
5547
5584
  clear() {
5548
5585
  this._array = [];
5549
- this._zArray = [];
5586
+ this._particleBuckets.clear();
5587
+ this._resetBuckets(this._container.zLayers);
5550
5588
  }
5551
5589
  destroy() {
5552
5590
  this._array = [];
5553
5591
  this._pool.length = 0;
5554
- this._zArray = [];
5592
+ this._particleBuckets.clear();
5593
+ this._zBuckets = [];
5555
5594
  this.checkParticlePositionPlugins = [];
5556
5595
  this._particleResetPlugins = [];
5557
5596
  this._particleUpdatePlugins = [];
@@ -5560,8 +5599,14 @@
5560
5599
  this._updatePlugins = [];
5561
5600
  }
5562
5601
  drawParticles(delta) {
5563
- for (const particle of this._zArray) {
5564
- particle.draw(delta);
5602
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
5603
+ const bucket = this._zBuckets[i];
5604
+ if (!bucket) {
5605
+ continue;
5606
+ }
5607
+ for (const particle of bucket) {
5608
+ particle.draw(delta);
5609
+ }
5565
5610
  }
5566
5611
  }
5567
5612
  filter(condition) {
@@ -5575,15 +5620,14 @@
5575
5620
  }
5576
5621
  async init() {
5577
5622
  const container = this._container, options = container.actualOptions;
5578
- this._minZIndex = 0;
5579
- this._maxZIndex = 0;
5580
- this._needsSort = false;
5581
5623
  this.checkParticlePositionPlugins = [];
5582
5624
  this._updatePlugins = [];
5583
5625
  this._particleUpdatePlugins = [];
5584
5626
  this._postUpdatePlugins = [];
5585
5627
  this._particleResetPlugins = [];
5586
5628
  this._postParticleUpdatePlugins = [];
5629
+ this._particleBuckets.clear();
5630
+ this._resetBuckets(container.zLayers);
5587
5631
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5588
5632
  for (const plugin of container.plugins) {
5589
5633
  if (plugin.redrawInit) {
@@ -5684,79 +5728,25 @@
5684
5728
  }
5685
5729
  this._applyDensity(options.particles, pluginsCount);
5686
5730
  }
5687
- setLastZIndex(zIndex) {
5688
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
5689
- }
5690
5731
  setResizeFactor(factor) {
5691
5732
  this._resizeFactor = factor;
5692
5733
  }
5693
5734
  update(delta) {
5694
- const particlesToDelete = new Set();
5695
5735
  this.grid.clear();
5696
5736
  for (const plugin of this._updatePlugins) {
5697
5737
  plugin.update?.(delta);
5698
5738
  }
5699
- const resizeFactor = this._resizeFactor;
5700
- for (const particle of this._array) {
5701
- if (resizeFactor && !particle.ignoresResizeRatio) {
5702
- particle.position.x *= resizeFactor.width;
5703
- particle.position.y *= resizeFactor.height;
5704
- particle.initialPosition.x *= resizeFactor.width;
5705
- particle.initialPosition.y *= resizeFactor.height;
5706
- }
5707
- particle.ignoresResizeRatio = false;
5708
- for (const plugin of this._particleResetPlugins) {
5709
- plugin.particleReset?.(particle);
5710
- }
5711
- for (const plugin of this._particleUpdatePlugins) {
5712
- if (particle.destroyed) {
5713
- break;
5714
- }
5715
- plugin.particleUpdate?.(particle, delta);
5716
- }
5717
- if (particle.destroyed) {
5718
- particlesToDelete.add(particle);
5719
- continue;
5720
- }
5721
- this.grid.insert(particle);
5722
- }
5739
+ const particlesToDelete = this._updateParticlesPhase1(delta);
5723
5740
  for (const plugin of this._postUpdatePlugins) {
5724
5741
  plugin.postUpdate?.(delta);
5725
5742
  }
5726
- for (const particle of this._array) {
5727
- if (particle.destroyed) {
5728
- particlesToDelete.add(particle);
5729
- continue;
5730
- }
5731
- for (const updater of this._container.particleUpdaters) {
5732
- updater.update(particle, delta);
5733
- }
5734
- if (!particle.destroyed && !particle.spawning) {
5735
- for (const plugin of this._postParticleUpdatePlugins) {
5736
- plugin.postParticleUpdate?.(particle, delta);
5737
- }
5738
- }
5739
- else if (particle.destroyed) {
5740
- particlesToDelete.add(particle);
5741
- }
5742
- }
5743
+ this._updateParticlesPhase2(delta, particlesToDelete);
5743
5744
  if (particlesToDelete.size) {
5744
5745
  for (const particle of particlesToDelete) {
5745
5746
  this.remove(particle);
5746
5747
  }
5747
5748
  }
5748
5749
  delete this._resizeFactor;
5749
- if (this._needsSort) {
5750
- const zArray = this._zArray;
5751
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
5752
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
5753
- if (!firstItem || !lastItem) {
5754
- return;
5755
- }
5756
- this._maxZIndex = firstItem.position.z;
5757
- this._minZIndex = lastItem.position.z;
5758
- this._needsSort = false;
5759
- }
5760
5750
  }
5761
5751
  _addToPool = (...particles) => {
5762
5752
  this._pool.push(...particles);
@@ -5786,13 +5776,52 @@
5786
5776
  this.removeQuantity(particlesCount - particlesNumber, group);
5787
5777
  }
5788
5778
  };
5779
+ _createBuckets = (zLayers) => {
5780
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5781
+ return Array.from({ length: bucketCount }, () => []);
5782
+ };
5783
+ _getBucketIndex = (zIndex) => {
5784
+ const maxBucketIndex = this._zBuckets.length - one;
5785
+ if (maxBucketIndex <= minIndex) {
5786
+ return minIndex;
5787
+ }
5788
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
5789
+ };
5790
+ _getParticleInsertIndex = (bucket, particleId) => {
5791
+ let start = minIndex, end = bucket.length;
5792
+ while (start < end) {
5793
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
5794
+ if (!middleParticle) {
5795
+ end = middle;
5796
+ continue;
5797
+ }
5798
+ if (middleParticle.id < particleId) {
5799
+ start = middle + one;
5800
+ }
5801
+ else {
5802
+ end = middle;
5803
+ }
5804
+ }
5805
+ return start;
5806
+ };
5789
5807
  _initDensityFactor = densityOptions => {
5790
5808
  const container = this._container;
5791
- if (!container.canvas.element || !densityOptions.enable) {
5809
+ if (!densityOptions.enable) {
5810
+ return defaultDensityFactor;
5811
+ }
5812
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
5813
+ if (!canvasSize.width || !canvasSize.height) {
5792
5814
  return defaultDensityFactor;
5793
5815
  }
5794
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
5795
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
5816
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5817
+ };
5818
+ _insertParticleIntoBucket = (particle) => {
5819
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5820
+ if (!bucket) {
5821
+ return;
5822
+ }
5823
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
5824
+ this._particleBuckets.set(particle.id, bucketIndex);
5796
5825
  };
5797
5826
  _removeParticle = (index, group, override) => {
5798
5827
  const particle = this._array[index];
@@ -5802,9 +5831,8 @@
5802
5831
  if (particle.group !== group) {
5803
5832
  return false;
5804
5833
  }
5805
- const zIdx = this._zArray.indexOf(particle);
5806
5834
  this._array.splice(index, deleteCount);
5807
- this._zArray.splice(zIdx, deleteCount);
5835
+ this._removeParticleFromBucket(particle);
5808
5836
  particle.destroy(override);
5809
5837
  this._container.dispatchEvent(EventType.particleRemoved, {
5810
5838
  particle,
@@ -5812,6 +5840,98 @@
5812
5840
  this._addToPool(particle);
5813
5841
  return true;
5814
5842
  };
5843
+ _removeParticleFromBucket = (particle) => {
5844
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5845
+ if (!bucket) {
5846
+ this._particleBuckets.delete(particle.id);
5847
+ return;
5848
+ }
5849
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
5850
+ if (bucket[particleIndex]?.id !== particle.id) {
5851
+ this._particleBuckets.delete(particle.id);
5852
+ return;
5853
+ }
5854
+ bucket.splice(particleIndex, deleteCount);
5855
+ this._particleBuckets.delete(particle.id);
5856
+ };
5857
+ _resetBuckets = (zLayers) => {
5858
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5859
+ if (this._zBuckets.length !== bucketCount) {
5860
+ this._zBuckets = this._createBuckets(bucketCount);
5861
+ return;
5862
+ }
5863
+ for (const bucket of this._zBuckets) {
5864
+ bucket.length = minIndex;
5865
+ }
5866
+ };
5867
+ _updateParticleBucket = (particle) => {
5868
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
5869
+ if (currentBucketIndex === undefined) {
5870
+ this._insertParticleIntoBucket(particle);
5871
+ return;
5872
+ }
5873
+ if (currentBucketIndex === newBucketIndex) {
5874
+ return;
5875
+ }
5876
+ const currentBucket = this._zBuckets[currentBucketIndex];
5877
+ if (currentBucket) {
5878
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
5879
+ if (currentBucket[particleIndex]?.id === particle.id) {
5880
+ currentBucket.splice(particleIndex, deleteCount);
5881
+ }
5882
+ }
5883
+ const newBucket = this._zBuckets[newBucketIndex];
5884
+ if (!newBucket) {
5885
+ this._particleBuckets.set(particle.id, newBucketIndex);
5886
+ return;
5887
+ }
5888
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
5889
+ this._particleBuckets.set(particle.id, newBucketIndex);
5890
+ };
5891
+ _updateParticlesPhase1 = (delta) => {
5892
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
5893
+ for (const particle of this._array) {
5894
+ if (resizeFactor && !particle.ignoresResizeRatio) {
5895
+ particle.position.x *= resizeFactor.width;
5896
+ particle.position.y *= resizeFactor.height;
5897
+ particle.initialPosition.x *= resizeFactor.width;
5898
+ particle.initialPosition.y *= resizeFactor.height;
5899
+ }
5900
+ particle.ignoresResizeRatio = false;
5901
+ for (const plugin of this._particleResetPlugins) {
5902
+ plugin.particleReset?.(particle);
5903
+ }
5904
+ for (const plugin of this._particleUpdatePlugins) {
5905
+ if (particle.destroyed) {
5906
+ break;
5907
+ }
5908
+ plugin.particleUpdate?.(particle, delta);
5909
+ }
5910
+ if (particle.destroyed) {
5911
+ particlesToDelete.add(particle);
5912
+ continue;
5913
+ }
5914
+ this.grid.insert(particle);
5915
+ }
5916
+ return particlesToDelete;
5917
+ };
5918
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
5919
+ for (const particle of this._array) {
5920
+ if (particle.destroyed) {
5921
+ particlesToDelete.add(particle);
5922
+ continue;
5923
+ }
5924
+ for (const updater of this._container.particleUpdaters) {
5925
+ updater.update(particle, delta);
5926
+ }
5927
+ if (!particle.spawning) {
5928
+ for (const plugin of this._postParticleUpdatePlugins) {
5929
+ plugin.postParticleUpdate?.(particle, delta);
5930
+ }
5931
+ }
5932
+ this._updateParticleBucket(particle);
5933
+ }
5934
+ };
5815
5935
  }
5816
5936
 
5817
5937
  class Retina {
@@ -5827,9 +5947,8 @@
5827
5947
  const container = this.container, options = container.actualOptions;
5828
5948
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
5829
5949
  this.reduceFactor = defaultReduceFactor;
5830
- const ratio = this.pixelRatio, canvas = container.canvas;
5831
- if (canvas.element) {
5832
- const element = canvas.element;
5950
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
5951
+ if (element) {
5833
5952
  canvas.size.width = element.offsetWidth * ratio;
5834
5953
  canvas.size.height = element.offsetHeight * ratio;
5835
5954
  }
@@ -6518,7 +6637,7 @@
6518
6637
  return;
6519
6638
  }
6520
6639
  const html = interactivityEl, canvas = container.canvas;
6521
- canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
6640
+ canvas.setPointerEvents(html === canvas.domElement ? "initial" : "none");
6522
6641
  if (add && !(options.interactivity?.events.onHover.enable || options.interactivity?.events.onClick.enable)) {
6523
6642
  return;
6524
6643
  }
@@ -6545,7 +6664,7 @@
6545
6664
  manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
6546
6665
  };
6547
6666
  _manageListeners = add => {
6548
- const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.element;
6667
+ const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.domElement;
6549
6668
  if (detectType === InteractivityDetect.window) {
6550
6669
  interactionManager.interactivityData.element = safeDocument();
6551
6670
  }
@@ -6592,7 +6711,7 @@
6592
6711
  mouse.clicking = false;
6593
6712
  };
6594
6713
  _mouseTouchMove = e => {
6595
- const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.element;
6714
+ const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.domElement;
6596
6715
  if (!interactivity.element) {
6597
6716
  return;
6598
6717
  }
@@ -6753,7 +6872,7 @@
6753
6872
  if (!lastTouch) {
6754
6873
  return;
6755
6874
  }
6756
- const element = container.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
6875
+ const element = container.canvas.domElement, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
6757
6876
  x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
6758
6877
  y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
6759
6878
  };