@tsparticles/particles 4.0.0-beta.16 → 4.0.0-beta.17

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.0.0-beta.16 */
2
+ /* tsParticles v4.0.0-beta.17 */
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) :
@@ -1081,7 +1081,7 @@
1081
1081
  }
1082
1082
  }
1083
1083
  else {
1084
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases[canvasFirstIndex];
1084
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
1085
1085
  if (foundCanvas) {
1086
1086
  canvasEl = foundCanvas;
1087
1087
  canvasEl.dataset[generatedAttribute] = generatedFalse;
@@ -1118,7 +1118,7 @@
1118
1118
  return this._domArray;
1119
1119
  }
1120
1120
  get version() {
1121
- return "4.0.0-beta.16";
1121
+ return "4.0.0-beta.17";
1122
1122
  }
1123
1123
  addEventListener(type, listener) {
1124
1124
  this._eventDispatcher.addEventListener(type, listener);
@@ -1149,7 +1149,11 @@
1149
1149
  }
1150
1150
  async load(params) {
1151
1151
  await this.init();
1152
- 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({
1152
+ let domSourceElement;
1153
+ if (typeof HTMLElement !== "undefined" && params.element instanceof HTMLElement) {
1154
+ domSourceElement = params.element;
1155
+ }
1156
+ 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({
1153
1157
  dispatchCallback: (eventType, args) => {
1154
1158
  this.dispatchEvent(eventType, args);
1155
1159
  },
@@ -1176,8 +1180,10 @@
1176
1180
  else {
1177
1181
  items.push(newItem);
1178
1182
  }
1179
- const domContainer = getDomContainer(id, params.element), canvasEl = getCanvasFromContainer(domContainer);
1180
- newItem.canvas.loadCanvas(canvasEl);
1183
+ const sourceCanvas = typeof OffscreenCanvas !== "undefined" && params.element instanceof OffscreenCanvas
1184
+ ? params.element
1185
+ : getCanvasFromContainer(getDomContainer(id, domSourceElement));
1186
+ newItem.canvas.loadCanvas(sourceCanvas);
1181
1187
  await newItem.start();
1182
1188
  return newItem;
1183
1189
  }
@@ -3093,7 +3099,7 @@
3093
3099
  }
3094
3100
 
3095
3101
  async function loadCircleShape(engine) {
3096
- engine.checkVersion("4.0.0-beta.16");
3102
+ engine.checkVersion("4.0.0-beta.17");
3097
3103
  await engine.pluginManager.register(e => {
3098
3104
  e.pluginManager.addShape(["circle"], () => {
3099
3105
  return Promise.resolve(new CircleDrawer());
@@ -3141,7 +3147,7 @@
3141
3147
  }
3142
3148
 
3143
3149
  async function loadHexColorPlugin(engine) {
3144
- engine.checkVersion("4.0.0-beta.16");
3150
+ engine.checkVersion("4.0.0-beta.17");
3145
3151
  await engine.pluginManager.register(e => {
3146
3152
  e.pluginManager.addColorManager("hex", new HexColorManager());
3147
3153
  });
@@ -3194,7 +3200,7 @@
3194
3200
  }
3195
3201
 
3196
3202
  async function loadHslColorPlugin(engine) {
3197
- engine.checkVersion("4.0.0-beta.16");
3203
+ engine.checkVersion("4.0.0-beta.17");
3198
3204
  await engine.pluginManager.register(e => {
3199
3205
  e.pluginManager.addColorManager("hsl", new HslColorManager());
3200
3206
  });
@@ -3218,7 +3224,7 @@
3218
3224
  }
3219
3225
 
3220
3226
  async function loadMovePlugin(engine) {
3221
- engine.checkVersion("4.0.0-beta.16");
3227
+ engine.checkVersion("4.0.0-beta.17");
3222
3228
  await engine.pluginManager.register(e => {
3223
3229
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
3224
3230
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -3279,7 +3285,7 @@
3279
3285
  }
3280
3286
 
3281
3287
  async function loadOpacityUpdater(engine) {
3282
- engine.checkVersion("4.0.0-beta.16");
3288
+ engine.checkVersion("4.0.0-beta.17");
3283
3289
  await engine.pluginManager.register(e => {
3284
3290
  e.pluginManager.addParticleUpdater("opacity", container => {
3285
3291
  return Promise.resolve(new OpacityUpdater(container));
@@ -3631,7 +3637,7 @@
3631
3637
  }
3632
3638
 
3633
3639
  async function loadOutModesUpdater(engine) {
3634
- engine.checkVersion("4.0.0-beta.16");
3640
+ engine.checkVersion("4.0.0-beta.17");
3635
3641
  await engine.pluginManager.register(e => {
3636
3642
  e.pluginManager.addParticleUpdater("outModes", container => {
3637
3643
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3702,7 +3708,7 @@
3702
3708
  }
3703
3709
 
3704
3710
  async function loadPaintUpdater(engine) {
3705
- engine.checkVersion("4.0.0-beta.16");
3711
+ engine.checkVersion("4.0.0-beta.17");
3706
3712
  await engine.pluginManager.register(e => {
3707
3713
  e.pluginManager.addParticleUpdater("paint", container => {
3708
3714
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3757,7 +3763,7 @@
3757
3763
  }
3758
3764
 
3759
3765
  async function loadRgbColorPlugin(engine) {
3760
- engine.checkVersion("4.0.0-beta.16");
3766
+ engine.checkVersion("4.0.0-beta.17");
3761
3767
  await engine.pluginManager.register(e => {
3762
3768
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3763
3769
  });
@@ -3800,7 +3806,7 @@
3800
3806
  }
3801
3807
 
3802
3808
  async function loadSizeUpdater(engine) {
3803
- engine.checkVersion("4.0.0-beta.16");
3809
+ engine.checkVersion("4.0.0-beta.17");
3804
3810
  await engine.pluginManager.register(e => {
3805
3811
  e.pluginManager.addParticleUpdater("size", container => {
3806
3812
  return Promise.resolve(new SizeUpdater(container));
@@ -3809,7 +3815,7 @@
3809
3815
  }
3810
3816
 
3811
3817
  async function loadBasic(engine) {
3812
- engine.checkVersion("4.0.0-beta.16");
3818
+ engine.checkVersion("4.0.0-beta.17");
3813
3819
  await engine.pluginManager.register(async (e) => {
3814
3820
  await Promise.all([
3815
3821
  loadHexColorPlugin(e),
@@ -4046,7 +4052,7 @@
4046
4052
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
4047
4053
 
4048
4054
  async function loadInteractivityPlugin(engine) {
4049
- engine.checkVersion("4.0.0-beta.16");
4055
+ engine.checkVersion("4.0.0-beta.17");
4050
4056
  await engine.pluginManager.register(e => {
4051
4057
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
4052
4058
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -4310,7 +4316,7 @@
4310
4316
  }
4311
4317
 
4312
4318
  async function loadParticlesCollisionsInteraction(engine) {
4313
- engine.checkVersion("4.0.0-beta.16");
4319
+ engine.checkVersion("4.0.0-beta.17");
4314
4320
  await engine.pluginManager.register((e) => {
4315
4321
  ensureInteractivityPluginLoaded(e);
4316
4322
  e.pluginManager.addPlugin(new OverlapPlugin());
@@ -4613,7 +4619,7 @@
4613
4619
  }
4614
4620
 
4615
4621
  async function loadParticlesLinksInteraction(engine) {
4616
- engine.checkVersion("4.0.0-beta.16");
4622
+ engine.checkVersion("4.0.0-beta.17");
4617
4623
  await engine.pluginManager.register((e) => {
4618
4624
  const pluginManager = e.pluginManager;
4619
4625
  ensureInteractivityPluginLoaded(e);
@@ -4626,7 +4632,7 @@
4626
4632
 
4627
4633
  let initPromise = null;
4628
4634
  async function doInitPlugins(engine) {
4629
- engine.checkVersion("4.0.0-beta.16");
4635
+ engine.checkVersion("4.0.0-beta.17");
4630
4636
  await engine.pluginManager.register(async (e) => {
4631
4637
  const loadParticlesInteractivity = async (e) => {
4632
4638
  await loadInteractivityPlugin(e);
@@ -4669,7 +4675,7 @@
4669
4675
  particles.init = async () => {
4670
4676
  await initPlugins(tsParticles);
4671
4677
  };
4672
- particles.version = "4.0.0-beta.16";
4678
+ particles.version = "4.0.0-beta.17";
4673
4679
  globalThis.particles = particles;
4674
4680
 
4675
4681
  const globalObject = globalThis;
@@ -4977,6 +4983,25 @@
4977
4983
  };
4978
4984
  }
4979
4985
 
4986
+ const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
4987
+ const transferredCanvas = transferredCanvases.get(canvas);
4988
+ if (transferredCanvas) {
4989
+ return transferredCanvas;
4990
+ }
4991
+ if (typeof canvas.transferControlToOffscreen !== "function") {
4992
+ throw new TypeError("OffscreenCanvas is required but not supported by this browser");
4993
+ }
4994
+ try {
4995
+ const offscreenCanvas = canvas.transferControlToOffscreen();
4996
+ transferredCanvases.set(canvas, offscreenCanvas);
4997
+ return offscreenCanvas;
4998
+ }
4999
+ catch {
5000
+ throw new TypeError("OffscreenCanvas transfer failed");
5001
+ }
5002
+ }, isHtmlCanvasElement = (canvas) => {
5003
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
5004
+ };
4980
5005
  function setStyle(canvas, style, important = false) {
4981
5006
  if (!style) {
4982
5007
  return;
@@ -5007,8 +5032,9 @@
5007
5032
  }
5008
5033
  }
5009
5034
  class CanvasManager {
5010
- element;
5035
+ domElement;
5011
5036
  render;
5037
+ renderCanvas;
5012
5038
  size;
5013
5039
  zoom = defaultZoom;
5014
5040
  _container;
@@ -5043,9 +5069,10 @@
5043
5069
  destroy() {
5044
5070
  this.stop();
5045
5071
  if (this._generated) {
5046
- const element = this.element;
5072
+ const element = this.domElement;
5047
5073
  element?.remove();
5048
- this.element = undefined;
5074
+ this.domElement = undefined;
5075
+ this.renderCanvas = undefined;
5049
5076
  }
5050
5077
  else {
5051
5078
  this._resetOriginalStyle();
@@ -5078,16 +5105,17 @@
5078
5105
  this._initStyle();
5079
5106
  this.initBackground();
5080
5107
  this._safeMutationObserver(obs => {
5081
- if (!this.element || !(this.element instanceof Node)) {
5108
+ const element = this.domElement;
5109
+ if (!element || !(element instanceof Node)) {
5082
5110
  return;
5083
5111
  }
5084
- obs.observe(this.element, { attributes: true });
5112
+ obs.observe(element, { attributes: true });
5085
5113
  });
5086
5114
  this.initPlugins();
5087
5115
  this.render.init();
5088
5116
  }
5089
5117
  initBackground() {
5090
- const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
5118
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.domElement;
5091
5119
  if (!element) {
5092
5120
  return;
5093
5121
  }
@@ -5112,21 +5140,30 @@
5112
5140
  }
5113
5141
  }
5114
5142
  loadCanvas(canvas) {
5115
- if (this._generated && this.element) {
5116
- this.element.remove();
5143
+ if (this._generated && this.domElement) {
5144
+ this.domElement.remove();
5145
+ }
5146
+ const container = this._container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
5147
+ this.domElement = domCanvas;
5148
+ this._generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
5149
+ this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
5150
+ const domElement = this.domElement;
5151
+ if (domElement) {
5152
+ domElement.ariaHidden = "true";
5153
+ this._originalStyle = cloneStyle(domElement.style);
5154
+ }
5155
+ const standardSize = this._standardSize, renderCanvas = this.renderCanvas;
5156
+ if (domElement) {
5157
+ standardSize.height = domElement.offsetHeight;
5158
+ standardSize.width = domElement.offsetWidth;
5159
+ }
5160
+ else {
5161
+ standardSize.height = renderCanvas.height;
5162
+ standardSize.width = renderCanvas.width;
5117
5163
  }
5118
- const container = this._container;
5119
- this._generated =
5120
- generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
5121
- this.element = canvas;
5122
- this.element.ariaHidden = "true";
5123
- this._originalStyle = cloneStyle(this.element.style);
5124
- const standardSize = this._standardSize;
5125
- standardSize.height = canvas.offsetHeight;
5126
- standardSize.width = canvas.offsetWidth;
5127
5164
  const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
5128
- canvas.height = retinaSize.height = standardSize.height * pxRatio;
5129
- canvas.width = retinaSize.width = standardSize.width * pxRatio;
5165
+ renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
5166
+ renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
5130
5167
  const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
5131
5168
  this.render.setContextSettings({
5132
5169
  alpha: true,
@@ -5134,42 +5171,48 @@
5134
5171
  desynchronized: true,
5135
5172
  willReadFrequently: false,
5136
5173
  });
5137
- this.render.setContext(this.element.getContext("2d", this.render.settings));
5174
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
5138
5175
  this._safeMutationObserver(obs => {
5139
5176
  obs.disconnect();
5140
5177
  });
5141
5178
  container.retina.init();
5142
5179
  this.initBackground();
5143
5180
  this._safeMutationObserver(obs => {
5144
- if (!this.element || !(this.element instanceof Node)) {
5181
+ const element = this.domElement;
5182
+ if (!element || !(element instanceof Node)) {
5145
5183
  return;
5146
5184
  }
5147
- obs.observe(this.element, { attributes: true });
5185
+ obs.observe(element, { attributes: true });
5148
5186
  });
5149
5187
  }
5150
5188
  resize() {
5151
- if (!this.element) {
5189
+ const element = this.domElement;
5190
+ if (!element) {
5191
+ return false;
5192
+ }
5193
+ const container = this._container, renderCanvas = this.renderCanvas;
5194
+ if (renderCanvas === undefined) {
5152
5195
  return false;
5153
5196
  }
5154
- const container = this._container, currentSize = container.canvas._standardSize, newSize = {
5155
- width: this.element.offsetWidth,
5156
- height: this.element.offsetHeight,
5197
+ const currentSize = container.canvas._standardSize, newSize = {
5198
+ width: element.offsetWidth,
5199
+ height: element.offsetHeight,
5157
5200
  }, pxRatio = container.retina.pixelRatio, retinaSize = {
5158
5201
  width: newSize.width * pxRatio,
5159
5202
  height: newSize.height * pxRatio,
5160
5203
  };
5161
5204
  if (newSize.height === currentSize.height &&
5162
5205
  newSize.width === currentSize.width &&
5163
- retinaSize.height === this.element.height &&
5164
- retinaSize.width === this.element.width) {
5206
+ retinaSize.height === renderCanvas.height &&
5207
+ retinaSize.width === renderCanvas.width) {
5165
5208
  return false;
5166
5209
  }
5167
5210
  const oldSize = { ...currentSize };
5168
5211
  currentSize.height = newSize.height;
5169
5212
  currentSize.width = newSize.width;
5170
5213
  const canvasSize = this.size;
5171
- this.element.width = canvasSize.width = retinaSize.width;
5172
- this.element.height = canvasSize.height = retinaSize.height;
5214
+ renderCanvas.width = canvasSize.width = retinaSize.width;
5215
+ renderCanvas.height = canvasSize.height = retinaSize.height;
5173
5216
  if (this._container.started) {
5174
5217
  container.particles.setResizeFactor({
5175
5218
  width: currentSize.width / oldSize.width,
@@ -5179,7 +5222,7 @@
5179
5222
  return true;
5180
5223
  }
5181
5224
  setPointerEvents(type) {
5182
- const element = this.element;
5225
+ const element = this.domElement;
5183
5226
  if (!element) {
5184
5227
  return;
5185
5228
  }
@@ -5198,7 +5241,7 @@
5198
5241
  this.render.stop();
5199
5242
  }
5200
5243
  async windowResize() {
5201
- if (!this.element || !this.resize()) {
5244
+ if (!this.domElement || !this.resize()) {
5202
5245
  return;
5203
5246
  }
5204
5247
  const container = this._container, needsRefresh = container.updateActualOptions();
@@ -5214,7 +5257,7 @@
5214
5257
  }
5215
5258
  };
5216
5259
  _initStyle = () => {
5217
- const element = this.element, options = this._container.actualOptions;
5260
+ const element = this.domElement, options = this._container.actualOptions;
5218
5261
  if (!element) {
5219
5262
  return;
5220
5263
  }
@@ -5236,7 +5279,7 @@
5236
5279
  }
5237
5280
  };
5238
5281
  _repairStyle = () => {
5239
- const element = this.element;
5282
+ const element = this.domElement;
5240
5283
  if (!element) {
5241
5284
  return;
5242
5285
  }
@@ -5256,7 +5299,7 @@
5256
5299
  });
5257
5300
  };
5258
5301
  _resetOriginalStyle = () => {
5259
- const element = this.element, originalStyle = this._originalStyle;
5302
+ const element = this.domElement, originalStyle = this._originalStyle;
5260
5303
  if (!element || !originalStyle) {
5261
5304
  return;
5262
5305
  }
@@ -5269,7 +5312,7 @@
5269
5312
  callback(this._mutationObserver);
5270
5313
  };
5271
5314
  _setFullScreenStyle = () => {
5272
- const element = this.element;
5315
+ const element = this.domElement;
5273
5316
  if (!element) {
5274
5317
  return;
5275
5318
  }
@@ -5343,7 +5386,7 @@
5343
5386
  manageListener(globalThis, resizeEvent, handlers.resize, add);
5344
5387
  return;
5345
5388
  }
5346
- const canvasEl = container.canvas.element;
5389
+ const canvasEl = container.canvas.domElement;
5347
5390
  if (this._resizeObserver && !add) {
5348
5391
  if (canvasEl) {
5349
5392
  this._resizeObserver.unobserve(canvasEl);
@@ -5598,8 +5641,6 @@
5598
5641
  this._initPosition(position);
5599
5642
  this.initialVelocity = this._calculateVelocity();
5600
5643
  this.velocity = this.initialVelocity.copy();
5601
- const particles = container.particles;
5602
- particles.setLastZIndex(this.position.z);
5603
5644
  this.zIndexFactor = this.position.z / container.zLayers;
5604
5645
  this.sides = 24;
5605
5646
  let effectDrawer, shapeDrawer;
@@ -5749,7 +5790,7 @@
5749
5790
  return color;
5750
5791
  };
5751
5792
  _initPosition = position => {
5752
- const container = this._container, zIndexValue = getRangeValue(this.options.zIndex.value), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5793
+ const container = this._container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5753
5794
  if (!initialPosition) {
5754
5795
  throw new Error("a valid position cannot be found for particle");
5755
5796
  }
@@ -5883,10 +5924,8 @@
5883
5924
  _container;
5884
5925
  _groupLimits;
5885
5926
  _limit;
5886
- _maxZIndex;
5887
- _minZIndex;
5888
- _needsSort;
5889
5927
  _nextId;
5928
+ _particleBuckets;
5890
5929
  _particleResetPlugins;
5891
5930
  _particleUpdatePlugins;
5892
5931
  _pluginManager;
@@ -5895,19 +5934,17 @@
5895
5934
  _postUpdatePlugins;
5896
5935
  _resizeFactor;
5897
5936
  _updatePlugins;
5898
- _zArray;
5937
+ _zBuckets;
5899
5938
  constructor(pluginManager, container) {
5900
5939
  this._pluginManager = pluginManager;
5901
5940
  this._container = container;
5902
5941
  this._nextId = 0;
5903
5942
  this._array = [];
5904
- this._zArray = [];
5905
5943
  this._pool = [];
5906
5944
  this._limit = 0;
5907
5945
  this._groupLimits = new Map();
5908
- this._needsSort = false;
5909
- this._minZIndex = 0;
5910
- this._maxZIndex = 0;
5946
+ this._particleBuckets = new Map();
5947
+ this._zBuckets = this._createBuckets(this._container.zLayers);
5911
5948
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5912
5949
  this.checkParticlePositionPlugins = [];
5913
5950
  this._particleResetPlugins = [];
@@ -5949,7 +5986,7 @@
5949
5986
  return;
5950
5987
  }
5951
5988
  this._array.push(particle);
5952
- this._zArray.push(particle);
5989
+ this._insertParticleIntoBucket(particle);
5953
5990
  this._nextId++;
5954
5991
  this._container.dispatchEvent(exports.EventType.particleAdded, {
5955
5992
  particle,
@@ -5963,12 +6000,14 @@
5963
6000
  }
5964
6001
  clear() {
5965
6002
  this._array = [];
5966
- this._zArray = [];
6003
+ this._particleBuckets.clear();
6004
+ this._resetBuckets(this._container.zLayers);
5967
6005
  }
5968
6006
  destroy() {
5969
6007
  this._array = [];
5970
6008
  this._pool.length = 0;
5971
- this._zArray = [];
6009
+ this._particleBuckets.clear();
6010
+ this._zBuckets = [];
5972
6011
  this.checkParticlePositionPlugins = [];
5973
6012
  this._particleResetPlugins = [];
5974
6013
  this._particleUpdatePlugins = [];
@@ -5977,8 +6016,14 @@
5977
6016
  this._updatePlugins = [];
5978
6017
  }
5979
6018
  drawParticles(delta) {
5980
- for (const particle of this._zArray) {
5981
- particle.draw(delta);
6019
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
6020
+ const bucket = this._zBuckets[i];
6021
+ if (!bucket) {
6022
+ continue;
6023
+ }
6024
+ for (const particle of bucket) {
6025
+ particle.draw(delta);
6026
+ }
5982
6027
  }
5983
6028
  }
5984
6029
  filter(condition) {
@@ -5992,15 +6037,14 @@
5992
6037
  }
5993
6038
  async init() {
5994
6039
  const container = this._container, options = container.actualOptions;
5995
- this._minZIndex = 0;
5996
- this._maxZIndex = 0;
5997
- this._needsSort = false;
5998
6040
  this.checkParticlePositionPlugins = [];
5999
6041
  this._updatePlugins = [];
6000
6042
  this._particleUpdatePlugins = [];
6001
6043
  this._postUpdatePlugins = [];
6002
6044
  this._particleResetPlugins = [];
6003
6045
  this._postParticleUpdatePlugins = [];
6046
+ this._particleBuckets.clear();
6047
+ this._resetBuckets(container.zLayers);
6004
6048
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
6005
6049
  for (const plugin of container.plugins) {
6006
6050
  if (plugin.redrawInit) {
@@ -6101,79 +6145,25 @@
6101
6145
  }
6102
6146
  this._applyDensity(options.particles, pluginsCount);
6103
6147
  }
6104
- setLastZIndex(zIndex) {
6105
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
6106
- }
6107
6148
  setResizeFactor(factor) {
6108
6149
  this._resizeFactor = factor;
6109
6150
  }
6110
6151
  update(delta) {
6111
- const particlesToDelete = new Set();
6112
6152
  this.grid.clear();
6113
6153
  for (const plugin of this._updatePlugins) {
6114
6154
  plugin.update?.(delta);
6115
6155
  }
6116
- const resizeFactor = this._resizeFactor;
6117
- for (const particle of this._array) {
6118
- if (resizeFactor && !particle.ignoresResizeRatio) {
6119
- particle.position.x *= resizeFactor.width;
6120
- particle.position.y *= resizeFactor.height;
6121
- particle.initialPosition.x *= resizeFactor.width;
6122
- particle.initialPosition.y *= resizeFactor.height;
6123
- }
6124
- particle.ignoresResizeRatio = false;
6125
- for (const plugin of this._particleResetPlugins) {
6126
- plugin.particleReset?.(particle);
6127
- }
6128
- for (const plugin of this._particleUpdatePlugins) {
6129
- if (particle.destroyed) {
6130
- break;
6131
- }
6132
- plugin.particleUpdate?.(particle, delta);
6133
- }
6134
- if (particle.destroyed) {
6135
- particlesToDelete.add(particle);
6136
- continue;
6137
- }
6138
- this.grid.insert(particle);
6139
- }
6156
+ const particlesToDelete = this._updateParticlesPhase1(delta);
6140
6157
  for (const plugin of this._postUpdatePlugins) {
6141
6158
  plugin.postUpdate?.(delta);
6142
6159
  }
6143
- for (const particle of this._array) {
6144
- if (particle.destroyed) {
6145
- particlesToDelete.add(particle);
6146
- continue;
6147
- }
6148
- for (const updater of this._container.particleUpdaters) {
6149
- updater.update(particle, delta);
6150
- }
6151
- if (!particle.destroyed && !particle.spawning) {
6152
- for (const plugin of this._postParticleUpdatePlugins) {
6153
- plugin.postParticleUpdate?.(particle, delta);
6154
- }
6155
- }
6156
- else if (particle.destroyed) {
6157
- particlesToDelete.add(particle);
6158
- }
6159
- }
6160
+ this._updateParticlesPhase2(delta, particlesToDelete);
6160
6161
  if (particlesToDelete.size) {
6161
6162
  for (const particle of particlesToDelete) {
6162
6163
  this.remove(particle);
6163
6164
  }
6164
6165
  }
6165
6166
  delete this._resizeFactor;
6166
- if (this._needsSort) {
6167
- const zArray = this._zArray;
6168
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
6169
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
6170
- if (!firstItem || !lastItem) {
6171
- return;
6172
- }
6173
- this._maxZIndex = firstItem.position.z;
6174
- this._minZIndex = lastItem.position.z;
6175
- this._needsSort = false;
6176
- }
6177
6167
  }
6178
6168
  _addToPool = (...particles) => {
6179
6169
  this._pool.push(...particles);
@@ -6203,13 +6193,52 @@
6203
6193
  this.removeQuantity(particlesCount - particlesNumber, group);
6204
6194
  }
6205
6195
  };
6196
+ _createBuckets = (zLayers) => {
6197
+ const bucketCount = Math.max(Math.floor(zLayers), one);
6198
+ return Array.from({ length: bucketCount }, () => []);
6199
+ };
6200
+ _getBucketIndex = (zIndex) => {
6201
+ const maxBucketIndex = this._zBuckets.length - one;
6202
+ if (maxBucketIndex <= minIndex) {
6203
+ return minIndex;
6204
+ }
6205
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
6206
+ };
6207
+ _getParticleInsertIndex = (bucket, particleId) => {
6208
+ let start = minIndex, end = bucket.length;
6209
+ while (start < end) {
6210
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
6211
+ if (!middleParticle) {
6212
+ end = middle;
6213
+ continue;
6214
+ }
6215
+ if (middleParticle.id < particleId) {
6216
+ start = middle + one;
6217
+ }
6218
+ else {
6219
+ end = middle;
6220
+ }
6221
+ }
6222
+ return start;
6223
+ };
6206
6224
  _initDensityFactor = densityOptions => {
6207
6225
  const container = this._container;
6208
- if (!container.canvas.element || !densityOptions.enable) {
6226
+ if (!densityOptions.enable) {
6227
+ return defaultDensityFactor;
6228
+ }
6229
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
6230
+ if (!canvasSize.width || !canvasSize.height) {
6209
6231
  return defaultDensityFactor;
6210
6232
  }
6211
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
6212
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
6233
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
6234
+ };
6235
+ _insertParticleIntoBucket = (particle) => {
6236
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
6237
+ if (!bucket) {
6238
+ return;
6239
+ }
6240
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
6241
+ this._particleBuckets.set(particle.id, bucketIndex);
6213
6242
  };
6214
6243
  _removeParticle = (index, group, override) => {
6215
6244
  const particle = this._array[index];
@@ -6219,9 +6248,8 @@
6219
6248
  if (particle.group !== group) {
6220
6249
  return false;
6221
6250
  }
6222
- const zIdx = this._zArray.indexOf(particle);
6223
6251
  this._array.splice(index, deleteCount);
6224
- this._zArray.splice(zIdx, deleteCount);
6252
+ this._removeParticleFromBucket(particle);
6225
6253
  particle.destroy(override);
6226
6254
  this._container.dispatchEvent(exports.EventType.particleRemoved, {
6227
6255
  particle,
@@ -6229,6 +6257,98 @@
6229
6257
  this._addToPool(particle);
6230
6258
  return true;
6231
6259
  };
6260
+ _removeParticleFromBucket = (particle) => {
6261
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
6262
+ if (!bucket) {
6263
+ this._particleBuckets.delete(particle.id);
6264
+ return;
6265
+ }
6266
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
6267
+ if (bucket[particleIndex]?.id !== particle.id) {
6268
+ this._particleBuckets.delete(particle.id);
6269
+ return;
6270
+ }
6271
+ bucket.splice(particleIndex, deleteCount);
6272
+ this._particleBuckets.delete(particle.id);
6273
+ };
6274
+ _resetBuckets = (zLayers) => {
6275
+ const bucketCount = Math.max(Math.floor(zLayers), one);
6276
+ if (this._zBuckets.length !== bucketCount) {
6277
+ this._zBuckets = this._createBuckets(bucketCount);
6278
+ return;
6279
+ }
6280
+ for (const bucket of this._zBuckets) {
6281
+ bucket.length = minIndex;
6282
+ }
6283
+ };
6284
+ _updateParticleBucket = (particle) => {
6285
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
6286
+ if (currentBucketIndex === undefined) {
6287
+ this._insertParticleIntoBucket(particle);
6288
+ return;
6289
+ }
6290
+ if (currentBucketIndex === newBucketIndex) {
6291
+ return;
6292
+ }
6293
+ const currentBucket = this._zBuckets[currentBucketIndex];
6294
+ if (currentBucket) {
6295
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
6296
+ if (currentBucket[particleIndex]?.id === particle.id) {
6297
+ currentBucket.splice(particleIndex, deleteCount);
6298
+ }
6299
+ }
6300
+ const newBucket = this._zBuckets[newBucketIndex];
6301
+ if (!newBucket) {
6302
+ this._particleBuckets.set(particle.id, newBucketIndex);
6303
+ return;
6304
+ }
6305
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
6306
+ this._particleBuckets.set(particle.id, newBucketIndex);
6307
+ };
6308
+ _updateParticlesPhase1 = (delta) => {
6309
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
6310
+ for (const particle of this._array) {
6311
+ if (resizeFactor && !particle.ignoresResizeRatio) {
6312
+ particle.position.x *= resizeFactor.width;
6313
+ particle.position.y *= resizeFactor.height;
6314
+ particle.initialPosition.x *= resizeFactor.width;
6315
+ particle.initialPosition.y *= resizeFactor.height;
6316
+ }
6317
+ particle.ignoresResizeRatio = false;
6318
+ for (const plugin of this._particleResetPlugins) {
6319
+ plugin.particleReset?.(particle);
6320
+ }
6321
+ for (const plugin of this._particleUpdatePlugins) {
6322
+ if (particle.destroyed) {
6323
+ break;
6324
+ }
6325
+ plugin.particleUpdate?.(particle, delta);
6326
+ }
6327
+ if (particle.destroyed) {
6328
+ particlesToDelete.add(particle);
6329
+ continue;
6330
+ }
6331
+ this.grid.insert(particle);
6332
+ }
6333
+ return particlesToDelete;
6334
+ };
6335
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
6336
+ for (const particle of this._array) {
6337
+ if (particle.destroyed) {
6338
+ particlesToDelete.add(particle);
6339
+ continue;
6340
+ }
6341
+ for (const updater of this._container.particleUpdaters) {
6342
+ updater.update(particle, delta);
6343
+ }
6344
+ if (!particle.spawning) {
6345
+ for (const plugin of this._postParticleUpdatePlugins) {
6346
+ plugin.postParticleUpdate?.(particle, delta);
6347
+ }
6348
+ }
6349
+ this._updateParticleBucket(particle);
6350
+ }
6351
+ };
6232
6352
  }
6233
6353
 
6234
6354
  class Retina {
@@ -6244,9 +6364,8 @@
6244
6364
  const container = this.container, options = container.actualOptions;
6245
6365
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
6246
6366
  this.reduceFactor = defaultReduceFactor;
6247
- const ratio = this.pixelRatio, canvas = container.canvas;
6248
- if (canvas.element) {
6249
- const element = canvas.element;
6367
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
6368
+ if (element) {
6250
6369
  canvas.size.width = element.offsetWidth * ratio;
6251
6370
  canvas.size.height = element.offsetHeight * ratio;
6252
6371
  }
@@ -6956,7 +7075,7 @@
6956
7075
  return;
6957
7076
  }
6958
7077
  const html = interactivityEl, canvas = container.canvas;
6959
- canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
7078
+ canvas.setPointerEvents(html === canvas.domElement ? "initial" : "none");
6960
7079
  if (add && !(options.interactivity?.events.onHover.enable || options.interactivity?.events.onClick.enable)) {
6961
7080
  return;
6962
7081
  }
@@ -6983,7 +7102,7 @@
6983
7102
  manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
6984
7103
  };
6985
7104
  _manageListeners = add => {
6986
- const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.element;
7105
+ const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.domElement;
6987
7106
  if (detectType === InteractivityDetect.window) {
6988
7107
  interactionManager.interactivityData.element = safeDocument();
6989
7108
  }
@@ -7030,7 +7149,7 @@
7030
7149
  mouse.clicking = false;
7031
7150
  };
7032
7151
  _mouseTouchMove = e => {
7033
- const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.element;
7152
+ const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.domElement;
7034
7153
  if (!interactivity.element) {
7035
7154
  return;
7036
7155
  }
@@ -7191,7 +7310,7 @@
7191
7310
  if (!lastTouch) {
7192
7311
  return;
7193
7312
  }
7194
- const element = container.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
7313
+ const element = container.canvas.domElement, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
7195
7314
  x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
7196
7315
  y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
7197
7316
  };