@tsparticles/preset-big-circles 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) :
@@ -15,7 +15,7 @@
15
15
  b: 0,
16
16
  c: 0,
17
17
  d: 1,
18
- }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
18
+ }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
19
19
 
20
20
  var MoveDirection;
21
21
  (function (MoveDirection) {
@@ -959,7 +959,7 @@
959
959
  }
960
960
  }
961
961
  else {
962
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases[canvasFirstIndex];
962
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
963
963
  if (foundCanvas) {
964
964
  canvasEl = foundCanvas;
965
965
  canvasEl.dataset[generatedAttribute] = generatedFalse;
@@ -996,7 +996,7 @@
996
996
  return this._domArray;
997
997
  }
998
998
  get version() {
999
- return "4.0.0-beta.16";
999
+ return "4.0.0";
1000
1000
  }
1001
1001
  addEventListener(type, listener) {
1002
1002
  this._eventDispatcher.addEventListener(type, listener);
@@ -1027,7 +1027,11 @@
1027
1027
  }
1028
1028
  async load(params) {
1029
1029
  await this.init();
1030
- 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({
1030
+ let domSourceElement;
1031
+ if (typeof HTMLElement !== "undefined" && params.element instanceof HTMLElement) {
1032
+ domSourceElement = params.element;
1033
+ }
1034
+ 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({
1031
1035
  dispatchCallback: (eventType, args) => {
1032
1036
  this.dispatchEvent(eventType, args);
1033
1037
  },
@@ -1054,8 +1058,10 @@
1054
1058
  else {
1055
1059
  items.push(newItem);
1056
1060
  }
1057
- const domContainer = getDomContainer(id, params.element), canvasEl = getCanvasFromContainer(domContainer);
1058
- newItem.canvas.loadCanvas(canvasEl);
1061
+ const sourceCanvas = typeof OffscreenCanvas !== "undefined" && params.element instanceof OffscreenCanvas
1062
+ ? params.element
1063
+ : getCanvasFromContainer(getDomContainer(id, domSourceElement));
1064
+ newItem.canvas.loadCanvas(sourceCanvas);
1059
1065
  await newItem.start();
1060
1066
  return newItem;
1061
1067
  }
@@ -2848,7 +2854,7 @@
2848
2854
  }
2849
2855
 
2850
2856
  async function loadCircleShape(engine) {
2851
- engine.checkVersion("4.0.0-beta.16");
2857
+ engine.checkVersion("4.0.0");
2852
2858
  await engine.pluginManager.register(e => {
2853
2859
  e.pluginManager.addShape(["circle"], () => {
2854
2860
  return Promise.resolve(new CircleDrawer());
@@ -2896,7 +2902,7 @@
2896
2902
  }
2897
2903
 
2898
2904
  async function loadHexColorPlugin(engine) {
2899
- engine.checkVersion("4.0.0-beta.16");
2905
+ engine.checkVersion("4.0.0");
2900
2906
  await engine.pluginManager.register(e => {
2901
2907
  e.pluginManager.addColorManager("hex", new HexColorManager());
2902
2908
  });
@@ -2949,7 +2955,7 @@
2949
2955
  }
2950
2956
 
2951
2957
  async function loadHslColorPlugin(engine) {
2952
- engine.checkVersion("4.0.0-beta.16");
2958
+ engine.checkVersion("4.0.0");
2953
2959
  await engine.pluginManager.register(e => {
2954
2960
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2955
2961
  });
@@ -2973,7 +2979,7 @@
2973
2979
  }
2974
2980
 
2975
2981
  async function loadMovePlugin(engine) {
2976
- engine.checkVersion("4.0.0-beta.16");
2982
+ engine.checkVersion("4.0.0");
2977
2983
  await engine.pluginManager.register(e => {
2978
2984
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2979
2985
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -3034,7 +3040,7 @@
3034
3040
  }
3035
3041
 
3036
3042
  async function loadOpacityUpdater(engine) {
3037
- engine.checkVersion("4.0.0-beta.16");
3043
+ engine.checkVersion("4.0.0");
3038
3044
  await engine.pluginManager.register(e => {
3039
3045
  e.pluginManager.addParticleUpdater("opacity", container => {
3040
3046
  return Promise.resolve(new OpacityUpdater(container));
@@ -3386,7 +3392,7 @@
3386
3392
  }
3387
3393
 
3388
3394
  async function loadOutModesUpdater(engine) {
3389
- engine.checkVersion("4.0.0-beta.16");
3395
+ engine.checkVersion("4.0.0");
3390
3396
  await engine.pluginManager.register(e => {
3391
3397
  e.pluginManager.addParticleUpdater("outModes", container => {
3392
3398
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3457,7 +3463,7 @@
3457
3463
  }
3458
3464
 
3459
3465
  async function loadPaintUpdater(engine) {
3460
- engine.checkVersion("4.0.0-beta.16");
3466
+ engine.checkVersion("4.0.0");
3461
3467
  await engine.pluginManager.register(e => {
3462
3468
  e.pluginManager.addParticleUpdater("paint", container => {
3463
3469
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3512,7 +3518,7 @@
3512
3518
  }
3513
3519
 
3514
3520
  async function loadRgbColorPlugin(engine) {
3515
- engine.checkVersion("4.0.0-beta.16");
3521
+ engine.checkVersion("4.0.0");
3516
3522
  await engine.pluginManager.register(e => {
3517
3523
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3518
3524
  });
@@ -3555,7 +3561,7 @@
3555
3561
  }
3556
3562
 
3557
3563
  async function loadSizeUpdater(engine) {
3558
- engine.checkVersion("4.0.0-beta.16");
3564
+ engine.checkVersion("4.0.0");
3559
3565
  await engine.pluginManager.register(e => {
3560
3566
  e.pluginManager.addParticleUpdater("size", container => {
3561
3567
  return Promise.resolve(new SizeUpdater(container));
@@ -3564,7 +3570,7 @@
3564
3570
  }
3565
3571
 
3566
3572
  async function loadBasic(engine) {
3567
- engine.checkVersion("4.0.0-beta.16");
3573
+ engine.checkVersion("4.0.0");
3568
3574
  await engine.pluginManager.register(async (e) => {
3569
3575
  await Promise.all([
3570
3576
  loadHexColorPlugin(e),
@@ -3978,6 +3984,25 @@
3978
3984
  };
3979
3985
  }
3980
3986
 
3987
+ const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
3988
+ const transferredCanvas = transferredCanvases.get(canvas);
3989
+ if (transferredCanvas) {
3990
+ return transferredCanvas;
3991
+ }
3992
+ if (typeof canvas.transferControlToOffscreen !== "function") {
3993
+ throw new TypeError("OffscreenCanvas is required but not supported by this browser");
3994
+ }
3995
+ try {
3996
+ const offscreenCanvas = canvas.transferControlToOffscreen();
3997
+ transferredCanvases.set(canvas, offscreenCanvas);
3998
+ return offscreenCanvas;
3999
+ }
4000
+ catch {
4001
+ throw new TypeError("OffscreenCanvas transfer failed");
4002
+ }
4003
+ }, isHtmlCanvasElement = (canvas) => {
4004
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
4005
+ };
3981
4006
  function setStyle(canvas, style, important = false) {
3982
4007
  if (!style) {
3983
4008
  return;
@@ -4008,8 +4033,9 @@
4008
4033
  }
4009
4034
  }
4010
4035
  class CanvasManager {
4011
- element;
4036
+ domElement;
4012
4037
  render;
4038
+ renderCanvas;
4013
4039
  size;
4014
4040
  zoom = defaultZoom;
4015
4041
  _container;
@@ -4044,9 +4070,10 @@
4044
4070
  destroy() {
4045
4071
  this.stop();
4046
4072
  if (this._generated) {
4047
- const element = this.element;
4073
+ const element = this.domElement;
4048
4074
  element?.remove();
4049
- this.element = undefined;
4075
+ this.domElement = undefined;
4076
+ this.renderCanvas = undefined;
4050
4077
  }
4051
4078
  else {
4052
4079
  this._resetOriginalStyle();
@@ -4079,16 +4106,17 @@
4079
4106
  this._initStyle();
4080
4107
  this.initBackground();
4081
4108
  this._safeMutationObserver(obs => {
4082
- if (!this.element || !(this.element instanceof Node)) {
4109
+ const element = this.domElement;
4110
+ if (!element || !(element instanceof Node)) {
4083
4111
  return;
4084
4112
  }
4085
- obs.observe(this.element, { attributes: true });
4113
+ obs.observe(element, { attributes: true });
4086
4114
  });
4087
4115
  this.initPlugins();
4088
4116
  this.render.init();
4089
4117
  }
4090
4118
  initBackground() {
4091
- const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
4119
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.domElement;
4092
4120
  if (!element) {
4093
4121
  return;
4094
4122
  }
@@ -4113,21 +4141,30 @@
4113
4141
  }
4114
4142
  }
4115
4143
  loadCanvas(canvas) {
4116
- if (this._generated && this.element) {
4117
- this.element.remove();
4144
+ if (this._generated && this.domElement) {
4145
+ this.domElement.remove();
4146
+ }
4147
+ const container = this._container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4148
+ this.domElement = domCanvas;
4149
+ this._generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4150
+ this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
4151
+ const domElement = this.domElement;
4152
+ if (domElement) {
4153
+ domElement.ariaHidden = "true";
4154
+ this._originalStyle = cloneStyle(domElement.style);
4155
+ }
4156
+ const standardSize = this._standardSize, renderCanvas = this.renderCanvas;
4157
+ if (domElement) {
4158
+ standardSize.height = domElement.offsetHeight;
4159
+ standardSize.width = domElement.offsetWidth;
4160
+ }
4161
+ else {
4162
+ standardSize.height = renderCanvas.height;
4163
+ standardSize.width = renderCanvas.width;
4118
4164
  }
4119
- const container = this._container;
4120
- this._generated =
4121
- generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
4122
- this.element = canvas;
4123
- this.element.ariaHidden = "true";
4124
- this._originalStyle = cloneStyle(this.element.style);
4125
- const standardSize = this._standardSize;
4126
- standardSize.height = canvas.offsetHeight;
4127
- standardSize.width = canvas.offsetWidth;
4128
4165
  const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
4129
- canvas.height = retinaSize.height = standardSize.height * pxRatio;
4130
- canvas.width = retinaSize.width = standardSize.width * pxRatio;
4166
+ renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4167
+ renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4131
4168
  const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4132
4169
  this.render.setContextSettings({
4133
4170
  alpha: true,
@@ -4135,42 +4172,48 @@
4135
4172
  desynchronized: true,
4136
4173
  willReadFrequently: false,
4137
4174
  });
4138
- this.render.setContext(this.element.getContext("2d", this.render.settings));
4175
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4139
4176
  this._safeMutationObserver(obs => {
4140
4177
  obs.disconnect();
4141
4178
  });
4142
4179
  container.retina.init();
4143
4180
  this.initBackground();
4144
4181
  this._safeMutationObserver(obs => {
4145
- if (!this.element || !(this.element instanceof Node)) {
4182
+ const element = this.domElement;
4183
+ if (!element || !(element instanceof Node)) {
4146
4184
  return;
4147
4185
  }
4148
- obs.observe(this.element, { attributes: true });
4186
+ obs.observe(element, { attributes: true });
4149
4187
  });
4150
4188
  }
4151
4189
  resize() {
4152
- if (!this.element) {
4190
+ const element = this.domElement;
4191
+ if (!element) {
4192
+ return false;
4193
+ }
4194
+ const container = this._container, renderCanvas = this.renderCanvas;
4195
+ if (renderCanvas === undefined) {
4153
4196
  return false;
4154
4197
  }
4155
- const container = this._container, currentSize = container.canvas._standardSize, newSize = {
4156
- width: this.element.offsetWidth,
4157
- height: this.element.offsetHeight,
4198
+ const currentSize = container.canvas._standardSize, newSize = {
4199
+ width: element.offsetWidth,
4200
+ height: element.offsetHeight,
4158
4201
  }, pxRatio = container.retina.pixelRatio, retinaSize = {
4159
4202
  width: newSize.width * pxRatio,
4160
4203
  height: newSize.height * pxRatio,
4161
4204
  };
4162
4205
  if (newSize.height === currentSize.height &&
4163
4206
  newSize.width === currentSize.width &&
4164
- retinaSize.height === this.element.height &&
4165
- retinaSize.width === this.element.width) {
4207
+ retinaSize.height === renderCanvas.height &&
4208
+ retinaSize.width === renderCanvas.width) {
4166
4209
  return false;
4167
4210
  }
4168
4211
  const oldSize = { ...currentSize };
4169
4212
  currentSize.height = newSize.height;
4170
4213
  currentSize.width = newSize.width;
4171
4214
  const canvasSize = this.size;
4172
- this.element.width = canvasSize.width = retinaSize.width;
4173
- this.element.height = canvasSize.height = retinaSize.height;
4215
+ renderCanvas.width = canvasSize.width = retinaSize.width;
4216
+ renderCanvas.height = canvasSize.height = retinaSize.height;
4174
4217
  if (this._container.started) {
4175
4218
  container.particles.setResizeFactor({
4176
4219
  width: currentSize.width / oldSize.width,
@@ -4180,7 +4223,7 @@
4180
4223
  return true;
4181
4224
  }
4182
4225
  setPointerEvents(type) {
4183
- const element = this.element;
4226
+ const element = this.domElement;
4184
4227
  if (!element) {
4185
4228
  return;
4186
4229
  }
@@ -4199,7 +4242,7 @@
4199
4242
  this.render.stop();
4200
4243
  }
4201
4244
  async windowResize() {
4202
- if (!this.element || !this.resize()) {
4245
+ if (!this.domElement || !this.resize()) {
4203
4246
  return;
4204
4247
  }
4205
4248
  const container = this._container, needsRefresh = container.updateActualOptions();
@@ -4215,7 +4258,7 @@
4215
4258
  }
4216
4259
  };
4217
4260
  _initStyle = () => {
4218
- const element = this.element, options = this._container.actualOptions;
4261
+ const element = this.domElement, options = this._container.actualOptions;
4219
4262
  if (!element) {
4220
4263
  return;
4221
4264
  }
@@ -4237,7 +4280,7 @@
4237
4280
  }
4238
4281
  };
4239
4282
  _repairStyle = () => {
4240
- const element = this.element;
4283
+ const element = this.domElement;
4241
4284
  if (!element) {
4242
4285
  return;
4243
4286
  }
@@ -4257,7 +4300,7 @@
4257
4300
  });
4258
4301
  };
4259
4302
  _resetOriginalStyle = () => {
4260
- const element = this.element, originalStyle = this._originalStyle;
4303
+ const element = this.domElement, originalStyle = this._originalStyle;
4261
4304
  if (!element || !originalStyle) {
4262
4305
  return;
4263
4306
  }
@@ -4270,7 +4313,7 @@
4270
4313
  callback(this._mutationObserver);
4271
4314
  };
4272
4315
  _setFullScreenStyle = () => {
4273
- const element = this.element;
4316
+ const element = this.domElement;
4274
4317
  if (!element) {
4275
4318
  return;
4276
4319
  }
@@ -4344,7 +4387,7 @@
4344
4387
  manageListener(globalThis, resizeEvent, handlers.resize, add);
4345
4388
  return;
4346
4389
  }
4347
- const canvasEl = container.canvas.element;
4390
+ const canvasEl = container.canvas.domElement;
4348
4391
  if (this._resizeObserver && !add) {
4349
4392
  if (canvasEl) {
4350
4393
  this._resizeObserver.unobserve(canvasEl);
@@ -4599,8 +4642,6 @@
4599
4642
  this._initPosition(position);
4600
4643
  this.initialVelocity = this._calculateVelocity();
4601
4644
  this.velocity = this.initialVelocity.copy();
4602
- const particles = container.particles;
4603
- particles.setLastZIndex(this.position.z);
4604
4645
  this.zIndexFactor = this.position.z / container.zLayers;
4605
4646
  this.sides = 24;
4606
4647
  let effectDrawer, shapeDrawer;
@@ -4750,7 +4791,7 @@
4750
4791
  return color;
4751
4792
  };
4752
4793
  _initPosition = position => {
4753
- const container = this._container, zIndexValue = getRangeValue(this.options.zIndex.value), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
4794
+ const container = this._container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
4754
4795
  if (!initialPosition) {
4755
4796
  throw new Error("a valid position cannot be found for particle");
4756
4797
  }
@@ -4884,10 +4925,8 @@
4884
4925
  _container;
4885
4926
  _groupLimits;
4886
4927
  _limit;
4887
- _maxZIndex;
4888
- _minZIndex;
4889
- _needsSort;
4890
4928
  _nextId;
4929
+ _particleBuckets;
4891
4930
  _particleResetPlugins;
4892
4931
  _particleUpdatePlugins;
4893
4932
  _pluginManager;
@@ -4896,19 +4935,17 @@
4896
4935
  _postUpdatePlugins;
4897
4936
  _resizeFactor;
4898
4937
  _updatePlugins;
4899
- _zArray;
4938
+ _zBuckets;
4900
4939
  constructor(pluginManager, container) {
4901
4940
  this._pluginManager = pluginManager;
4902
4941
  this._container = container;
4903
4942
  this._nextId = 0;
4904
4943
  this._array = [];
4905
- this._zArray = [];
4906
4944
  this._pool = [];
4907
4945
  this._limit = 0;
4908
4946
  this._groupLimits = new Map();
4909
- this._needsSort = false;
4910
- this._minZIndex = 0;
4911
- this._maxZIndex = 0;
4947
+ this._particleBuckets = new Map();
4948
+ this._zBuckets = this._createBuckets(this._container.zLayers);
4912
4949
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
4913
4950
  this.checkParticlePositionPlugins = [];
4914
4951
  this._particleResetPlugins = [];
@@ -4950,7 +4987,7 @@
4950
4987
  return;
4951
4988
  }
4952
4989
  this._array.push(particle);
4953
- this._zArray.push(particle);
4990
+ this._insertParticleIntoBucket(particle);
4954
4991
  this._nextId++;
4955
4992
  this._container.dispatchEvent(EventType.particleAdded, {
4956
4993
  particle,
@@ -4964,12 +5001,14 @@
4964
5001
  }
4965
5002
  clear() {
4966
5003
  this._array = [];
4967
- this._zArray = [];
5004
+ this._particleBuckets.clear();
5005
+ this._resetBuckets(this._container.zLayers);
4968
5006
  }
4969
5007
  destroy() {
4970
5008
  this._array = [];
4971
5009
  this._pool.length = 0;
4972
- this._zArray = [];
5010
+ this._particleBuckets.clear();
5011
+ this._zBuckets = [];
4973
5012
  this.checkParticlePositionPlugins = [];
4974
5013
  this._particleResetPlugins = [];
4975
5014
  this._particleUpdatePlugins = [];
@@ -4978,8 +5017,14 @@
4978
5017
  this._updatePlugins = [];
4979
5018
  }
4980
5019
  drawParticles(delta) {
4981
- for (const particle of this._zArray) {
4982
- particle.draw(delta);
5020
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
5021
+ const bucket = this._zBuckets[i];
5022
+ if (!bucket) {
5023
+ continue;
5024
+ }
5025
+ for (const particle of bucket) {
5026
+ particle.draw(delta);
5027
+ }
4983
5028
  }
4984
5029
  }
4985
5030
  filter(condition) {
@@ -4993,15 +5038,14 @@
4993
5038
  }
4994
5039
  async init() {
4995
5040
  const container = this._container, options = container.actualOptions;
4996
- this._minZIndex = 0;
4997
- this._maxZIndex = 0;
4998
- this._needsSort = false;
4999
5041
  this.checkParticlePositionPlugins = [];
5000
5042
  this._updatePlugins = [];
5001
5043
  this._particleUpdatePlugins = [];
5002
5044
  this._postUpdatePlugins = [];
5003
5045
  this._particleResetPlugins = [];
5004
5046
  this._postParticleUpdatePlugins = [];
5047
+ this._particleBuckets.clear();
5048
+ this._resetBuckets(container.zLayers);
5005
5049
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5006
5050
  for (const plugin of container.plugins) {
5007
5051
  if (plugin.redrawInit) {
@@ -5102,79 +5146,25 @@
5102
5146
  }
5103
5147
  this._applyDensity(options.particles, pluginsCount);
5104
5148
  }
5105
- setLastZIndex(zIndex) {
5106
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
5107
- }
5108
5149
  setResizeFactor(factor) {
5109
5150
  this._resizeFactor = factor;
5110
5151
  }
5111
5152
  update(delta) {
5112
- const particlesToDelete = new Set();
5113
5153
  this.grid.clear();
5114
5154
  for (const plugin of this._updatePlugins) {
5115
5155
  plugin.update?.(delta);
5116
5156
  }
5117
- const resizeFactor = this._resizeFactor;
5118
- for (const particle of this._array) {
5119
- if (resizeFactor && !particle.ignoresResizeRatio) {
5120
- particle.position.x *= resizeFactor.width;
5121
- particle.position.y *= resizeFactor.height;
5122
- particle.initialPosition.x *= resizeFactor.width;
5123
- particle.initialPosition.y *= resizeFactor.height;
5124
- }
5125
- particle.ignoresResizeRatio = false;
5126
- for (const plugin of this._particleResetPlugins) {
5127
- plugin.particleReset?.(particle);
5128
- }
5129
- for (const plugin of this._particleUpdatePlugins) {
5130
- if (particle.destroyed) {
5131
- break;
5132
- }
5133
- plugin.particleUpdate?.(particle, delta);
5134
- }
5135
- if (particle.destroyed) {
5136
- particlesToDelete.add(particle);
5137
- continue;
5138
- }
5139
- this.grid.insert(particle);
5140
- }
5157
+ const particlesToDelete = this._updateParticlesPhase1(delta);
5141
5158
  for (const plugin of this._postUpdatePlugins) {
5142
5159
  plugin.postUpdate?.(delta);
5143
5160
  }
5144
- for (const particle of this._array) {
5145
- if (particle.destroyed) {
5146
- particlesToDelete.add(particle);
5147
- continue;
5148
- }
5149
- for (const updater of this._container.particleUpdaters) {
5150
- updater.update(particle, delta);
5151
- }
5152
- if (!particle.destroyed && !particle.spawning) {
5153
- for (const plugin of this._postParticleUpdatePlugins) {
5154
- plugin.postParticleUpdate?.(particle, delta);
5155
- }
5156
- }
5157
- else if (particle.destroyed) {
5158
- particlesToDelete.add(particle);
5159
- }
5160
- }
5161
+ this._updateParticlesPhase2(delta, particlesToDelete);
5161
5162
  if (particlesToDelete.size) {
5162
5163
  for (const particle of particlesToDelete) {
5163
5164
  this.remove(particle);
5164
5165
  }
5165
5166
  }
5166
5167
  delete this._resizeFactor;
5167
- if (this._needsSort) {
5168
- const zArray = this._zArray;
5169
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
5170
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
5171
- if (!firstItem || !lastItem) {
5172
- return;
5173
- }
5174
- this._maxZIndex = firstItem.position.z;
5175
- this._minZIndex = lastItem.position.z;
5176
- this._needsSort = false;
5177
- }
5178
5168
  }
5179
5169
  _addToPool = (...particles) => {
5180
5170
  this._pool.push(...particles);
@@ -5204,13 +5194,52 @@
5204
5194
  this.removeQuantity(particlesCount - particlesNumber, group);
5205
5195
  }
5206
5196
  };
5197
+ _createBuckets = (zLayers) => {
5198
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5199
+ return Array.from({ length: bucketCount }, () => []);
5200
+ };
5201
+ _getBucketIndex = (zIndex) => {
5202
+ const maxBucketIndex = this._zBuckets.length - one;
5203
+ if (maxBucketIndex <= minIndex) {
5204
+ return minIndex;
5205
+ }
5206
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
5207
+ };
5208
+ _getParticleInsertIndex = (bucket, particleId) => {
5209
+ let start = minIndex, end = bucket.length;
5210
+ while (start < end) {
5211
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
5212
+ if (!middleParticle) {
5213
+ end = middle;
5214
+ continue;
5215
+ }
5216
+ if (middleParticle.id < particleId) {
5217
+ start = middle + one;
5218
+ }
5219
+ else {
5220
+ end = middle;
5221
+ }
5222
+ }
5223
+ return start;
5224
+ };
5207
5225
  _initDensityFactor = densityOptions => {
5208
5226
  const container = this._container;
5209
- if (!container.canvas.element || !densityOptions.enable) {
5227
+ if (!densityOptions.enable) {
5228
+ return defaultDensityFactor;
5229
+ }
5230
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
5231
+ if (!canvasSize.width || !canvasSize.height) {
5210
5232
  return defaultDensityFactor;
5211
5233
  }
5212
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
5213
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
5234
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5235
+ };
5236
+ _insertParticleIntoBucket = (particle) => {
5237
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5238
+ if (!bucket) {
5239
+ return;
5240
+ }
5241
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
5242
+ this._particleBuckets.set(particle.id, bucketIndex);
5214
5243
  };
5215
5244
  _removeParticle = (index, group, override) => {
5216
5245
  const particle = this._array[index];
@@ -5220,9 +5249,8 @@
5220
5249
  if (particle.group !== group) {
5221
5250
  return false;
5222
5251
  }
5223
- const zIdx = this._zArray.indexOf(particle);
5224
5252
  this._array.splice(index, deleteCount);
5225
- this._zArray.splice(zIdx, deleteCount);
5253
+ this._removeParticleFromBucket(particle);
5226
5254
  particle.destroy(override);
5227
5255
  this._container.dispatchEvent(EventType.particleRemoved, {
5228
5256
  particle,
@@ -5230,6 +5258,98 @@
5230
5258
  this._addToPool(particle);
5231
5259
  return true;
5232
5260
  };
5261
+ _removeParticleFromBucket = (particle) => {
5262
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5263
+ if (!bucket) {
5264
+ this._particleBuckets.delete(particle.id);
5265
+ return;
5266
+ }
5267
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
5268
+ if (bucket[particleIndex]?.id !== particle.id) {
5269
+ this._particleBuckets.delete(particle.id);
5270
+ return;
5271
+ }
5272
+ bucket.splice(particleIndex, deleteCount);
5273
+ this._particleBuckets.delete(particle.id);
5274
+ };
5275
+ _resetBuckets = (zLayers) => {
5276
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5277
+ if (this._zBuckets.length !== bucketCount) {
5278
+ this._zBuckets = this._createBuckets(bucketCount);
5279
+ return;
5280
+ }
5281
+ for (const bucket of this._zBuckets) {
5282
+ bucket.length = minIndex;
5283
+ }
5284
+ };
5285
+ _updateParticleBucket = (particle) => {
5286
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
5287
+ if (currentBucketIndex === undefined) {
5288
+ this._insertParticleIntoBucket(particle);
5289
+ return;
5290
+ }
5291
+ if (currentBucketIndex === newBucketIndex) {
5292
+ return;
5293
+ }
5294
+ const currentBucket = this._zBuckets[currentBucketIndex];
5295
+ if (currentBucket) {
5296
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
5297
+ if (currentBucket[particleIndex]?.id === particle.id) {
5298
+ currentBucket.splice(particleIndex, deleteCount);
5299
+ }
5300
+ }
5301
+ const newBucket = this._zBuckets[newBucketIndex];
5302
+ if (!newBucket) {
5303
+ this._particleBuckets.set(particle.id, newBucketIndex);
5304
+ return;
5305
+ }
5306
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
5307
+ this._particleBuckets.set(particle.id, newBucketIndex);
5308
+ };
5309
+ _updateParticlesPhase1 = (delta) => {
5310
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
5311
+ for (const particle of this._array) {
5312
+ if (resizeFactor && !particle.ignoresResizeRatio) {
5313
+ particle.position.x *= resizeFactor.width;
5314
+ particle.position.y *= resizeFactor.height;
5315
+ particle.initialPosition.x *= resizeFactor.width;
5316
+ particle.initialPosition.y *= resizeFactor.height;
5317
+ }
5318
+ particle.ignoresResizeRatio = false;
5319
+ for (const plugin of this._particleResetPlugins) {
5320
+ plugin.particleReset?.(particle);
5321
+ }
5322
+ for (const plugin of this._particleUpdatePlugins) {
5323
+ if (particle.destroyed) {
5324
+ break;
5325
+ }
5326
+ plugin.particleUpdate?.(particle, delta);
5327
+ }
5328
+ if (particle.destroyed) {
5329
+ particlesToDelete.add(particle);
5330
+ continue;
5331
+ }
5332
+ this.grid.insert(particle);
5333
+ }
5334
+ return particlesToDelete;
5335
+ };
5336
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
5337
+ for (const particle of this._array) {
5338
+ if (particle.destroyed) {
5339
+ particlesToDelete.add(particle);
5340
+ continue;
5341
+ }
5342
+ for (const updater of this._container.particleUpdaters) {
5343
+ updater.update(particle, delta);
5344
+ }
5345
+ if (!particle.spawning) {
5346
+ for (const plugin of this._postParticleUpdatePlugins) {
5347
+ plugin.postParticleUpdate?.(particle, delta);
5348
+ }
5349
+ }
5350
+ this._updateParticleBucket(particle);
5351
+ }
5352
+ };
5233
5353
  }
5234
5354
 
5235
5355
  class Retina {
@@ -5245,9 +5365,8 @@
5245
5365
  const container = this.container, options = container.actualOptions;
5246
5366
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
5247
5367
  this.reduceFactor = defaultReduceFactor;
5248
- const ratio = this.pixelRatio, canvas = container.canvas;
5249
- if (canvas.element) {
5250
- const element = canvas.element;
5368
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
5369
+ if (element) {
5251
5370
  canvas.size.width = element.offsetWidth * ratio;
5252
5371
  canvas.size.height = element.offsetHeight * ratio;
5253
5372
  }