@tsparticles/preset-stars 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),
@@ -3932,6 +3938,25 @@
3932
3938
  };
3933
3939
  }
3934
3940
 
3941
+ const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
3942
+ const transferredCanvas = transferredCanvases.get(canvas);
3943
+ if (transferredCanvas) {
3944
+ return transferredCanvas;
3945
+ }
3946
+ if (typeof canvas.transferControlToOffscreen !== "function") {
3947
+ throw new TypeError("OffscreenCanvas is required but not supported by this browser");
3948
+ }
3949
+ try {
3950
+ const offscreenCanvas = canvas.transferControlToOffscreen();
3951
+ transferredCanvases.set(canvas, offscreenCanvas);
3952
+ return offscreenCanvas;
3953
+ }
3954
+ catch {
3955
+ throw new TypeError("OffscreenCanvas transfer failed");
3956
+ }
3957
+ }, isHtmlCanvasElement = (canvas) => {
3958
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
3959
+ };
3935
3960
  function setStyle(canvas, style, important = false) {
3936
3961
  if (!style) {
3937
3962
  return;
@@ -3962,8 +3987,9 @@
3962
3987
  }
3963
3988
  }
3964
3989
  class CanvasManager {
3965
- element;
3990
+ domElement;
3966
3991
  render;
3992
+ renderCanvas;
3967
3993
  size;
3968
3994
  zoom = defaultZoom;
3969
3995
  _container;
@@ -3998,9 +4024,10 @@
3998
4024
  destroy() {
3999
4025
  this.stop();
4000
4026
  if (this._generated) {
4001
- const element = this.element;
4027
+ const element = this.domElement;
4002
4028
  element?.remove();
4003
- this.element = undefined;
4029
+ this.domElement = undefined;
4030
+ this.renderCanvas = undefined;
4004
4031
  }
4005
4032
  else {
4006
4033
  this._resetOriginalStyle();
@@ -4033,16 +4060,17 @@
4033
4060
  this._initStyle();
4034
4061
  this.initBackground();
4035
4062
  this._safeMutationObserver(obs => {
4036
- if (!this.element || !(this.element instanceof Node)) {
4063
+ const element = this.domElement;
4064
+ if (!element || !(element instanceof Node)) {
4037
4065
  return;
4038
4066
  }
4039
- obs.observe(this.element, { attributes: true });
4067
+ obs.observe(element, { attributes: true });
4040
4068
  });
4041
4069
  this.initPlugins();
4042
4070
  this.render.init();
4043
4071
  }
4044
4072
  initBackground() {
4045
- const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
4073
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.domElement;
4046
4074
  if (!element) {
4047
4075
  return;
4048
4076
  }
@@ -4067,21 +4095,30 @@
4067
4095
  }
4068
4096
  }
4069
4097
  loadCanvas(canvas) {
4070
- if (this._generated && this.element) {
4071
- this.element.remove();
4098
+ if (this._generated && this.domElement) {
4099
+ this.domElement.remove();
4100
+ }
4101
+ const container = this._container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4102
+ this.domElement = domCanvas;
4103
+ this._generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4104
+ this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
4105
+ const domElement = this.domElement;
4106
+ if (domElement) {
4107
+ domElement.ariaHidden = "true";
4108
+ this._originalStyle = cloneStyle(domElement.style);
4109
+ }
4110
+ const standardSize = this._standardSize, renderCanvas = this.renderCanvas;
4111
+ if (domElement) {
4112
+ standardSize.height = domElement.offsetHeight;
4113
+ standardSize.width = domElement.offsetWidth;
4114
+ }
4115
+ else {
4116
+ standardSize.height = renderCanvas.height;
4117
+ standardSize.width = renderCanvas.width;
4072
4118
  }
4073
- const container = this._container;
4074
- this._generated =
4075
- generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
4076
- this.element = canvas;
4077
- this.element.ariaHidden = "true";
4078
- this._originalStyle = cloneStyle(this.element.style);
4079
- const standardSize = this._standardSize;
4080
- standardSize.height = canvas.offsetHeight;
4081
- standardSize.width = canvas.offsetWidth;
4082
4119
  const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
4083
- canvas.height = retinaSize.height = standardSize.height * pxRatio;
4084
- canvas.width = retinaSize.width = standardSize.width * pxRatio;
4120
+ renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4121
+ renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4085
4122
  const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4086
4123
  this.render.setContextSettings({
4087
4124
  alpha: true,
@@ -4089,42 +4126,48 @@
4089
4126
  desynchronized: true,
4090
4127
  willReadFrequently: false,
4091
4128
  });
4092
- this.render.setContext(this.element.getContext("2d", this.render.settings));
4129
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4093
4130
  this._safeMutationObserver(obs => {
4094
4131
  obs.disconnect();
4095
4132
  });
4096
4133
  container.retina.init();
4097
4134
  this.initBackground();
4098
4135
  this._safeMutationObserver(obs => {
4099
- if (!this.element || !(this.element instanceof Node)) {
4136
+ const element = this.domElement;
4137
+ if (!element || !(element instanceof Node)) {
4100
4138
  return;
4101
4139
  }
4102
- obs.observe(this.element, { attributes: true });
4140
+ obs.observe(element, { attributes: true });
4103
4141
  });
4104
4142
  }
4105
4143
  resize() {
4106
- if (!this.element) {
4144
+ const element = this.domElement;
4145
+ if (!element) {
4146
+ return false;
4147
+ }
4148
+ const container = this._container, renderCanvas = this.renderCanvas;
4149
+ if (renderCanvas === undefined) {
4107
4150
  return false;
4108
4151
  }
4109
- const container = this._container, currentSize = container.canvas._standardSize, newSize = {
4110
- width: this.element.offsetWidth,
4111
- height: this.element.offsetHeight,
4152
+ const currentSize = container.canvas._standardSize, newSize = {
4153
+ width: element.offsetWidth,
4154
+ height: element.offsetHeight,
4112
4155
  }, pxRatio = container.retina.pixelRatio, retinaSize = {
4113
4156
  width: newSize.width * pxRatio,
4114
4157
  height: newSize.height * pxRatio,
4115
4158
  };
4116
4159
  if (newSize.height === currentSize.height &&
4117
4160
  newSize.width === currentSize.width &&
4118
- retinaSize.height === this.element.height &&
4119
- retinaSize.width === this.element.width) {
4161
+ retinaSize.height === renderCanvas.height &&
4162
+ retinaSize.width === renderCanvas.width) {
4120
4163
  return false;
4121
4164
  }
4122
4165
  const oldSize = { ...currentSize };
4123
4166
  currentSize.height = newSize.height;
4124
4167
  currentSize.width = newSize.width;
4125
4168
  const canvasSize = this.size;
4126
- this.element.width = canvasSize.width = retinaSize.width;
4127
- this.element.height = canvasSize.height = retinaSize.height;
4169
+ renderCanvas.width = canvasSize.width = retinaSize.width;
4170
+ renderCanvas.height = canvasSize.height = retinaSize.height;
4128
4171
  if (this._container.started) {
4129
4172
  container.particles.setResizeFactor({
4130
4173
  width: currentSize.width / oldSize.width,
@@ -4134,7 +4177,7 @@
4134
4177
  return true;
4135
4178
  }
4136
4179
  setPointerEvents(type) {
4137
- const element = this.element;
4180
+ const element = this.domElement;
4138
4181
  if (!element) {
4139
4182
  return;
4140
4183
  }
@@ -4153,7 +4196,7 @@
4153
4196
  this.render.stop();
4154
4197
  }
4155
4198
  async windowResize() {
4156
- if (!this.element || !this.resize()) {
4199
+ if (!this.domElement || !this.resize()) {
4157
4200
  return;
4158
4201
  }
4159
4202
  const container = this._container, needsRefresh = container.updateActualOptions();
@@ -4169,7 +4212,7 @@
4169
4212
  }
4170
4213
  };
4171
4214
  _initStyle = () => {
4172
- const element = this.element, options = this._container.actualOptions;
4215
+ const element = this.domElement, options = this._container.actualOptions;
4173
4216
  if (!element) {
4174
4217
  return;
4175
4218
  }
@@ -4191,7 +4234,7 @@
4191
4234
  }
4192
4235
  };
4193
4236
  _repairStyle = () => {
4194
- const element = this.element;
4237
+ const element = this.domElement;
4195
4238
  if (!element) {
4196
4239
  return;
4197
4240
  }
@@ -4211,7 +4254,7 @@
4211
4254
  });
4212
4255
  };
4213
4256
  _resetOriginalStyle = () => {
4214
- const element = this.element, originalStyle = this._originalStyle;
4257
+ const element = this.domElement, originalStyle = this._originalStyle;
4215
4258
  if (!element || !originalStyle) {
4216
4259
  return;
4217
4260
  }
@@ -4224,7 +4267,7 @@
4224
4267
  callback(this._mutationObserver);
4225
4268
  };
4226
4269
  _setFullScreenStyle = () => {
4227
- const element = this.element;
4270
+ const element = this.domElement;
4228
4271
  if (!element) {
4229
4272
  return;
4230
4273
  }
@@ -4298,7 +4341,7 @@
4298
4341
  manageListener(globalThis, resizeEvent, handlers.resize, add);
4299
4342
  return;
4300
4343
  }
4301
- const canvasEl = container.canvas.element;
4344
+ const canvasEl = container.canvas.domElement;
4302
4345
  if (this._resizeObserver && !add) {
4303
4346
  if (canvasEl) {
4304
4347
  this._resizeObserver.unobserve(canvasEl);
@@ -4553,8 +4596,6 @@
4553
4596
  this._initPosition(position);
4554
4597
  this.initialVelocity = this._calculateVelocity();
4555
4598
  this.velocity = this.initialVelocity.copy();
4556
- const particles = container.particles;
4557
- particles.setLastZIndex(this.position.z);
4558
4599
  this.zIndexFactor = this.position.z / container.zLayers;
4559
4600
  this.sides = 24;
4560
4601
  let effectDrawer, shapeDrawer;
@@ -4704,7 +4745,7 @@
4704
4745
  return color;
4705
4746
  };
4706
4747
  _initPosition = position => {
4707
- const container = this._container, zIndexValue = getRangeValue(this.options.zIndex.value), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
4748
+ const container = this._container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
4708
4749
  if (!initialPosition) {
4709
4750
  throw new Error("a valid position cannot be found for particle");
4710
4751
  }
@@ -4838,10 +4879,8 @@
4838
4879
  _container;
4839
4880
  _groupLimits;
4840
4881
  _limit;
4841
- _maxZIndex;
4842
- _minZIndex;
4843
- _needsSort;
4844
4882
  _nextId;
4883
+ _particleBuckets;
4845
4884
  _particleResetPlugins;
4846
4885
  _particleUpdatePlugins;
4847
4886
  _pluginManager;
@@ -4850,19 +4889,17 @@
4850
4889
  _postUpdatePlugins;
4851
4890
  _resizeFactor;
4852
4891
  _updatePlugins;
4853
- _zArray;
4892
+ _zBuckets;
4854
4893
  constructor(pluginManager, container) {
4855
4894
  this._pluginManager = pluginManager;
4856
4895
  this._container = container;
4857
4896
  this._nextId = 0;
4858
4897
  this._array = [];
4859
- this._zArray = [];
4860
4898
  this._pool = [];
4861
4899
  this._limit = 0;
4862
4900
  this._groupLimits = new Map();
4863
- this._needsSort = false;
4864
- this._minZIndex = 0;
4865
- this._maxZIndex = 0;
4901
+ this._particleBuckets = new Map();
4902
+ this._zBuckets = this._createBuckets(this._container.zLayers);
4866
4903
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
4867
4904
  this.checkParticlePositionPlugins = [];
4868
4905
  this._particleResetPlugins = [];
@@ -4904,7 +4941,7 @@
4904
4941
  return;
4905
4942
  }
4906
4943
  this._array.push(particle);
4907
- this._zArray.push(particle);
4944
+ this._insertParticleIntoBucket(particle);
4908
4945
  this._nextId++;
4909
4946
  this._container.dispatchEvent(EventType.particleAdded, {
4910
4947
  particle,
@@ -4918,12 +4955,14 @@
4918
4955
  }
4919
4956
  clear() {
4920
4957
  this._array = [];
4921
- this._zArray = [];
4958
+ this._particleBuckets.clear();
4959
+ this._resetBuckets(this._container.zLayers);
4922
4960
  }
4923
4961
  destroy() {
4924
4962
  this._array = [];
4925
4963
  this._pool.length = 0;
4926
- this._zArray = [];
4964
+ this._particleBuckets.clear();
4965
+ this._zBuckets = [];
4927
4966
  this.checkParticlePositionPlugins = [];
4928
4967
  this._particleResetPlugins = [];
4929
4968
  this._particleUpdatePlugins = [];
@@ -4932,8 +4971,14 @@
4932
4971
  this._updatePlugins = [];
4933
4972
  }
4934
4973
  drawParticles(delta) {
4935
- for (const particle of this._zArray) {
4936
- particle.draw(delta);
4974
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
4975
+ const bucket = this._zBuckets[i];
4976
+ if (!bucket) {
4977
+ continue;
4978
+ }
4979
+ for (const particle of bucket) {
4980
+ particle.draw(delta);
4981
+ }
4937
4982
  }
4938
4983
  }
4939
4984
  filter(condition) {
@@ -4947,15 +4992,14 @@
4947
4992
  }
4948
4993
  async init() {
4949
4994
  const container = this._container, options = container.actualOptions;
4950
- this._minZIndex = 0;
4951
- this._maxZIndex = 0;
4952
- this._needsSort = false;
4953
4995
  this.checkParticlePositionPlugins = [];
4954
4996
  this._updatePlugins = [];
4955
4997
  this._particleUpdatePlugins = [];
4956
4998
  this._postUpdatePlugins = [];
4957
4999
  this._particleResetPlugins = [];
4958
5000
  this._postParticleUpdatePlugins = [];
5001
+ this._particleBuckets.clear();
5002
+ this._resetBuckets(container.zLayers);
4959
5003
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
4960
5004
  for (const plugin of container.plugins) {
4961
5005
  if (plugin.redrawInit) {
@@ -5056,79 +5100,25 @@
5056
5100
  }
5057
5101
  this._applyDensity(options.particles, pluginsCount);
5058
5102
  }
5059
- setLastZIndex(zIndex) {
5060
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
5061
- }
5062
5103
  setResizeFactor(factor) {
5063
5104
  this._resizeFactor = factor;
5064
5105
  }
5065
5106
  update(delta) {
5066
- const particlesToDelete = new Set();
5067
5107
  this.grid.clear();
5068
5108
  for (const plugin of this._updatePlugins) {
5069
5109
  plugin.update?.(delta);
5070
5110
  }
5071
- const resizeFactor = this._resizeFactor;
5072
- for (const particle of this._array) {
5073
- if (resizeFactor && !particle.ignoresResizeRatio) {
5074
- particle.position.x *= resizeFactor.width;
5075
- particle.position.y *= resizeFactor.height;
5076
- particle.initialPosition.x *= resizeFactor.width;
5077
- particle.initialPosition.y *= resizeFactor.height;
5078
- }
5079
- particle.ignoresResizeRatio = false;
5080
- for (const plugin of this._particleResetPlugins) {
5081
- plugin.particleReset?.(particle);
5082
- }
5083
- for (const plugin of this._particleUpdatePlugins) {
5084
- if (particle.destroyed) {
5085
- break;
5086
- }
5087
- plugin.particleUpdate?.(particle, delta);
5088
- }
5089
- if (particle.destroyed) {
5090
- particlesToDelete.add(particle);
5091
- continue;
5092
- }
5093
- this.grid.insert(particle);
5094
- }
5111
+ const particlesToDelete = this._updateParticlesPhase1(delta);
5095
5112
  for (const plugin of this._postUpdatePlugins) {
5096
5113
  plugin.postUpdate?.(delta);
5097
5114
  }
5098
- for (const particle of this._array) {
5099
- if (particle.destroyed) {
5100
- particlesToDelete.add(particle);
5101
- continue;
5102
- }
5103
- for (const updater of this._container.particleUpdaters) {
5104
- updater.update(particle, delta);
5105
- }
5106
- if (!particle.destroyed && !particle.spawning) {
5107
- for (const plugin of this._postParticleUpdatePlugins) {
5108
- plugin.postParticleUpdate?.(particle, delta);
5109
- }
5110
- }
5111
- else if (particle.destroyed) {
5112
- particlesToDelete.add(particle);
5113
- }
5114
- }
5115
+ this._updateParticlesPhase2(delta, particlesToDelete);
5115
5116
  if (particlesToDelete.size) {
5116
5117
  for (const particle of particlesToDelete) {
5117
5118
  this.remove(particle);
5118
5119
  }
5119
5120
  }
5120
5121
  delete this._resizeFactor;
5121
- if (this._needsSort) {
5122
- const zArray = this._zArray;
5123
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
5124
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
5125
- if (!firstItem || !lastItem) {
5126
- return;
5127
- }
5128
- this._maxZIndex = firstItem.position.z;
5129
- this._minZIndex = lastItem.position.z;
5130
- this._needsSort = false;
5131
- }
5132
5122
  }
5133
5123
  _addToPool = (...particles) => {
5134
5124
  this._pool.push(...particles);
@@ -5158,13 +5148,52 @@
5158
5148
  this.removeQuantity(particlesCount - particlesNumber, group);
5159
5149
  }
5160
5150
  };
5151
+ _createBuckets = (zLayers) => {
5152
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5153
+ return Array.from({ length: bucketCount }, () => []);
5154
+ };
5155
+ _getBucketIndex = (zIndex) => {
5156
+ const maxBucketIndex = this._zBuckets.length - one;
5157
+ if (maxBucketIndex <= minIndex) {
5158
+ return minIndex;
5159
+ }
5160
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
5161
+ };
5162
+ _getParticleInsertIndex = (bucket, particleId) => {
5163
+ let start = minIndex, end = bucket.length;
5164
+ while (start < end) {
5165
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
5166
+ if (!middleParticle) {
5167
+ end = middle;
5168
+ continue;
5169
+ }
5170
+ if (middleParticle.id < particleId) {
5171
+ start = middle + one;
5172
+ }
5173
+ else {
5174
+ end = middle;
5175
+ }
5176
+ }
5177
+ return start;
5178
+ };
5161
5179
  _initDensityFactor = densityOptions => {
5162
5180
  const container = this._container;
5163
- if (!container.canvas.element || !densityOptions.enable) {
5181
+ if (!densityOptions.enable) {
5182
+ return defaultDensityFactor;
5183
+ }
5184
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
5185
+ if (!canvasSize.width || !canvasSize.height) {
5164
5186
  return defaultDensityFactor;
5165
5187
  }
5166
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
5167
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
5188
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5189
+ };
5190
+ _insertParticleIntoBucket = (particle) => {
5191
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5192
+ if (!bucket) {
5193
+ return;
5194
+ }
5195
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
5196
+ this._particleBuckets.set(particle.id, bucketIndex);
5168
5197
  };
5169
5198
  _removeParticle = (index, group, override) => {
5170
5199
  const particle = this._array[index];
@@ -5174,9 +5203,8 @@
5174
5203
  if (particle.group !== group) {
5175
5204
  return false;
5176
5205
  }
5177
- const zIdx = this._zArray.indexOf(particle);
5178
5206
  this._array.splice(index, deleteCount);
5179
- this._zArray.splice(zIdx, deleteCount);
5207
+ this._removeParticleFromBucket(particle);
5180
5208
  particle.destroy(override);
5181
5209
  this._container.dispatchEvent(EventType.particleRemoved, {
5182
5210
  particle,
@@ -5184,6 +5212,98 @@
5184
5212
  this._addToPool(particle);
5185
5213
  return true;
5186
5214
  };
5215
+ _removeParticleFromBucket = (particle) => {
5216
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5217
+ if (!bucket) {
5218
+ this._particleBuckets.delete(particle.id);
5219
+ return;
5220
+ }
5221
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
5222
+ if (bucket[particleIndex]?.id !== particle.id) {
5223
+ this._particleBuckets.delete(particle.id);
5224
+ return;
5225
+ }
5226
+ bucket.splice(particleIndex, deleteCount);
5227
+ this._particleBuckets.delete(particle.id);
5228
+ };
5229
+ _resetBuckets = (zLayers) => {
5230
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5231
+ if (this._zBuckets.length !== bucketCount) {
5232
+ this._zBuckets = this._createBuckets(bucketCount);
5233
+ return;
5234
+ }
5235
+ for (const bucket of this._zBuckets) {
5236
+ bucket.length = minIndex;
5237
+ }
5238
+ };
5239
+ _updateParticleBucket = (particle) => {
5240
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
5241
+ if (currentBucketIndex === undefined) {
5242
+ this._insertParticleIntoBucket(particle);
5243
+ return;
5244
+ }
5245
+ if (currentBucketIndex === newBucketIndex) {
5246
+ return;
5247
+ }
5248
+ const currentBucket = this._zBuckets[currentBucketIndex];
5249
+ if (currentBucket) {
5250
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
5251
+ if (currentBucket[particleIndex]?.id === particle.id) {
5252
+ currentBucket.splice(particleIndex, deleteCount);
5253
+ }
5254
+ }
5255
+ const newBucket = this._zBuckets[newBucketIndex];
5256
+ if (!newBucket) {
5257
+ this._particleBuckets.set(particle.id, newBucketIndex);
5258
+ return;
5259
+ }
5260
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
5261
+ this._particleBuckets.set(particle.id, newBucketIndex);
5262
+ };
5263
+ _updateParticlesPhase1 = (delta) => {
5264
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
5265
+ for (const particle of this._array) {
5266
+ if (resizeFactor && !particle.ignoresResizeRatio) {
5267
+ particle.position.x *= resizeFactor.width;
5268
+ particle.position.y *= resizeFactor.height;
5269
+ particle.initialPosition.x *= resizeFactor.width;
5270
+ particle.initialPosition.y *= resizeFactor.height;
5271
+ }
5272
+ particle.ignoresResizeRatio = false;
5273
+ for (const plugin of this._particleResetPlugins) {
5274
+ plugin.particleReset?.(particle);
5275
+ }
5276
+ for (const plugin of this._particleUpdatePlugins) {
5277
+ if (particle.destroyed) {
5278
+ break;
5279
+ }
5280
+ plugin.particleUpdate?.(particle, delta);
5281
+ }
5282
+ if (particle.destroyed) {
5283
+ particlesToDelete.add(particle);
5284
+ continue;
5285
+ }
5286
+ this.grid.insert(particle);
5287
+ }
5288
+ return particlesToDelete;
5289
+ };
5290
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
5291
+ for (const particle of this._array) {
5292
+ if (particle.destroyed) {
5293
+ particlesToDelete.add(particle);
5294
+ continue;
5295
+ }
5296
+ for (const updater of this._container.particleUpdaters) {
5297
+ updater.update(particle, delta);
5298
+ }
5299
+ if (!particle.spawning) {
5300
+ for (const plugin of this._postParticleUpdatePlugins) {
5301
+ plugin.postParticleUpdate?.(particle, delta);
5302
+ }
5303
+ }
5304
+ this._updateParticleBucket(particle);
5305
+ }
5306
+ };
5187
5307
  }
5188
5308
 
5189
5309
  class Retina {
@@ -5199,9 +5319,8 @@
5199
5319
  const container = this.container, options = container.actualOptions;
5200
5320
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
5201
5321
  this.reduceFactor = defaultReduceFactor;
5202
- const ratio = this.pixelRatio, canvas = container.canvas;
5203
- if (canvas.element) {
5204
- const element = canvas.element;
5322
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
5323
+ if (element) {
5205
5324
  canvas.size.width = element.offsetWidth * ratio;
5206
5325
  canvas.size.height = element.offsetHeight * ratio;
5207
5326
  }