@tsparticles/preset-bubbles 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) {
@@ -975,7 +975,7 @@
975
975
  }
976
976
  }
977
977
  else {
978
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases[canvasFirstIndex];
978
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
979
979
  if (foundCanvas) {
980
980
  canvasEl = foundCanvas;
981
981
  canvasEl.dataset[generatedAttribute] = generatedFalse;
@@ -1012,7 +1012,7 @@
1012
1012
  return this._domArray;
1013
1013
  }
1014
1014
  get version() {
1015
- return "4.0.0-beta.16";
1015
+ return "4.0.0";
1016
1016
  }
1017
1017
  addEventListener(type, listener) {
1018
1018
  this._eventDispatcher.addEventListener(type, listener);
@@ -1043,7 +1043,11 @@
1043
1043
  }
1044
1044
  async load(params) {
1045
1045
  await this.init();
1046
- 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({
1046
+ let domSourceElement;
1047
+ if (typeof HTMLElement !== "undefined" && params.element instanceof HTMLElement) {
1048
+ domSourceElement = params.element;
1049
+ }
1050
+ 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({
1047
1051
  dispatchCallback: (eventType, args) => {
1048
1052
  this.dispatchEvent(eventType, args);
1049
1053
  },
@@ -1070,8 +1074,10 @@
1070
1074
  else {
1071
1075
  items.push(newItem);
1072
1076
  }
1073
- const domContainer = getDomContainer(id, params.element), canvasEl = getCanvasFromContainer(domContainer);
1074
- newItem.canvas.loadCanvas(canvasEl);
1077
+ const sourceCanvas = typeof OffscreenCanvas !== "undefined" && params.element instanceof OffscreenCanvas
1078
+ ? params.element
1079
+ : getCanvasFromContainer(getDomContainer(id, domSourceElement));
1080
+ newItem.canvas.loadCanvas(sourceCanvas);
1075
1081
  await newItem.start();
1076
1082
  return newItem;
1077
1083
  }
@@ -2864,7 +2870,7 @@
2864
2870
  }
2865
2871
 
2866
2872
  async function loadCircleShape(engine) {
2867
- engine.checkVersion("4.0.0-beta.16");
2873
+ engine.checkVersion("4.0.0");
2868
2874
  await engine.pluginManager.register(e => {
2869
2875
  e.pluginManager.addShape(["circle"], () => {
2870
2876
  return Promise.resolve(new CircleDrawer());
@@ -2912,7 +2918,7 @@
2912
2918
  }
2913
2919
 
2914
2920
  async function loadHexColorPlugin(engine) {
2915
- engine.checkVersion("4.0.0-beta.16");
2921
+ engine.checkVersion("4.0.0");
2916
2922
  await engine.pluginManager.register(e => {
2917
2923
  e.pluginManager.addColorManager("hex", new HexColorManager());
2918
2924
  });
@@ -2965,7 +2971,7 @@
2965
2971
  }
2966
2972
 
2967
2973
  async function loadHslColorPlugin(engine) {
2968
- engine.checkVersion("4.0.0-beta.16");
2974
+ engine.checkVersion("4.0.0");
2969
2975
  await engine.pluginManager.register(e => {
2970
2976
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2971
2977
  });
@@ -2989,7 +2995,7 @@
2989
2995
  }
2990
2996
 
2991
2997
  async function loadMovePlugin(engine) {
2992
- engine.checkVersion("4.0.0-beta.16");
2998
+ engine.checkVersion("4.0.0");
2993
2999
  await engine.pluginManager.register(e => {
2994
3000
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2995
3001
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -3050,7 +3056,7 @@
3050
3056
  }
3051
3057
 
3052
3058
  async function loadOpacityUpdater(engine) {
3053
- engine.checkVersion("4.0.0-beta.16");
3059
+ engine.checkVersion("4.0.0");
3054
3060
  await engine.pluginManager.register(e => {
3055
3061
  e.pluginManager.addParticleUpdater("opacity", container => {
3056
3062
  return Promise.resolve(new OpacityUpdater(container));
@@ -3402,7 +3408,7 @@
3402
3408
  }
3403
3409
 
3404
3410
  async function loadOutModesUpdater(engine) {
3405
- engine.checkVersion("4.0.0-beta.16");
3411
+ engine.checkVersion("4.0.0");
3406
3412
  await engine.pluginManager.register(e => {
3407
3413
  e.pluginManager.addParticleUpdater("outModes", container => {
3408
3414
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3473,7 +3479,7 @@
3473
3479
  }
3474
3480
 
3475
3481
  async function loadPaintUpdater(engine) {
3476
- engine.checkVersion("4.0.0-beta.16");
3482
+ engine.checkVersion("4.0.0");
3477
3483
  await engine.pluginManager.register(e => {
3478
3484
  e.pluginManager.addParticleUpdater("paint", container => {
3479
3485
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3528,7 +3534,7 @@
3528
3534
  }
3529
3535
 
3530
3536
  async function loadRgbColorPlugin(engine) {
3531
- engine.checkVersion("4.0.0-beta.16");
3537
+ engine.checkVersion("4.0.0");
3532
3538
  await engine.pluginManager.register(e => {
3533
3539
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3534
3540
  });
@@ -3571,7 +3577,7 @@
3571
3577
  }
3572
3578
 
3573
3579
  async function loadSizeUpdater(engine) {
3574
- engine.checkVersion("4.0.0-beta.16");
3580
+ engine.checkVersion("4.0.0");
3575
3581
  await engine.pluginManager.register(e => {
3576
3582
  e.pluginManager.addParticleUpdater("size", container => {
3577
3583
  return Promise.resolve(new SizeUpdater(container));
@@ -3580,7 +3586,7 @@
3580
3586
  }
3581
3587
 
3582
3588
  async function loadBasic(engine) {
3583
- engine.checkVersion("4.0.0-beta.16");
3589
+ engine.checkVersion("4.0.0");
3584
3590
  await engine.pluginManager.register(async (e) => {
3585
3591
  await Promise.all([
3586
3592
  loadHexColorPlugin(e),
@@ -3864,7 +3870,7 @@
3864
3870
  })(EmitterClickMode || (EmitterClickMode = {}));
3865
3871
 
3866
3872
  async function loadEmittersPluginSimple(engine) {
3867
- engine.checkVersion("4.0.0-beta.16");
3873
+ engine.checkVersion("4.0.0");
3868
3874
  await engine.pluginManager.register(async (e) => {
3869
3875
  const instancesManager = await getEmittersInstancesManager(e);
3870
3876
  await addEmittersShapesManager(e);
@@ -4242,6 +4248,25 @@
4242
4248
  };
4243
4249
  }
4244
4250
 
4251
+ const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
4252
+ const transferredCanvas = transferredCanvases.get(canvas);
4253
+ if (transferredCanvas) {
4254
+ return transferredCanvas;
4255
+ }
4256
+ if (typeof canvas.transferControlToOffscreen !== "function") {
4257
+ throw new TypeError("OffscreenCanvas is required but not supported by this browser");
4258
+ }
4259
+ try {
4260
+ const offscreenCanvas = canvas.transferControlToOffscreen();
4261
+ transferredCanvases.set(canvas, offscreenCanvas);
4262
+ return offscreenCanvas;
4263
+ }
4264
+ catch {
4265
+ throw new TypeError("OffscreenCanvas transfer failed");
4266
+ }
4267
+ }, isHtmlCanvasElement = (canvas) => {
4268
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
4269
+ };
4245
4270
  function setStyle(canvas, style, important = false) {
4246
4271
  if (!style) {
4247
4272
  return;
@@ -4272,8 +4297,9 @@
4272
4297
  }
4273
4298
  }
4274
4299
  class CanvasManager {
4275
- element;
4300
+ domElement;
4276
4301
  render;
4302
+ renderCanvas;
4277
4303
  size;
4278
4304
  zoom = defaultZoom;
4279
4305
  _container;
@@ -4308,9 +4334,10 @@
4308
4334
  destroy() {
4309
4335
  this.stop();
4310
4336
  if (this._generated) {
4311
- const element = this.element;
4337
+ const element = this.domElement;
4312
4338
  element?.remove();
4313
- this.element = undefined;
4339
+ this.domElement = undefined;
4340
+ this.renderCanvas = undefined;
4314
4341
  }
4315
4342
  else {
4316
4343
  this._resetOriginalStyle();
@@ -4343,16 +4370,17 @@
4343
4370
  this._initStyle();
4344
4371
  this.initBackground();
4345
4372
  this._safeMutationObserver(obs => {
4346
- if (!this.element || !(this.element instanceof Node)) {
4373
+ const element = this.domElement;
4374
+ if (!element || !(element instanceof Node)) {
4347
4375
  return;
4348
4376
  }
4349
- obs.observe(this.element, { attributes: true });
4377
+ obs.observe(element, { attributes: true });
4350
4378
  });
4351
4379
  this.initPlugins();
4352
4380
  this.render.init();
4353
4381
  }
4354
4382
  initBackground() {
4355
- const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
4383
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.domElement;
4356
4384
  if (!element) {
4357
4385
  return;
4358
4386
  }
@@ -4377,21 +4405,30 @@
4377
4405
  }
4378
4406
  }
4379
4407
  loadCanvas(canvas) {
4380
- if (this._generated && this.element) {
4381
- this.element.remove();
4408
+ if (this._generated && this.domElement) {
4409
+ this.domElement.remove();
4410
+ }
4411
+ const container = this._container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
4412
+ this.domElement = domCanvas;
4413
+ this._generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
4414
+ this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
4415
+ const domElement = this.domElement;
4416
+ if (domElement) {
4417
+ domElement.ariaHidden = "true";
4418
+ this._originalStyle = cloneStyle(domElement.style);
4419
+ }
4420
+ const standardSize = this._standardSize, renderCanvas = this.renderCanvas;
4421
+ if (domElement) {
4422
+ standardSize.height = domElement.offsetHeight;
4423
+ standardSize.width = domElement.offsetWidth;
4424
+ }
4425
+ else {
4426
+ standardSize.height = renderCanvas.height;
4427
+ standardSize.width = renderCanvas.width;
4382
4428
  }
4383
- const container = this._container;
4384
- this._generated =
4385
- generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
4386
- this.element = canvas;
4387
- this.element.ariaHidden = "true";
4388
- this._originalStyle = cloneStyle(this.element.style);
4389
- const standardSize = this._standardSize;
4390
- standardSize.height = canvas.offsetHeight;
4391
- standardSize.width = canvas.offsetWidth;
4392
4429
  const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
4393
- canvas.height = retinaSize.height = standardSize.height * pxRatio;
4394
- canvas.width = retinaSize.width = standardSize.width * pxRatio;
4430
+ renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
4431
+ renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
4395
4432
  const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
4396
4433
  this.render.setContextSettings({
4397
4434
  alpha: true,
@@ -4399,42 +4436,48 @@
4399
4436
  desynchronized: true,
4400
4437
  willReadFrequently: false,
4401
4438
  });
4402
- this.render.setContext(this.element.getContext("2d", this.render.settings));
4439
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4403
4440
  this._safeMutationObserver(obs => {
4404
4441
  obs.disconnect();
4405
4442
  });
4406
4443
  container.retina.init();
4407
4444
  this.initBackground();
4408
4445
  this._safeMutationObserver(obs => {
4409
- if (!this.element || !(this.element instanceof Node)) {
4446
+ const element = this.domElement;
4447
+ if (!element || !(element instanceof Node)) {
4410
4448
  return;
4411
4449
  }
4412
- obs.observe(this.element, { attributes: true });
4450
+ obs.observe(element, { attributes: true });
4413
4451
  });
4414
4452
  }
4415
4453
  resize() {
4416
- if (!this.element) {
4454
+ const element = this.domElement;
4455
+ if (!element) {
4456
+ return false;
4457
+ }
4458
+ const container = this._container, renderCanvas = this.renderCanvas;
4459
+ if (renderCanvas === undefined) {
4417
4460
  return false;
4418
4461
  }
4419
- const container = this._container, currentSize = container.canvas._standardSize, newSize = {
4420
- width: this.element.offsetWidth,
4421
- height: this.element.offsetHeight,
4462
+ const currentSize = container.canvas._standardSize, newSize = {
4463
+ width: element.offsetWidth,
4464
+ height: element.offsetHeight,
4422
4465
  }, pxRatio = container.retina.pixelRatio, retinaSize = {
4423
4466
  width: newSize.width * pxRatio,
4424
4467
  height: newSize.height * pxRatio,
4425
4468
  };
4426
4469
  if (newSize.height === currentSize.height &&
4427
4470
  newSize.width === currentSize.width &&
4428
- retinaSize.height === this.element.height &&
4429
- retinaSize.width === this.element.width) {
4471
+ retinaSize.height === renderCanvas.height &&
4472
+ retinaSize.width === renderCanvas.width) {
4430
4473
  return false;
4431
4474
  }
4432
4475
  const oldSize = { ...currentSize };
4433
4476
  currentSize.height = newSize.height;
4434
4477
  currentSize.width = newSize.width;
4435
4478
  const canvasSize = this.size;
4436
- this.element.width = canvasSize.width = retinaSize.width;
4437
- this.element.height = canvasSize.height = retinaSize.height;
4479
+ renderCanvas.width = canvasSize.width = retinaSize.width;
4480
+ renderCanvas.height = canvasSize.height = retinaSize.height;
4438
4481
  if (this._container.started) {
4439
4482
  container.particles.setResizeFactor({
4440
4483
  width: currentSize.width / oldSize.width,
@@ -4444,7 +4487,7 @@
4444
4487
  return true;
4445
4488
  }
4446
4489
  setPointerEvents(type) {
4447
- const element = this.element;
4490
+ const element = this.domElement;
4448
4491
  if (!element) {
4449
4492
  return;
4450
4493
  }
@@ -4463,7 +4506,7 @@
4463
4506
  this.render.stop();
4464
4507
  }
4465
4508
  async windowResize() {
4466
- if (!this.element || !this.resize()) {
4509
+ if (!this.domElement || !this.resize()) {
4467
4510
  return;
4468
4511
  }
4469
4512
  const container = this._container, needsRefresh = container.updateActualOptions();
@@ -4479,7 +4522,7 @@
4479
4522
  }
4480
4523
  };
4481
4524
  _initStyle = () => {
4482
- const element = this.element, options = this._container.actualOptions;
4525
+ const element = this.domElement, options = this._container.actualOptions;
4483
4526
  if (!element) {
4484
4527
  return;
4485
4528
  }
@@ -4501,7 +4544,7 @@
4501
4544
  }
4502
4545
  };
4503
4546
  _repairStyle = () => {
4504
- const element = this.element;
4547
+ const element = this.domElement;
4505
4548
  if (!element) {
4506
4549
  return;
4507
4550
  }
@@ -4521,7 +4564,7 @@
4521
4564
  });
4522
4565
  };
4523
4566
  _resetOriginalStyle = () => {
4524
- const element = this.element, originalStyle = this._originalStyle;
4567
+ const element = this.domElement, originalStyle = this._originalStyle;
4525
4568
  if (!element || !originalStyle) {
4526
4569
  return;
4527
4570
  }
@@ -4534,7 +4577,7 @@
4534
4577
  callback(this._mutationObserver);
4535
4578
  };
4536
4579
  _setFullScreenStyle = () => {
4537
- const element = this.element;
4580
+ const element = this.domElement;
4538
4581
  if (!element) {
4539
4582
  return;
4540
4583
  }
@@ -4608,7 +4651,7 @@
4608
4651
  manageListener(globalThis, resizeEvent, handlers.resize, add);
4609
4652
  return;
4610
4653
  }
4611
- const canvasEl = container.canvas.element;
4654
+ const canvasEl = container.canvas.domElement;
4612
4655
  if (this._resizeObserver && !add) {
4613
4656
  if (canvasEl) {
4614
4657
  this._resizeObserver.unobserve(canvasEl);
@@ -4863,8 +4906,6 @@
4863
4906
  this._initPosition(position);
4864
4907
  this.initialVelocity = this._calculateVelocity();
4865
4908
  this.velocity = this.initialVelocity.copy();
4866
- const particles = container.particles;
4867
- particles.setLastZIndex(this.position.z);
4868
4909
  this.zIndexFactor = this.position.z / container.zLayers;
4869
4910
  this.sides = 24;
4870
4911
  let effectDrawer, shapeDrawer;
@@ -5014,7 +5055,7 @@
5014
5055
  return color;
5015
5056
  };
5016
5057
  _initPosition = position => {
5017
- const container = this._container, zIndexValue = getRangeValue(this.options.zIndex.value), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5058
+ const container = this._container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5018
5059
  if (!initialPosition) {
5019
5060
  throw new Error("a valid position cannot be found for particle");
5020
5061
  }
@@ -5148,10 +5189,8 @@
5148
5189
  _container;
5149
5190
  _groupLimits;
5150
5191
  _limit;
5151
- _maxZIndex;
5152
- _minZIndex;
5153
- _needsSort;
5154
5192
  _nextId;
5193
+ _particleBuckets;
5155
5194
  _particleResetPlugins;
5156
5195
  _particleUpdatePlugins;
5157
5196
  _pluginManager;
@@ -5160,19 +5199,17 @@
5160
5199
  _postUpdatePlugins;
5161
5200
  _resizeFactor;
5162
5201
  _updatePlugins;
5163
- _zArray;
5202
+ _zBuckets;
5164
5203
  constructor(pluginManager, container) {
5165
5204
  this._pluginManager = pluginManager;
5166
5205
  this._container = container;
5167
5206
  this._nextId = 0;
5168
5207
  this._array = [];
5169
- this._zArray = [];
5170
5208
  this._pool = [];
5171
5209
  this._limit = 0;
5172
5210
  this._groupLimits = new Map();
5173
- this._needsSort = false;
5174
- this._minZIndex = 0;
5175
- this._maxZIndex = 0;
5211
+ this._particleBuckets = new Map();
5212
+ this._zBuckets = this._createBuckets(this._container.zLayers);
5176
5213
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5177
5214
  this.checkParticlePositionPlugins = [];
5178
5215
  this._particleResetPlugins = [];
@@ -5214,7 +5251,7 @@
5214
5251
  return;
5215
5252
  }
5216
5253
  this._array.push(particle);
5217
- this._zArray.push(particle);
5254
+ this._insertParticleIntoBucket(particle);
5218
5255
  this._nextId++;
5219
5256
  this._container.dispatchEvent(EventType.particleAdded, {
5220
5257
  particle,
@@ -5228,12 +5265,14 @@
5228
5265
  }
5229
5266
  clear() {
5230
5267
  this._array = [];
5231
- this._zArray = [];
5268
+ this._particleBuckets.clear();
5269
+ this._resetBuckets(this._container.zLayers);
5232
5270
  }
5233
5271
  destroy() {
5234
5272
  this._array = [];
5235
5273
  this._pool.length = 0;
5236
- this._zArray = [];
5274
+ this._particleBuckets.clear();
5275
+ this._zBuckets = [];
5237
5276
  this.checkParticlePositionPlugins = [];
5238
5277
  this._particleResetPlugins = [];
5239
5278
  this._particleUpdatePlugins = [];
@@ -5242,8 +5281,14 @@
5242
5281
  this._updatePlugins = [];
5243
5282
  }
5244
5283
  drawParticles(delta) {
5245
- for (const particle of this._zArray) {
5246
- particle.draw(delta);
5284
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
5285
+ const bucket = this._zBuckets[i];
5286
+ if (!bucket) {
5287
+ continue;
5288
+ }
5289
+ for (const particle of bucket) {
5290
+ particle.draw(delta);
5291
+ }
5247
5292
  }
5248
5293
  }
5249
5294
  filter(condition) {
@@ -5257,15 +5302,14 @@
5257
5302
  }
5258
5303
  async init() {
5259
5304
  const container = this._container, options = container.actualOptions;
5260
- this._minZIndex = 0;
5261
- this._maxZIndex = 0;
5262
- this._needsSort = false;
5263
5305
  this.checkParticlePositionPlugins = [];
5264
5306
  this._updatePlugins = [];
5265
5307
  this._particleUpdatePlugins = [];
5266
5308
  this._postUpdatePlugins = [];
5267
5309
  this._particleResetPlugins = [];
5268
5310
  this._postParticleUpdatePlugins = [];
5311
+ this._particleBuckets.clear();
5312
+ this._resetBuckets(container.zLayers);
5269
5313
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5270
5314
  for (const plugin of container.plugins) {
5271
5315
  if (plugin.redrawInit) {
@@ -5366,79 +5410,25 @@
5366
5410
  }
5367
5411
  this._applyDensity(options.particles, pluginsCount);
5368
5412
  }
5369
- setLastZIndex(zIndex) {
5370
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
5371
- }
5372
5413
  setResizeFactor(factor) {
5373
5414
  this._resizeFactor = factor;
5374
5415
  }
5375
5416
  update(delta) {
5376
- const particlesToDelete = new Set();
5377
5417
  this.grid.clear();
5378
5418
  for (const plugin of this._updatePlugins) {
5379
5419
  plugin.update?.(delta);
5380
5420
  }
5381
- const resizeFactor = this._resizeFactor;
5382
- for (const particle of this._array) {
5383
- if (resizeFactor && !particle.ignoresResizeRatio) {
5384
- particle.position.x *= resizeFactor.width;
5385
- particle.position.y *= resizeFactor.height;
5386
- particle.initialPosition.x *= resizeFactor.width;
5387
- particle.initialPosition.y *= resizeFactor.height;
5388
- }
5389
- particle.ignoresResizeRatio = false;
5390
- for (const plugin of this._particleResetPlugins) {
5391
- plugin.particleReset?.(particle);
5392
- }
5393
- for (const plugin of this._particleUpdatePlugins) {
5394
- if (particle.destroyed) {
5395
- break;
5396
- }
5397
- plugin.particleUpdate?.(particle, delta);
5398
- }
5399
- if (particle.destroyed) {
5400
- particlesToDelete.add(particle);
5401
- continue;
5402
- }
5403
- this.grid.insert(particle);
5404
- }
5421
+ const particlesToDelete = this._updateParticlesPhase1(delta);
5405
5422
  for (const plugin of this._postUpdatePlugins) {
5406
5423
  plugin.postUpdate?.(delta);
5407
5424
  }
5408
- for (const particle of this._array) {
5409
- if (particle.destroyed) {
5410
- particlesToDelete.add(particle);
5411
- continue;
5412
- }
5413
- for (const updater of this._container.particleUpdaters) {
5414
- updater.update(particle, delta);
5415
- }
5416
- if (!particle.destroyed && !particle.spawning) {
5417
- for (const plugin of this._postParticleUpdatePlugins) {
5418
- plugin.postParticleUpdate?.(particle, delta);
5419
- }
5420
- }
5421
- else if (particle.destroyed) {
5422
- particlesToDelete.add(particle);
5423
- }
5424
- }
5425
+ this._updateParticlesPhase2(delta, particlesToDelete);
5425
5426
  if (particlesToDelete.size) {
5426
5427
  for (const particle of particlesToDelete) {
5427
5428
  this.remove(particle);
5428
5429
  }
5429
5430
  }
5430
5431
  delete this._resizeFactor;
5431
- if (this._needsSort) {
5432
- const zArray = this._zArray;
5433
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
5434
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
5435
- if (!firstItem || !lastItem) {
5436
- return;
5437
- }
5438
- this._maxZIndex = firstItem.position.z;
5439
- this._minZIndex = lastItem.position.z;
5440
- this._needsSort = false;
5441
- }
5442
5432
  }
5443
5433
  _addToPool = (...particles) => {
5444
5434
  this._pool.push(...particles);
@@ -5468,13 +5458,52 @@
5468
5458
  this.removeQuantity(particlesCount - particlesNumber, group);
5469
5459
  }
5470
5460
  };
5461
+ _createBuckets = (zLayers) => {
5462
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5463
+ return Array.from({ length: bucketCount }, () => []);
5464
+ };
5465
+ _getBucketIndex = (zIndex) => {
5466
+ const maxBucketIndex = this._zBuckets.length - one;
5467
+ if (maxBucketIndex <= minIndex) {
5468
+ return minIndex;
5469
+ }
5470
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
5471
+ };
5472
+ _getParticleInsertIndex = (bucket, particleId) => {
5473
+ let start = minIndex, end = bucket.length;
5474
+ while (start < end) {
5475
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
5476
+ if (!middleParticle) {
5477
+ end = middle;
5478
+ continue;
5479
+ }
5480
+ if (middleParticle.id < particleId) {
5481
+ start = middle + one;
5482
+ }
5483
+ else {
5484
+ end = middle;
5485
+ }
5486
+ }
5487
+ return start;
5488
+ };
5471
5489
  _initDensityFactor = densityOptions => {
5472
5490
  const container = this._container;
5473
- if (!container.canvas.element || !densityOptions.enable) {
5491
+ if (!densityOptions.enable) {
5492
+ return defaultDensityFactor;
5493
+ }
5494
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
5495
+ if (!canvasSize.width || !canvasSize.height) {
5474
5496
  return defaultDensityFactor;
5475
5497
  }
5476
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
5477
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
5498
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5499
+ };
5500
+ _insertParticleIntoBucket = (particle) => {
5501
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5502
+ if (!bucket) {
5503
+ return;
5504
+ }
5505
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
5506
+ this._particleBuckets.set(particle.id, bucketIndex);
5478
5507
  };
5479
5508
  _removeParticle = (index, group, override) => {
5480
5509
  const particle = this._array[index];
@@ -5484,9 +5513,8 @@
5484
5513
  if (particle.group !== group) {
5485
5514
  return false;
5486
5515
  }
5487
- const zIdx = this._zArray.indexOf(particle);
5488
5516
  this._array.splice(index, deleteCount);
5489
- this._zArray.splice(zIdx, deleteCount);
5517
+ this._removeParticleFromBucket(particle);
5490
5518
  particle.destroy(override);
5491
5519
  this._container.dispatchEvent(EventType.particleRemoved, {
5492
5520
  particle,
@@ -5494,6 +5522,98 @@
5494
5522
  this._addToPool(particle);
5495
5523
  return true;
5496
5524
  };
5525
+ _removeParticleFromBucket = (particle) => {
5526
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
5527
+ if (!bucket) {
5528
+ this._particleBuckets.delete(particle.id);
5529
+ return;
5530
+ }
5531
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
5532
+ if (bucket[particleIndex]?.id !== particle.id) {
5533
+ this._particleBuckets.delete(particle.id);
5534
+ return;
5535
+ }
5536
+ bucket.splice(particleIndex, deleteCount);
5537
+ this._particleBuckets.delete(particle.id);
5538
+ };
5539
+ _resetBuckets = (zLayers) => {
5540
+ const bucketCount = Math.max(Math.floor(zLayers), one);
5541
+ if (this._zBuckets.length !== bucketCount) {
5542
+ this._zBuckets = this._createBuckets(bucketCount);
5543
+ return;
5544
+ }
5545
+ for (const bucket of this._zBuckets) {
5546
+ bucket.length = minIndex;
5547
+ }
5548
+ };
5549
+ _updateParticleBucket = (particle) => {
5550
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
5551
+ if (currentBucketIndex === undefined) {
5552
+ this._insertParticleIntoBucket(particle);
5553
+ return;
5554
+ }
5555
+ if (currentBucketIndex === newBucketIndex) {
5556
+ return;
5557
+ }
5558
+ const currentBucket = this._zBuckets[currentBucketIndex];
5559
+ if (currentBucket) {
5560
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
5561
+ if (currentBucket[particleIndex]?.id === particle.id) {
5562
+ currentBucket.splice(particleIndex, deleteCount);
5563
+ }
5564
+ }
5565
+ const newBucket = this._zBuckets[newBucketIndex];
5566
+ if (!newBucket) {
5567
+ this._particleBuckets.set(particle.id, newBucketIndex);
5568
+ return;
5569
+ }
5570
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
5571
+ this._particleBuckets.set(particle.id, newBucketIndex);
5572
+ };
5573
+ _updateParticlesPhase1 = (delta) => {
5574
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
5575
+ for (const particle of this._array) {
5576
+ if (resizeFactor && !particle.ignoresResizeRatio) {
5577
+ particle.position.x *= resizeFactor.width;
5578
+ particle.position.y *= resizeFactor.height;
5579
+ particle.initialPosition.x *= resizeFactor.width;
5580
+ particle.initialPosition.y *= resizeFactor.height;
5581
+ }
5582
+ particle.ignoresResizeRatio = false;
5583
+ for (const plugin of this._particleResetPlugins) {
5584
+ plugin.particleReset?.(particle);
5585
+ }
5586
+ for (const plugin of this._particleUpdatePlugins) {
5587
+ if (particle.destroyed) {
5588
+ break;
5589
+ }
5590
+ plugin.particleUpdate?.(particle, delta);
5591
+ }
5592
+ if (particle.destroyed) {
5593
+ particlesToDelete.add(particle);
5594
+ continue;
5595
+ }
5596
+ this.grid.insert(particle);
5597
+ }
5598
+ return particlesToDelete;
5599
+ };
5600
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
5601
+ for (const particle of this._array) {
5602
+ if (particle.destroyed) {
5603
+ particlesToDelete.add(particle);
5604
+ continue;
5605
+ }
5606
+ for (const updater of this._container.particleUpdaters) {
5607
+ updater.update(particle, delta);
5608
+ }
5609
+ if (!particle.spawning) {
5610
+ for (const plugin of this._postParticleUpdatePlugins) {
5611
+ plugin.postParticleUpdate?.(particle, delta);
5612
+ }
5613
+ }
5614
+ this._updateParticleBucket(particle);
5615
+ }
5616
+ };
5497
5617
  }
5498
5618
 
5499
5619
  class Retina {
@@ -5509,9 +5629,8 @@
5509
5629
  const container = this.container, options = container.actualOptions;
5510
5630
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
5511
5631
  this.reduceFactor = defaultReduceFactor;
5512
- const ratio = this.pixelRatio, canvas = container.canvas;
5513
- if (canvas.element) {
5514
- const element = canvas.element;
5632
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
5633
+ if (element) {
5515
5634
  canvas.size.width = element.offsetWidth * ratio;
5516
5635
  canvas.size.height = element.offsetHeight * ratio;
5517
5636
  }