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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* tsParticles v4.0.0-beta.16 */
2
+ /* tsParticles v4.0.0-beta.17 */
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
5
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -1081,7 +1081,7 @@
1081
1081
  }
1082
1082
  }
1083
1083
  else {
1084
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases[canvasFirstIndex];
1084
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
1085
1085
  if (foundCanvas) {
1086
1086
  canvasEl = foundCanvas;
1087
1087
  canvasEl.dataset[generatedAttribute] = generatedFalse;
@@ -1118,7 +1118,7 @@
1118
1118
  return this._domArray;
1119
1119
  }
1120
1120
  get version() {
1121
- return "4.0.0-beta.16";
1121
+ return "4.0.0-beta.17";
1122
1122
  }
1123
1123
  addEventListener(type, listener) {
1124
1124
  this._eventDispatcher.addEventListener(type, listener);
@@ -1149,7 +1149,11 @@
1149
1149
  }
1150
1150
  async load(params) {
1151
1151
  await this.init();
1152
- const { Container } = await Promise.resolve().then(function () { return Container$1; }), id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor).toString()}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container({
1152
+ let domSourceElement;
1153
+ if (typeof HTMLElement !== "undefined" && params.element instanceof HTMLElement) {
1154
+ domSourceElement = params.element;
1155
+ }
1156
+ const { Container } = await Promise.resolve().then(function () { return Container$1; }), id = params.id ?? domSourceElement?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor).toString()}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container({
1153
1157
  dispatchCallback: (eventType, args) => {
1154
1158
  this.dispatchEvent(eventType, args);
1155
1159
  },
@@ -1176,8 +1180,10 @@
1176
1180
  else {
1177
1181
  items.push(newItem);
1178
1182
  }
1179
- const domContainer = getDomContainer(id, params.element), canvasEl = getCanvasFromContainer(domContainer);
1180
- newItem.canvas.loadCanvas(canvasEl);
1183
+ const sourceCanvas = typeof OffscreenCanvas !== "undefined" && params.element instanceof OffscreenCanvas
1184
+ ? params.element
1185
+ : getCanvasFromContainer(getDomContainer(id, domSourceElement));
1186
+ newItem.canvas.loadCanvas(sourceCanvas);
1181
1187
  await newItem.start();
1182
1188
  return newItem;
1183
1189
  }
@@ -3618,7 +3624,7 @@
3618
3624
  }
3619
3625
 
3620
3626
  async function loadInteractivityPlugin(engine) {
3621
- engine.checkVersion("4.0.0-beta.16");
3627
+ engine.checkVersion("4.0.0-beta.17");
3622
3628
  await engine.pluginManager.register(e => {
3623
3629
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3624
3630
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3892,7 +3898,7 @@
3892
3898
  }
3893
3899
 
3894
3900
  async function loadAbsorbersInteraction(engine) {
3895
- engine.checkVersion("4.0.0-beta.16");
3901
+ engine.checkVersion("4.0.0-beta.17");
3896
3902
  await engine.pluginManager.register(async (e) => {
3897
3903
  const pluginManager = e.pluginManager, instancesManager = await getAbsorbersInstancesManager(e);
3898
3904
  ensureInteractivityPluginLoaded(e);
@@ -3940,7 +3946,7 @@
3940
3946
  }
3941
3947
 
3942
3948
  async function loadAbsorbersPluginSimple(engine) {
3943
- engine.checkVersion("4.0.0-beta.16");
3949
+ engine.checkVersion("4.0.0-beta.17");
3944
3950
  await engine.pluginManager.register(async (e) => {
3945
3951
  const pluginManager = e.pluginManager, instancesManager = await getAbsorbersInstancesManager(e);
3946
3952
  pluginManager.addPlugin(new AbsorbersPlugin(instancesManager));
@@ -4305,7 +4311,7 @@
4305
4311
  }
4306
4312
 
4307
4313
  async function loadDestroyUpdater(engine) {
4308
- engine.checkVersion("4.0.0-beta.16");
4314
+ engine.checkVersion("4.0.0-beta.17");
4309
4315
  await engine.pluginManager.register(e => {
4310
4316
  e.pluginManager.addParticleUpdater("destroy", container => {
4311
4317
  return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
@@ -4685,7 +4691,7 @@
4685
4691
  })(EmitterClickMode || (EmitterClickMode = {}));
4686
4692
 
4687
4693
  async function loadEmittersInteraction(engine) {
4688
- engine.checkVersion("4.0.0-beta.16");
4694
+ engine.checkVersion("4.0.0-beta.17");
4689
4695
  await engine.pluginManager.register(async (e) => {
4690
4696
  const instancesManager = await getEmittersInstancesManager(e);
4691
4697
  ensureInteractivityPluginLoaded(e);
@@ -4728,7 +4734,7 @@
4728
4734
  }
4729
4735
 
4730
4736
  async function loadEmittersPluginSimple(engine) {
4731
- engine.checkVersion("4.0.0-beta.16");
4737
+ engine.checkVersion("4.0.0-beta.17");
4732
4738
  await engine.pluginManager.register(async (e) => {
4733
4739
  const instancesManager = await getEmittersInstancesManager(e);
4734
4740
  await addEmittersShapesManager(e);
@@ -4786,7 +4792,7 @@
4786
4792
  }
4787
4793
 
4788
4794
  async function loadEmittersShapeCircle(engine) {
4789
- engine.checkVersion("4.0.0-beta.16");
4795
+ engine.checkVersion("4.0.0-beta.17");
4790
4796
  await engine.pluginManager.register((e) => {
4791
4797
  ensureEmittersPluginLoaded(e);
4792
4798
  e.pluginManager.addEmitterShapeGenerator?.("circle", new EmittersCircleShapeGenerator());
@@ -4867,7 +4873,7 @@
4867
4873
  }
4868
4874
 
4869
4875
  async function loadEmittersShapeSquare(engine) {
4870
- engine.checkVersion("4.0.0-beta.16");
4876
+ engine.checkVersion("4.0.0-beta.17");
4871
4877
  await engine.pluginManager.register((e) => {
4872
4878
  ensureEmittersPluginLoaded(e);
4873
4879
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -5060,7 +5066,7 @@
5060
5066
  }
5061
5067
 
5062
5068
  async function loadExternalDragInteraction(engine) {
5063
- engine.checkVersion("4.0.0-beta.16");
5069
+ engine.checkVersion("4.0.0-beta.17");
5064
5070
  await engine.pluginManager.register((e) => {
5065
5071
  ensureInteractivityPluginLoaded(e);
5066
5072
  e.pluginManager.addInteractor?.("externalDrag", container => {
@@ -5264,7 +5270,7 @@
5264
5270
  }
5265
5271
 
5266
5272
  async function loadExternalTrailInteraction(engine) {
5267
- engine.checkVersion("4.0.0-beta.16");
5273
+ engine.checkVersion("4.0.0-beta.17");
5268
5274
  await engine.pluginManager.register((e) => {
5269
5275
  ensureInteractivityPluginLoaded(e);
5270
5276
  e.pluginManager.addInteractor?.("externalTrail", container => {
@@ -5424,7 +5430,7 @@
5424
5430
  }
5425
5431
 
5426
5432
  async function loadRollUpdater(engine) {
5427
- engine.checkVersion("4.0.0-beta.16");
5433
+ engine.checkVersion("4.0.0-beta.17");
5428
5434
  await engine.pluginManager.register(e => {
5429
5435
  e.pluginManager.addParticleUpdater("roll", () => {
5430
5436
  return Promise.resolve(new RollUpdater(e.pluginManager));
@@ -5463,7 +5469,7 @@
5463
5469
  }
5464
5470
 
5465
5471
  async function loadCircleShape(engine) {
5466
- engine.checkVersion("4.0.0-beta.16");
5472
+ engine.checkVersion("4.0.0-beta.17");
5467
5473
  await engine.pluginManager.register(e => {
5468
5474
  e.pluginManager.addShape(["circle"], () => {
5469
5475
  return Promise.resolve(new CircleDrawer());
@@ -5511,7 +5517,7 @@
5511
5517
  }
5512
5518
 
5513
5519
  async function loadHexColorPlugin(engine) {
5514
- engine.checkVersion("4.0.0-beta.16");
5520
+ engine.checkVersion("4.0.0-beta.17");
5515
5521
  await engine.pluginManager.register(e => {
5516
5522
  e.pluginManager.addColorManager("hex", new HexColorManager());
5517
5523
  });
@@ -5564,7 +5570,7 @@
5564
5570
  }
5565
5571
 
5566
5572
  async function loadHslColorPlugin(engine) {
5567
- engine.checkVersion("4.0.0-beta.16");
5573
+ engine.checkVersion("4.0.0-beta.17");
5568
5574
  await engine.pluginManager.register(e => {
5569
5575
  e.pluginManager.addColorManager("hsl", new HslColorManager());
5570
5576
  });
@@ -5588,7 +5594,7 @@
5588
5594
  }
5589
5595
 
5590
5596
  async function loadMovePlugin(engine) {
5591
- engine.checkVersion("4.0.0-beta.16");
5597
+ engine.checkVersion("4.0.0-beta.17");
5592
5598
  await engine.pluginManager.register(e => {
5593
5599
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
5594
5600
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -5649,7 +5655,7 @@
5649
5655
  }
5650
5656
 
5651
5657
  async function loadOpacityUpdater(engine) {
5652
- engine.checkVersion("4.0.0-beta.16");
5658
+ engine.checkVersion("4.0.0-beta.17");
5653
5659
  await engine.pluginManager.register(e => {
5654
5660
  e.pluginManager.addParticleUpdater("opacity", container => {
5655
5661
  return Promise.resolve(new OpacityUpdater(container));
@@ -6001,7 +6007,7 @@
6001
6007
  }
6002
6008
 
6003
6009
  async function loadOutModesUpdater(engine) {
6004
- engine.checkVersion("4.0.0-beta.16");
6010
+ engine.checkVersion("4.0.0-beta.17");
6005
6011
  await engine.pluginManager.register(e => {
6006
6012
  e.pluginManager.addParticleUpdater("outModes", container => {
6007
6013
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -6072,7 +6078,7 @@
6072
6078
  }
6073
6079
 
6074
6080
  async function loadPaintUpdater(engine) {
6075
- engine.checkVersion("4.0.0-beta.16");
6081
+ engine.checkVersion("4.0.0-beta.17");
6076
6082
  await engine.pluginManager.register(e => {
6077
6083
  e.pluginManager.addParticleUpdater("paint", container => {
6078
6084
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -6127,7 +6133,7 @@
6127
6133
  }
6128
6134
 
6129
6135
  async function loadRgbColorPlugin(engine) {
6130
- engine.checkVersion("4.0.0-beta.16");
6136
+ engine.checkVersion("4.0.0-beta.17");
6131
6137
  await engine.pluginManager.register(e => {
6132
6138
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
6133
6139
  });
@@ -6170,7 +6176,7 @@
6170
6176
  }
6171
6177
 
6172
6178
  async function loadSizeUpdater(engine) {
6173
- engine.checkVersion("4.0.0-beta.16");
6179
+ engine.checkVersion("4.0.0-beta.17");
6174
6180
  await engine.pluginManager.register(e => {
6175
6181
  e.pluginManager.addParticleUpdater("size", container => {
6176
6182
  return Promise.resolve(new SizeUpdater(container));
@@ -6179,7 +6185,7 @@
6179
6185
  }
6180
6186
 
6181
6187
  async function loadBasic(engine) {
6182
- engine.checkVersion("4.0.0-beta.16");
6188
+ engine.checkVersion("4.0.0-beta.17");
6183
6189
  await engine.pluginManager.register(async (e) => {
6184
6190
  await Promise.all([
6185
6191
  loadHexColorPlugin(e),
@@ -6201,7 +6207,7 @@
6201
6207
  easingsFunctions.set(exports.EasingType.easeInOutQuad, value => (value < 0.5 ? 2 * value ** 2 : 1 - (-2 * value + 2) ** 2 / 2));
6202
6208
 
6203
6209
  async function loadEasingQuadPlugin(engine) {
6204
- engine.checkVersion("4.0.0-beta.16");
6210
+ engine.checkVersion("4.0.0-beta.17");
6205
6211
  await engine.pluginManager.register(e => {
6206
6212
  for (const [easing, easingFn] of easingsFunctions) {
6207
6213
  e.pluginManager.addEasing(easing, easingFn);
@@ -6294,19 +6300,7 @@
6294
6300
  particle.emojiDataKey = cacheKey;
6295
6301
  return;
6296
6302
  }
6297
- const padding = emojiOptions.padding * double, maxSize = getRangeMax(particle.size.value), fullSize = maxSize + padding, canvasSize = fullSize * double;
6298
- let cacheCanvas, context;
6299
- if (typeof OffscreenCanvas === "undefined") {
6300
- const canvas = safeDocument().createElement("canvas");
6301
- canvas.width = canvasSize;
6302
- canvas.height = canvasSize;
6303
- context = canvas.getContext("2d", container.canvas.render.settings);
6304
- cacheCanvas = canvas;
6305
- }
6306
- else {
6307
- cacheCanvas = new OffscreenCanvas(canvasSize, canvasSize);
6308
- context = cacheCanvas.getContext("2d", container.canvas.render.settings);
6309
- }
6303
+ const padding = emojiOptions.padding * double, maxSize = getRangeMax(particle.size.value), fullSize = maxSize + padding, canvasSize = fullSize * double, cacheCanvas = new OffscreenCanvas(canvasSize, canvasSize), context = cacheCanvas.getContext("2d", container.canvas.render.settings);
6310
6304
  if (!context) {
6311
6305
  return;
6312
6306
  }
@@ -6321,14 +6315,14 @@
6321
6315
  }
6322
6316
 
6323
6317
  async function loadEmojiShape(engine) {
6324
- engine.checkVersion("4.0.0-beta.16");
6318
+ engine.checkVersion("4.0.0-beta.17");
6325
6319
  await engine.pluginManager.register(e => {
6326
6320
  e.pluginManager.addShape(validTypes$1, () => Promise.resolve(new EmojiDrawer()));
6327
6321
  });
6328
6322
  }
6329
6323
 
6330
6324
  const minFactor = 1, minRadius$5 = 0, updateVector = Vector.origin;
6331
- function processAttract(pluginManager, container, position, attractRadius, area, queryCb) {
6325
+ function processAttract(pluginManager, container, position, attractRadius, area, queryCb, onAttractParticle) {
6332
6326
  const attractOptions = container.actualOptions.interactivity?.modes.attract;
6333
6327
  if (!attractOptions) {
6334
6328
  return;
@@ -6338,10 +6332,11 @@
6338
6332
  const { dx, dy, distance } = getDistances(particle.position, position), velocity = attractOptions.speed * attractOptions.factor, attractFactor = clamp(pluginManager.getEasing(attractOptions.easing)(identity$3 - distance / attractRadius) * velocity, minFactor, attractOptions.maxSpeed);
6339
6333
  updateVector.x = !distance ? velocity : (dx / distance) * attractFactor;
6340
6334
  updateVector.y = !distance ? velocity : (dy / distance) * attractFactor;
6335
+ onAttractParticle?.(particle);
6341
6336
  particle.position.subFrom(updateVector);
6342
6337
  }
6343
6338
  }
6344
- function clickAttract(pluginManager, container, interactivityData, enabledCb) {
6339
+ function clickAttract(pluginManager, container, interactivityData, enabledCb, onAttractParticle) {
6345
6340
  container.attract ??= { particles: [] };
6346
6341
  const { attract } = container;
6347
6342
  if (!attract.finish) {
@@ -6356,18 +6351,18 @@
6356
6351
  if (!attractRadius || attractRadius < minRadius$5 || !mousePos) {
6357
6352
  return;
6358
6353
  }
6359
- processAttract(pluginManager, container, mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius), (p) => enabledCb(p));
6354
+ processAttract(pluginManager, container, mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius), (p) => enabledCb(p), onAttractParticle);
6360
6355
  }
6361
6356
  else if (attract.clicking === false) {
6362
6357
  attract.particles = [];
6363
6358
  }
6364
6359
  }
6365
- function hoverAttract(pluginManager, container, interactivityData, enabledCb) {
6360
+ function hoverAttract(pluginManager, container, interactivityData, enabledCb, onAttractParticle) {
6366
6361
  const mousePos = interactivityData.mouse.position, attractRadius = container.retina.attractModeDistance;
6367
6362
  if (!attractRadius || attractRadius < minRadius$5 || !mousePos) {
6368
6363
  return;
6369
6364
  }
6370
- processAttract(pluginManager, container, mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius), (p) => enabledCb(p));
6365
+ processAttract(pluginManager, container, mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius), (p) => enabledCb(p), onAttractParticle);
6371
6366
  }
6372
6367
 
6373
6368
  let Attract$1 = class Attract {
@@ -6376,6 +6371,7 @@
6376
6371
  easing;
6377
6372
  factor;
6378
6373
  maxSpeed;
6374
+ restore;
6379
6375
  speed;
6380
6376
  constructor() {
6381
6377
  this.distance = 200;
@@ -6384,6 +6380,12 @@
6384
6380
  this.factor = 1;
6385
6381
  this.maxSpeed = 50;
6386
6382
  this.speed = 1;
6383
+ this.restore = {
6384
+ enable: false,
6385
+ delay: 0,
6386
+ speed: 0.08,
6387
+ follow: true,
6388
+ };
6387
6389
  }
6388
6390
  load(data) {
6389
6391
  if (isNull(data)) {
@@ -6407,18 +6409,28 @@
6407
6409
  if (data.speed !== undefined) {
6408
6410
  this.speed = data.speed;
6409
6411
  }
6412
+ if (data.restore !== undefined) {
6413
+ this.restore.enable = data.restore.enable ?? this.restore.enable;
6414
+ this.restore.delay = data.restore.delay ?? this.restore.delay;
6415
+ this.restore.speed = data.restore.speed ?? this.restore.speed;
6416
+ this.restore.follow = data.restore.follow ?? this.restore.follow;
6417
+ }
6410
6418
  }
6411
6419
  };
6412
6420
 
6413
- const attractMode = "attract";
6421
+ const attractMode = "attract", minVelocityLengthSq = 0, minRestoreSpeed$1 = 0.001, maxRestoreSpeed$1 = 1, restoreEpsilon$1 = 0.5;
6414
6422
  let Attractor$1 = class Attractor extends ExternalInteractorBase {
6415
6423
  handleClickMode;
6424
+ _interactedThisFrame;
6416
6425
  _maxDistance;
6417
6426
  _pluginManager;
6427
+ _restoreData;
6418
6428
  constructor(pluginManager, container) {
6419
6429
  super(container);
6420
6430
  this._pluginManager = pluginManager;
6421
6431
  this._maxDistance = 0;
6432
+ this._interactedThisFrame = new Set();
6433
+ this._restoreData = new Map();
6422
6434
  container.attract ??= { particles: [] };
6423
6435
  this.handleClickMode = (mode, interactivityData) => {
6424
6436
  const options = this.container.actualOptions, attract = options.interactivity?.modes.attract;
@@ -6459,17 +6471,23 @@
6459
6471
  container.retina.attractModeDistance = attract.distance * container.retina.pixelRatio;
6460
6472
  }
6461
6473
  interact(interactivityData) {
6474
+ this._interactedThisFrame.clear();
6462
6475
  const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
6463
6476
  if (!events) {
6464
6477
  return;
6465
6478
  }
6466
6479
  const { enable: hoverEnabled, mode: hoverMode } = events.onHover, { enable: clickEnabled, mode: clickMode } = events.onClick;
6467
6480
  if (mouseMoveStatus && hoverEnabled && isInArray(attractMode, hoverMode)) {
6468
- hoverAttract(this._pluginManager, this.container, interactivityData, p => this.isEnabled(interactivityData, p));
6481
+ hoverAttract(this._pluginManager, this.container, interactivityData, p => this.isEnabled(interactivityData, p), p => {
6482
+ this._trackInteractedParticle(p);
6483
+ });
6469
6484
  }
6470
6485
  else if (clickEnabled && isInArray(attractMode, clickMode)) {
6471
- clickAttract(this._pluginManager, this.container, interactivityData, p => this.isEnabled(interactivityData, p));
6486
+ clickAttract(this._pluginManager, this.container, interactivityData, p => this.isEnabled(interactivityData, p), p => {
6487
+ this._trackInteractedParticle(p);
6488
+ });
6472
6489
  }
6490
+ this._restoreParticles();
6473
6491
  }
6474
6492
  isEnabled(interactivityData, particle) {
6475
6493
  const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
@@ -6487,10 +6505,67 @@
6487
6505
  }
6488
6506
  reset() {
6489
6507
  }
6508
+ _restoreParticles() {
6509
+ const restore = this.container.actualOptions.interactivity?.modes.attract?.restore;
6510
+ if (!restore?.enable || !this._restoreData.size) {
6511
+ return;
6512
+ }
6513
+ const now = Date.now(), restoreDelay = restore.delay * millisecondsToSeconds, restoreSpeed = Math.max(minRestoreSpeed$1, Math.min(maxRestoreSpeed$1, restore.speed));
6514
+ for (const [particle, restoreData] of this._restoreData) {
6515
+ if (this._interactedThisFrame.has(particle)) {
6516
+ continue;
6517
+ }
6518
+ if (particle.destroyed) {
6519
+ this._restoreData.delete(particle);
6520
+ continue;
6521
+ }
6522
+ const target = restoreData.target;
6523
+ if (now - restoreData.lastInteractionTime < restoreDelay) {
6524
+ continue;
6525
+ }
6526
+ let dx = target.x - particle.position.x, dy = target.y - particle.position.y, dz = target.z - particle.position.z;
6527
+ if (restore.follow && particle.options.move.enable) {
6528
+ const { x: vx, y: vy, z: vz } = particle.velocity, velocityLengthSq = vx * vx + vy * vy + vz * vz;
6529
+ if (velocityLengthSq > minVelocityLengthSq) {
6530
+ const parallelScale = (dx * vx + dy * vy + dz * vz) / velocityLengthSq;
6531
+ dx -= vx * parallelScale;
6532
+ dy -= vy * parallelScale;
6533
+ dz -= vz * parallelScale;
6534
+ }
6535
+ }
6536
+ particle.position.x += dx * restoreSpeed;
6537
+ particle.position.y += dy * restoreSpeed;
6538
+ particle.position.z += dz * restoreSpeed;
6539
+ if (Math.abs(dx) <= restoreEpsilon$1 && Math.abs(dy) <= restoreEpsilon$1) {
6540
+ particle.position.x = target.x;
6541
+ particle.position.y = target.y;
6542
+ particle.position.z = target.z;
6543
+ this._restoreData.delete(particle);
6544
+ continue;
6545
+ }
6546
+ }
6547
+ }
6548
+ _trackInteractedParticle(particle) {
6549
+ this._interactedThisFrame.add(particle);
6550
+ const restore = this.container.actualOptions.interactivity?.modes.attract?.restore;
6551
+ if (!restore?.enable) {
6552
+ return;
6553
+ }
6554
+ const now = Date.now();
6555
+ let restoreData = this._restoreData.get(particle);
6556
+ if (!restoreData) {
6557
+ restoreData = {
6558
+ target: particle.position.copy(),
6559
+ lastInteractionTime: now,
6560
+ };
6561
+ this._restoreData.set(particle, restoreData);
6562
+ }
6563
+ restoreData.lastInteractionTime = now;
6564
+ }
6490
6565
  };
6491
6566
 
6492
6567
  async function loadExternalAttractInteraction(engine) {
6493
- engine.checkVersion("4.0.0-beta.16");
6568
+ engine.checkVersion("4.0.0-beta.17");
6494
6569
  await engine.pluginManager.register((e) => {
6495
6570
  ensureInteractivityPluginLoaded(e);
6496
6571
  e.pluginManager.addInteractor?.("externalAttract", container => {
@@ -6687,7 +6762,7 @@
6687
6762
  }
6688
6763
 
6689
6764
  async function loadExternalBounceInteraction(engine) {
6690
- engine.checkVersion("4.0.0-beta.16");
6765
+ engine.checkVersion("4.0.0-beta.17");
6691
6766
  await engine.pluginManager.register((e) => {
6692
6767
  ensureInteractivityPluginLoaded(e);
6693
6768
  e.pluginManager.addInteractor?.("externalBounce", container => {
@@ -7067,7 +7142,7 @@
7067
7142
  }
7068
7143
 
7069
7144
  async function loadExternalBubbleInteraction(engine) {
7070
- engine.checkVersion("4.0.0-beta.16");
7145
+ engine.checkVersion("4.0.0-beta.17");
7071
7146
  await engine.pluginManager.register((e) => {
7072
7147
  ensureInteractivityPluginLoaded(e);
7073
7148
  e.pluginManager.addInteractor?.("externalBubble", container => {
@@ -7212,7 +7287,7 @@
7212
7287
  }
7213
7288
 
7214
7289
  async function loadExternalConnectInteraction(engine) {
7215
- engine.checkVersion("4.0.0-beta.16");
7290
+ engine.checkVersion("4.0.0-beta.17");
7216
7291
  await engine.pluginManager.register((e) => {
7217
7292
  ensureInteractivityPluginLoaded(e);
7218
7293
  e.pluginManager.addInteractor?.("externalConnect", container => {
@@ -7324,7 +7399,7 @@
7324
7399
  }
7325
7400
 
7326
7401
  async function loadExternalDestroyInteraction(engine) {
7327
- engine.checkVersion("4.0.0-beta.16");
7402
+ engine.checkVersion("4.0.0-beta.17");
7328
7403
  await engine.pluginManager.register((e) => {
7329
7404
  ensureInteractivityPluginLoaded(e);
7330
7405
  e.pluginManager.addInteractor?.("externalDestroy", async (container) => {
@@ -7468,7 +7543,7 @@
7468
7543
  }
7469
7544
 
7470
7545
  async function loadExternalGrabInteraction(engine) {
7471
- engine.checkVersion("4.0.0-beta.16");
7546
+ engine.checkVersion("4.0.0-beta.17");
7472
7547
  await engine.pluginManager.register((e) => {
7473
7548
  ensureInteractivityPluginLoaded(e);
7474
7549
  e.pluginManager.addInteractor?.("externalGrab", container => {
@@ -7549,7 +7624,7 @@
7549
7624
  }
7550
7625
 
7551
7626
  async function loadExternalParallaxInteraction(engine) {
7552
- engine.checkVersion("4.0.0-beta.16");
7627
+ engine.checkVersion("4.0.0-beta.17");
7553
7628
  await engine.pluginManager.register((e) => {
7554
7629
  ensureInteractivityPluginLoaded(e);
7555
7630
  e.pluginManager.addInteractor?.("externalParallax", container => {
@@ -7592,7 +7667,7 @@
7592
7667
  }
7593
7668
 
7594
7669
  async function loadExternalPauseInteraction(engine) {
7595
- engine.checkVersion("4.0.0-beta.16");
7670
+ engine.checkVersion("4.0.0-beta.17");
7596
7671
  await engine.pluginManager.register((e) => {
7597
7672
  ensureInteractivityPluginLoaded(e);
7598
7673
  e.pluginManager.addInteractor?.("externalPause", container => {
@@ -7677,7 +7752,7 @@
7677
7752
  }
7678
7753
 
7679
7754
  async function loadExternalPushInteraction(engine) {
7680
- engine.checkVersion("4.0.0-beta.16");
7755
+ engine.checkVersion("4.0.0-beta.17");
7681
7756
  await engine.pluginManager.register((e) => {
7682
7757
  ensureInteractivityPluginLoaded(e);
7683
7758
  e.pluginManager.addInteractor?.("externalPush", container => {
@@ -7740,7 +7815,7 @@
7740
7815
  }
7741
7816
 
7742
7817
  async function loadExternalRemoveInteraction(engine) {
7743
- engine.checkVersion("4.0.0-beta.16");
7818
+ engine.checkVersion("4.0.0-beta.17");
7744
7819
  await engine.pluginManager.register((e) => {
7745
7820
  ensureInteractivityPluginLoaded(e);
7746
7821
  e.pluginManager.addInteractor?.("externalRemove", container => {
@@ -7755,6 +7830,7 @@
7755
7830
  easing;
7756
7831
  factor;
7757
7832
  maxSpeed;
7833
+ restore;
7758
7834
  speed;
7759
7835
  constructor() {
7760
7836
  this.distance = 200;
@@ -7763,6 +7839,12 @@
7763
7839
  this.speed = 1;
7764
7840
  this.maxSpeed = 50;
7765
7841
  this.easing = exports.EasingType.easeOutQuad;
7842
+ this.restore = {
7843
+ enable: false,
7844
+ delay: 0,
7845
+ speed: 0.08,
7846
+ follow: true,
7847
+ };
7766
7848
  }
7767
7849
  load(data) {
7768
7850
  if (isNull(data)) {
@@ -7786,6 +7868,12 @@
7786
7868
  if (data.maxSpeed !== undefined) {
7787
7869
  this.maxSpeed = data.maxSpeed;
7788
7870
  }
7871
+ if (data.restore !== undefined) {
7872
+ this.restore.enable = data.restore.enable ?? this.restore.enable;
7873
+ this.restore.delay = data.restore.delay ?? this.restore.delay;
7874
+ this.restore.speed = data.restore.speed ?? this.restore.speed;
7875
+ this.restore.follow = data.restore.follow ?? this.restore.follow;
7876
+ }
7789
7877
  }
7790
7878
  }
7791
7879
 
@@ -7821,19 +7909,23 @@
7821
7909
  }
7822
7910
  }
7823
7911
 
7824
- const repulseMode = "repulse", minDistance$2 = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius$2 = 0, minSpeed = 0, easingOffset = 1;
7912
+ const repulseMode = "repulse", minDistance$2 = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius$2 = 0, minSpeed = 0, easingOffset = 1, minRestoreSpeed = 0.001, maxRestoreSpeed = 1, restoreEpsilon = 0.5;
7825
7913
  class Repulser extends ExternalInteractorBase {
7826
7914
  handleClickMode;
7827
7915
  _clickVec;
7916
+ _interactedThisFrame;
7828
7917
  _maxDistance;
7829
7918
  _normVec;
7830
7919
  _pluginManager;
7920
+ _restoreData;
7831
7921
  constructor(pluginManager, container) {
7832
7922
  super(container);
7833
7923
  this._pluginManager = pluginManager;
7834
7924
  this._maxDistance = 0;
7835
7925
  this._normVec = Vector.origin;
7926
+ this._interactedThisFrame = new Set();
7836
7927
  this._clickVec = Vector.origin;
7928
+ this._restoreData = new Map();
7837
7929
  container.repulse ??= { particles: [] };
7838
7930
  this.handleClickMode = (mode, interactivityData) => {
7839
7931
  const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
@@ -7874,6 +7966,7 @@
7874
7966
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
7875
7967
  }
7876
7968
  interact(interactivityData) {
7969
+ this._interactedThisFrame.clear();
7877
7970
  const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
7878
7971
  if (!events) {
7879
7972
  return;
@@ -7890,6 +7983,7 @@
7890
7983
  this._singleSelectorRepulse(interactivityData, selector, div);
7891
7984
  });
7892
7985
  }
7986
+ this._restoreParticles();
7893
7987
  }
7894
7988
  isEnabled(interactivityData, particle) {
7895
7989
  const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
@@ -7937,6 +8031,7 @@
7937
8031
  for (const particle of query) {
7938
8032
  const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
7939
8033
  if (d <= repulseRadius) {
8034
+ this._trackInteractedParticle(particle);
7940
8035
  repulse.particles.push(particle);
7941
8036
  this._clickVec.x = dx;
7942
8037
  this._clickVec.y = dy;
@@ -7969,9 +8064,46 @@
7969
8064
  const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
7970
8065
  this._normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
7971
8066
  this._normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
8067
+ this._trackInteractedParticle(particle);
7972
8068
  particle.position.addTo(this._normVec);
7973
8069
  }
7974
8070
  };
8071
+ _restoreParticles() {
8072
+ const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
8073
+ if (!restore?.enable || !this._restoreData.size) {
8074
+ return;
8075
+ }
8076
+ const now = Date.now(), restoreDelay = restore.delay * millisecondsToSeconds, restoreSpeed = Math.max(minRestoreSpeed, Math.min(maxRestoreSpeed, restore.speed));
8077
+ for (const [particle, restoreData] of this._restoreData) {
8078
+ if (this._interactedThisFrame.has(particle)) {
8079
+ continue;
8080
+ }
8081
+ if (particle.destroyed) {
8082
+ this._restoreData.delete(particle);
8083
+ continue;
8084
+ }
8085
+ const target = restoreData.target;
8086
+ if (now - restoreData.lastInteractionTime < restoreDelay) {
8087
+ continue;
8088
+ }
8089
+ if (restore.follow && particle.options.move.enable) {
8090
+ target.x += particle.velocity.x;
8091
+ target.y += particle.velocity.y;
8092
+ target.z += particle.velocity.z;
8093
+ }
8094
+ const dx = target.x - particle.position.x, dy = target.y - particle.position.y, dz = target.z - particle.position.z;
8095
+ particle.position.x += dx * restoreSpeed;
8096
+ particle.position.y += dy * restoreSpeed;
8097
+ particle.position.z += dz * restoreSpeed;
8098
+ if (Math.abs(dx) <= restoreEpsilon && Math.abs(dy) <= restoreEpsilon) {
8099
+ particle.position.x = target.x;
8100
+ particle.position.y = target.y;
8101
+ particle.position.z = target.z;
8102
+ this._restoreData.delete(particle);
8103
+ continue;
8104
+ }
8105
+ }
8106
+ }
7975
8107
  _singleSelectorRepulse = (interactivityData, selector, div) => {
7976
8108
  const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
7977
8109
  if (!repulse) {
@@ -7991,10 +8123,32 @@
7991
8123
  this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
7992
8124
  });
7993
8125
  };
8126
+ _trackInteractedParticle(particle) {
8127
+ this._interactedThisFrame.add(particle);
8128
+ const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
8129
+ if (!restore?.enable) {
8130
+ return;
8131
+ }
8132
+ const now = Date.now();
8133
+ let restoreData = this._restoreData.get(particle);
8134
+ if (!restoreData) {
8135
+ restoreData = {
8136
+ target: particle.position.copy(),
8137
+ lastInteractionTime: now,
8138
+ };
8139
+ this._restoreData.set(particle, restoreData);
8140
+ }
8141
+ restoreData.lastInteractionTime = now;
8142
+ if (restore.follow && particle.options.move.enable) {
8143
+ restoreData.target.x += particle.velocity.x;
8144
+ restoreData.target.y += particle.velocity.y;
8145
+ restoreData.target.z += particle.velocity.z;
8146
+ }
8147
+ }
7994
8148
  }
7995
8149
 
7996
8150
  async function loadExternalRepulseInteraction(engine) {
7997
- engine.checkVersion("4.0.0-beta.16");
8151
+ engine.checkVersion("4.0.0-beta.17");
7998
8152
  await engine.pluginManager.register((e) => {
7999
8153
  ensureInteractivityPluginLoaded(e);
8000
8154
  const pluginManager = e.pluginManager;
@@ -8076,7 +8230,7 @@
8076
8230
  }
8077
8231
 
8078
8232
  async function loadExternalSlowInteraction(engine) {
8079
- engine.checkVersion("4.0.0-beta.16");
8233
+ engine.checkVersion("4.0.0-beta.17");
8080
8234
  await engine.pluginManager.register((e) => {
8081
8235
  ensureInteractivityPluginLoaded(e);
8082
8236
  e.pluginManager.addInteractor?.("externalSlow", container => {
@@ -8904,7 +9058,7 @@
8904
9058
  };
8905
9059
  }
8906
9060
  async function loadImageShape(engine) {
8907
- engine.checkVersion("4.0.0-beta.16");
9061
+ engine.checkVersion("4.0.0-beta.17");
8908
9062
  await engine.pluginManager.register(e => {
8909
9063
  addLoadImageToEngine(e);
8910
9064
  e.pluginManager.addPlugin(new ImagePreloaderPlugin(e));
@@ -9071,7 +9225,7 @@
9071
9225
  }
9072
9226
 
9073
9227
  async function loadLifeUpdater(engine) {
9074
- engine.checkVersion("4.0.0-beta.16");
9228
+ engine.checkVersion("4.0.0-beta.17");
9075
9229
  await engine.pluginManager.register(e => {
9076
9230
  e.pluginManager.addParticleUpdater("life", container => {
9077
9231
  return Promise.resolve(new LifeUpdater(container));
@@ -9097,7 +9251,7 @@
9097
9251
  }
9098
9252
 
9099
9253
  async function loadLineShape(engine) {
9100
- engine.checkVersion("4.0.0-beta.16");
9254
+ engine.checkVersion("4.0.0-beta.17");
9101
9255
  await engine.pluginManager.register(e => {
9102
9256
  e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
9103
9257
  });
@@ -9190,7 +9344,7 @@
9190
9344
  }
9191
9345
 
9192
9346
  async function loadParticlesAttractInteraction(engine) {
9193
- engine.checkVersion("4.0.0-beta.16");
9347
+ engine.checkVersion("4.0.0-beta.17");
9194
9348
  await engine.pluginManager.register((e) => {
9195
9349
  ensureInteractivityPluginLoaded(e);
9196
9350
  e.pluginManager.addInteractor?.("particlesAttract", container => {
@@ -9430,7 +9584,7 @@
9430
9584
  }
9431
9585
 
9432
9586
  async function loadParticlesCollisionsInteraction(engine) {
9433
- engine.checkVersion("4.0.0-beta.16");
9587
+ engine.checkVersion("4.0.0-beta.17");
9434
9588
  await engine.pluginManager.register((e) => {
9435
9589
  ensureInteractivityPluginLoaded(e);
9436
9590
  e.pluginManager.addPlugin(new OverlapPlugin());
@@ -9733,7 +9887,7 @@
9733
9887
  }
9734
9888
 
9735
9889
  async function loadParticlesLinksInteraction(engine) {
9736
- engine.checkVersion("4.0.0-beta.16");
9890
+ engine.checkVersion("4.0.0-beta.17");
9737
9891
  await engine.pluginManager.register((e) => {
9738
9892
  const pluginManager = e.pluginManager;
9739
9893
  ensureInteractivityPluginLoaded(e);
@@ -9823,19 +9977,19 @@
9823
9977
  }
9824
9978
 
9825
9979
  async function loadGenericPolygonShape(engine) {
9826
- engine.checkVersion("4.0.0-beta.16");
9980
+ engine.checkVersion("4.0.0-beta.17");
9827
9981
  await engine.pluginManager.register(e => {
9828
9982
  e.pluginManager.addShape(["polygon"], () => Promise.resolve(new PolygonDrawer()));
9829
9983
  });
9830
9984
  }
9831
9985
  async function loadTriangleShape(engine) {
9832
- engine.checkVersion("4.0.0-beta.16");
9986
+ engine.checkVersion("4.0.0-beta.17");
9833
9987
  await engine.pluginManager.register(e => {
9834
9988
  e.pluginManager.addShape(["triangle"], () => Promise.resolve(new TriangleDrawer()));
9835
9989
  });
9836
9990
  }
9837
9991
  async function loadPolygonShape(engine) {
9838
- engine.checkVersion("4.0.0-beta.16");
9992
+ engine.checkVersion("4.0.0-beta.17");
9839
9993
  await Promise.all([
9840
9994
  loadGenericPolygonShape(engine),
9841
9995
  loadTriangleShape(engine),
@@ -9968,7 +10122,7 @@
9968
10122
  }
9969
10123
 
9970
10124
  async function loadRotateUpdater(engine) {
9971
- engine.checkVersion("4.0.0-beta.16");
10125
+ engine.checkVersion("4.0.0-beta.17");
9972
10126
  await engine.pluginManager.register(e => {
9973
10127
  e.pluginManager.addParticleUpdater("rotate", container => {
9974
10128
  return Promise.resolve(new RotateUpdater(container));
@@ -9992,7 +10146,7 @@
9992
10146
  }
9993
10147
 
9994
10148
  async function loadSquareShape(engine) {
9995
- engine.checkVersion("4.0.0-beta.16");
10149
+ engine.checkVersion("4.0.0-beta.17");
9996
10150
  await engine.pluginManager.register(e => {
9997
10151
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
9998
10152
  });
@@ -10026,14 +10180,14 @@
10026
10180
  }
10027
10181
 
10028
10182
  async function loadStarShape(engine) {
10029
- engine.checkVersion("4.0.0-beta.16");
10183
+ engine.checkVersion("4.0.0-beta.17");
10030
10184
  await engine.pluginManager.register(e => {
10031
10185
  e.pluginManager.addShape(["star"], () => Promise.resolve(new StarDrawer()));
10032
10186
  });
10033
10187
  }
10034
10188
 
10035
10189
  async function loadSlim(engine) {
10036
- engine.checkVersion("4.0.0-beta.16");
10190
+ engine.checkVersion("4.0.0-beta.17");
10037
10191
  await engine.pluginManager.register(async (e) => {
10038
10192
  const loadInteractivityForSlim = async (e) => {
10039
10193
  await loadInteractivityPlugin(e);
@@ -10150,7 +10304,7 @@
10150
10304
  }
10151
10305
 
10152
10306
  async function loadTextShape(engine) {
10153
- engine.checkVersion("4.0.0-beta.16");
10307
+ engine.checkVersion("4.0.0-beta.17");
10154
10308
  await engine.pluginManager.register(e => {
10155
10309
  e.pluginManager.addShape(validTypes, () => Promise.resolve(new TextDrawer()));
10156
10310
  });
@@ -10287,7 +10441,7 @@
10287
10441
  }
10288
10442
 
10289
10443
  async function loadTiltUpdater(engine) {
10290
- engine.checkVersion("4.0.0-beta.16");
10444
+ engine.checkVersion("4.0.0-beta.17");
10291
10445
  await engine.pluginManager.register(e => {
10292
10446
  e.pluginManager.addParticleUpdater("tilt", container => {
10293
10447
  return Promise.resolve(new TiltUpdater(container));
@@ -10420,7 +10574,7 @@
10420
10574
  }
10421
10575
 
10422
10576
  async function loadTwinkleUpdater(engine) {
10423
- engine.checkVersion("4.0.0-beta.16");
10577
+ engine.checkVersion("4.0.0-beta.17");
10424
10578
  await engine.pluginManager.register(e => {
10425
10579
  e.pluginManager.addParticleUpdater("twinkle", container => {
10426
10580
  return Promise.resolve(new TwinkleUpdater(e.pluginManager, container));
@@ -10542,7 +10696,7 @@
10542
10696
  }
10543
10697
 
10544
10698
  async function loadWobbleUpdater(engine) {
10545
- engine.checkVersion("4.0.0-beta.16");
10699
+ engine.checkVersion("4.0.0-beta.17");
10546
10700
  await engine.pluginManager.register(e => {
10547
10701
  e.pluginManager.addParticleUpdater("wobble", container => {
10548
10702
  return Promise.resolve(new WobbleUpdater(container));
@@ -10551,7 +10705,7 @@
10551
10705
  }
10552
10706
 
10553
10707
  async function loadFull(engine) {
10554
- engine.checkVersion("4.0.0-beta.16");
10708
+ engine.checkVersion("4.0.0-beta.17");
10555
10709
  await engine.pluginManager.register(async (e) => {
10556
10710
  const loadEmittersPluginBundle = async (e) => {
10557
10711
  await loadEmittersPlugin(e);
@@ -10656,14 +10810,14 @@
10656
10810
  }
10657
10811
 
10658
10812
  async function loadResponsivePlugin(engine) {
10659
- engine.checkVersion("4.0.0-beta.16");
10813
+ engine.checkVersion("4.0.0-beta.17");
10660
10814
  await engine.pluginManager.register(e => {
10661
10815
  e.pluginManager.addPlugin(new ResponsivePlugin());
10662
10816
  });
10663
10817
  }
10664
10818
 
10665
10819
  const initPjs = async (engine) => {
10666
- engine.checkVersion("4.0.0-beta.16");
10820
+ engine.checkVersion("4.0.0-beta.17");
10667
10821
  await engine.pluginManager.register(async (e) => {
10668
10822
  await Promise.all([loadFull(e), loadResponsivePlugin(e)]);
10669
10823
  });
@@ -10978,6 +11132,25 @@
10978
11132
  };
10979
11133
  }
10980
11134
 
11135
+ const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
11136
+ const transferredCanvas = transferredCanvases.get(canvas);
11137
+ if (transferredCanvas) {
11138
+ return transferredCanvas;
11139
+ }
11140
+ if (typeof canvas.transferControlToOffscreen !== "function") {
11141
+ throw new TypeError("OffscreenCanvas is required but not supported by this browser");
11142
+ }
11143
+ try {
11144
+ const offscreenCanvas = canvas.transferControlToOffscreen();
11145
+ transferredCanvases.set(canvas, offscreenCanvas);
11146
+ return offscreenCanvas;
11147
+ }
11148
+ catch {
11149
+ throw new TypeError("OffscreenCanvas transfer failed");
11150
+ }
11151
+ }, isHtmlCanvasElement = (canvas) => {
11152
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
11153
+ };
10981
11154
  function setStyle(canvas, style, important = false) {
10982
11155
  if (!style) {
10983
11156
  return;
@@ -11008,8 +11181,9 @@
11008
11181
  }
11009
11182
  }
11010
11183
  class CanvasManager {
11011
- element;
11184
+ domElement;
11012
11185
  render;
11186
+ renderCanvas;
11013
11187
  size;
11014
11188
  zoom = defaultZoom;
11015
11189
  _container;
@@ -11044,9 +11218,10 @@
11044
11218
  destroy() {
11045
11219
  this.stop();
11046
11220
  if (this._generated) {
11047
- const element = this.element;
11221
+ const element = this.domElement;
11048
11222
  element?.remove();
11049
- this.element = undefined;
11223
+ this.domElement = undefined;
11224
+ this.renderCanvas = undefined;
11050
11225
  }
11051
11226
  else {
11052
11227
  this._resetOriginalStyle();
@@ -11079,16 +11254,17 @@
11079
11254
  this._initStyle();
11080
11255
  this.initBackground();
11081
11256
  this._safeMutationObserver(obs => {
11082
- if (!this.element || !(this.element instanceof Node)) {
11257
+ const element = this.domElement;
11258
+ if (!element || !(element instanceof Node)) {
11083
11259
  return;
11084
11260
  }
11085
- obs.observe(this.element, { attributes: true });
11261
+ obs.observe(element, { attributes: true });
11086
11262
  });
11087
11263
  this.initPlugins();
11088
11264
  this.render.init();
11089
11265
  }
11090
11266
  initBackground() {
11091
- const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
11267
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.domElement;
11092
11268
  if (!element) {
11093
11269
  return;
11094
11270
  }
@@ -11113,21 +11289,30 @@
11113
11289
  }
11114
11290
  }
11115
11291
  loadCanvas(canvas) {
11116
- if (this._generated && this.element) {
11117
- this.element.remove();
11292
+ if (this._generated && this.domElement) {
11293
+ this.domElement.remove();
11294
+ }
11295
+ const container = this._container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
11296
+ this.domElement = domCanvas;
11297
+ this._generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
11298
+ this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
11299
+ const domElement = this.domElement;
11300
+ if (domElement) {
11301
+ domElement.ariaHidden = "true";
11302
+ this._originalStyle = cloneStyle(domElement.style);
11303
+ }
11304
+ const standardSize = this._standardSize, renderCanvas = this.renderCanvas;
11305
+ if (domElement) {
11306
+ standardSize.height = domElement.offsetHeight;
11307
+ standardSize.width = domElement.offsetWidth;
11308
+ }
11309
+ else {
11310
+ standardSize.height = renderCanvas.height;
11311
+ standardSize.width = renderCanvas.width;
11118
11312
  }
11119
- const container = this._container;
11120
- this._generated =
11121
- generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
11122
- this.element = canvas;
11123
- this.element.ariaHidden = "true";
11124
- this._originalStyle = cloneStyle(this.element.style);
11125
- const standardSize = this._standardSize;
11126
- standardSize.height = canvas.offsetHeight;
11127
- standardSize.width = canvas.offsetWidth;
11128
11313
  const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
11129
- canvas.height = retinaSize.height = standardSize.height * pxRatio;
11130
- canvas.width = retinaSize.width = standardSize.width * pxRatio;
11314
+ renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
11315
+ renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
11131
11316
  const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
11132
11317
  this.render.setContextSettings({
11133
11318
  alpha: true,
@@ -11135,42 +11320,48 @@
11135
11320
  desynchronized: true,
11136
11321
  willReadFrequently: false,
11137
11322
  });
11138
- this.render.setContext(this.element.getContext("2d", this.render.settings));
11323
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
11139
11324
  this._safeMutationObserver(obs => {
11140
11325
  obs.disconnect();
11141
11326
  });
11142
11327
  container.retina.init();
11143
11328
  this.initBackground();
11144
11329
  this._safeMutationObserver(obs => {
11145
- if (!this.element || !(this.element instanceof Node)) {
11330
+ const element = this.domElement;
11331
+ if (!element || !(element instanceof Node)) {
11146
11332
  return;
11147
11333
  }
11148
- obs.observe(this.element, { attributes: true });
11334
+ obs.observe(element, { attributes: true });
11149
11335
  });
11150
11336
  }
11151
11337
  resize() {
11152
- if (!this.element) {
11338
+ const element = this.domElement;
11339
+ if (!element) {
11340
+ return false;
11341
+ }
11342
+ const container = this._container, renderCanvas = this.renderCanvas;
11343
+ if (renderCanvas === undefined) {
11153
11344
  return false;
11154
11345
  }
11155
- const container = this._container, currentSize = container.canvas._standardSize, newSize = {
11156
- width: this.element.offsetWidth,
11157
- height: this.element.offsetHeight,
11346
+ const currentSize = container.canvas._standardSize, newSize = {
11347
+ width: element.offsetWidth,
11348
+ height: element.offsetHeight,
11158
11349
  }, pxRatio = container.retina.pixelRatio, retinaSize = {
11159
11350
  width: newSize.width * pxRatio,
11160
11351
  height: newSize.height * pxRatio,
11161
11352
  };
11162
11353
  if (newSize.height === currentSize.height &&
11163
11354
  newSize.width === currentSize.width &&
11164
- retinaSize.height === this.element.height &&
11165
- retinaSize.width === this.element.width) {
11355
+ retinaSize.height === renderCanvas.height &&
11356
+ retinaSize.width === renderCanvas.width) {
11166
11357
  return false;
11167
11358
  }
11168
11359
  const oldSize = { ...currentSize };
11169
11360
  currentSize.height = newSize.height;
11170
11361
  currentSize.width = newSize.width;
11171
11362
  const canvasSize = this.size;
11172
- this.element.width = canvasSize.width = retinaSize.width;
11173
- this.element.height = canvasSize.height = retinaSize.height;
11363
+ renderCanvas.width = canvasSize.width = retinaSize.width;
11364
+ renderCanvas.height = canvasSize.height = retinaSize.height;
11174
11365
  if (this._container.started) {
11175
11366
  container.particles.setResizeFactor({
11176
11367
  width: currentSize.width / oldSize.width,
@@ -11180,7 +11371,7 @@
11180
11371
  return true;
11181
11372
  }
11182
11373
  setPointerEvents(type) {
11183
- const element = this.element;
11374
+ const element = this.domElement;
11184
11375
  if (!element) {
11185
11376
  return;
11186
11377
  }
@@ -11199,7 +11390,7 @@
11199
11390
  this.render.stop();
11200
11391
  }
11201
11392
  async windowResize() {
11202
- if (!this.element || !this.resize()) {
11393
+ if (!this.domElement || !this.resize()) {
11203
11394
  return;
11204
11395
  }
11205
11396
  const container = this._container, needsRefresh = container.updateActualOptions();
@@ -11215,7 +11406,7 @@
11215
11406
  }
11216
11407
  };
11217
11408
  _initStyle = () => {
11218
- const element = this.element, options = this._container.actualOptions;
11409
+ const element = this.domElement, options = this._container.actualOptions;
11219
11410
  if (!element) {
11220
11411
  return;
11221
11412
  }
@@ -11237,7 +11428,7 @@
11237
11428
  }
11238
11429
  };
11239
11430
  _repairStyle = () => {
11240
- const element = this.element;
11431
+ const element = this.domElement;
11241
11432
  if (!element) {
11242
11433
  return;
11243
11434
  }
@@ -11257,7 +11448,7 @@
11257
11448
  });
11258
11449
  };
11259
11450
  _resetOriginalStyle = () => {
11260
- const element = this.element, originalStyle = this._originalStyle;
11451
+ const element = this.domElement, originalStyle = this._originalStyle;
11261
11452
  if (!element || !originalStyle) {
11262
11453
  return;
11263
11454
  }
@@ -11270,7 +11461,7 @@
11270
11461
  callback(this._mutationObserver);
11271
11462
  };
11272
11463
  _setFullScreenStyle = () => {
11273
- const element = this.element;
11464
+ const element = this.domElement;
11274
11465
  if (!element) {
11275
11466
  return;
11276
11467
  }
@@ -11344,7 +11535,7 @@
11344
11535
  manageListener(globalThis, resizeEvent, handlers.resize, add);
11345
11536
  return;
11346
11537
  }
11347
- const canvasEl = container.canvas.element;
11538
+ const canvasEl = container.canvas.domElement;
11348
11539
  if (this._resizeObserver && !add) {
11349
11540
  if (canvasEl) {
11350
11541
  this._resizeObserver.unobserve(canvasEl);
@@ -11599,8 +11790,6 @@
11599
11790
  this._initPosition(position);
11600
11791
  this.initialVelocity = this._calculateVelocity();
11601
11792
  this.velocity = this.initialVelocity.copy();
11602
- const particles = container.particles;
11603
- particles.setLastZIndex(this.position.z);
11604
11793
  this.zIndexFactor = this.position.z / container.zLayers;
11605
11794
  this.sides = 24;
11606
11795
  let effectDrawer, shapeDrawer;
@@ -11750,7 +11939,7 @@
11750
11939
  return color;
11751
11940
  };
11752
11941
  _initPosition = position => {
11753
- const container = this._container, zIndexValue = getRangeValue(this.options.zIndex.value), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
11942
+ const container = this._container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this._calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
11754
11943
  if (!initialPosition) {
11755
11944
  throw new Error("a valid position cannot be found for particle");
11756
11945
  }
@@ -11884,10 +12073,8 @@
11884
12073
  _container;
11885
12074
  _groupLimits;
11886
12075
  _limit;
11887
- _maxZIndex;
11888
- _minZIndex;
11889
- _needsSort;
11890
12076
  _nextId;
12077
+ _particleBuckets;
11891
12078
  _particleResetPlugins;
11892
12079
  _particleUpdatePlugins;
11893
12080
  _pluginManager;
@@ -11896,19 +12083,17 @@
11896
12083
  _postUpdatePlugins;
11897
12084
  _resizeFactor;
11898
12085
  _updatePlugins;
11899
- _zArray;
12086
+ _zBuckets;
11900
12087
  constructor(pluginManager, container) {
11901
12088
  this._pluginManager = pluginManager;
11902
12089
  this._container = container;
11903
12090
  this._nextId = 0;
11904
12091
  this._array = [];
11905
- this._zArray = [];
11906
12092
  this._pool = [];
11907
12093
  this._limit = 0;
11908
12094
  this._groupLimits = new Map();
11909
- this._needsSort = false;
11910
- this._minZIndex = 0;
11911
- this._maxZIndex = 0;
12095
+ this._particleBuckets = new Map();
12096
+ this._zBuckets = this._createBuckets(this._container.zLayers);
11912
12097
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
11913
12098
  this.checkParticlePositionPlugins = [];
11914
12099
  this._particleResetPlugins = [];
@@ -11950,7 +12135,7 @@
11950
12135
  return;
11951
12136
  }
11952
12137
  this._array.push(particle);
11953
- this._zArray.push(particle);
12138
+ this._insertParticleIntoBucket(particle);
11954
12139
  this._nextId++;
11955
12140
  this._container.dispatchEvent(exports.EventType.particleAdded, {
11956
12141
  particle,
@@ -11964,12 +12149,14 @@
11964
12149
  }
11965
12150
  clear() {
11966
12151
  this._array = [];
11967
- this._zArray = [];
12152
+ this._particleBuckets.clear();
12153
+ this._resetBuckets(this._container.zLayers);
11968
12154
  }
11969
12155
  destroy() {
11970
12156
  this._array = [];
11971
12157
  this._pool.length = 0;
11972
- this._zArray = [];
12158
+ this._particleBuckets.clear();
12159
+ this._zBuckets = [];
11973
12160
  this.checkParticlePositionPlugins = [];
11974
12161
  this._particleResetPlugins = [];
11975
12162
  this._particleUpdatePlugins = [];
@@ -11978,8 +12165,14 @@
11978
12165
  this._updatePlugins = [];
11979
12166
  }
11980
12167
  drawParticles(delta) {
11981
- for (const particle of this._zArray) {
11982
- particle.draw(delta);
12168
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
12169
+ const bucket = this._zBuckets[i];
12170
+ if (!bucket) {
12171
+ continue;
12172
+ }
12173
+ for (const particle of bucket) {
12174
+ particle.draw(delta);
12175
+ }
11983
12176
  }
11984
12177
  }
11985
12178
  filter(condition) {
@@ -11993,15 +12186,14 @@
11993
12186
  }
11994
12187
  async init() {
11995
12188
  const container = this._container, options = container.actualOptions;
11996
- this._minZIndex = 0;
11997
- this._maxZIndex = 0;
11998
- this._needsSort = false;
11999
12189
  this.checkParticlePositionPlugins = [];
12000
12190
  this._updatePlugins = [];
12001
12191
  this._particleUpdatePlugins = [];
12002
12192
  this._postUpdatePlugins = [];
12003
12193
  this._particleResetPlugins = [];
12004
12194
  this._postParticleUpdatePlugins = [];
12195
+ this._particleBuckets.clear();
12196
+ this._resetBuckets(container.zLayers);
12005
12197
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
12006
12198
  for (const plugin of container.plugins) {
12007
12199
  if (plugin.redrawInit) {
@@ -12102,79 +12294,25 @@
12102
12294
  }
12103
12295
  this._applyDensity(options.particles, pluginsCount);
12104
12296
  }
12105
- setLastZIndex(zIndex) {
12106
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
12107
- }
12108
12297
  setResizeFactor(factor) {
12109
12298
  this._resizeFactor = factor;
12110
12299
  }
12111
12300
  update(delta) {
12112
- const particlesToDelete = new Set();
12113
12301
  this.grid.clear();
12114
12302
  for (const plugin of this._updatePlugins) {
12115
12303
  plugin.update?.(delta);
12116
12304
  }
12117
- const resizeFactor = this._resizeFactor;
12118
- for (const particle of this._array) {
12119
- if (resizeFactor && !particle.ignoresResizeRatio) {
12120
- particle.position.x *= resizeFactor.width;
12121
- particle.position.y *= resizeFactor.height;
12122
- particle.initialPosition.x *= resizeFactor.width;
12123
- particle.initialPosition.y *= resizeFactor.height;
12124
- }
12125
- particle.ignoresResizeRatio = false;
12126
- for (const plugin of this._particleResetPlugins) {
12127
- plugin.particleReset?.(particle);
12128
- }
12129
- for (const plugin of this._particleUpdatePlugins) {
12130
- if (particle.destroyed) {
12131
- break;
12132
- }
12133
- plugin.particleUpdate?.(particle, delta);
12134
- }
12135
- if (particle.destroyed) {
12136
- particlesToDelete.add(particle);
12137
- continue;
12138
- }
12139
- this.grid.insert(particle);
12140
- }
12305
+ const particlesToDelete = this._updateParticlesPhase1(delta);
12141
12306
  for (const plugin of this._postUpdatePlugins) {
12142
12307
  plugin.postUpdate?.(delta);
12143
12308
  }
12144
- for (const particle of this._array) {
12145
- if (particle.destroyed) {
12146
- particlesToDelete.add(particle);
12147
- continue;
12148
- }
12149
- for (const updater of this._container.particleUpdaters) {
12150
- updater.update(particle, delta);
12151
- }
12152
- if (!particle.destroyed && !particle.spawning) {
12153
- for (const plugin of this._postParticleUpdatePlugins) {
12154
- plugin.postParticleUpdate?.(particle, delta);
12155
- }
12156
- }
12157
- else if (particle.destroyed) {
12158
- particlesToDelete.add(particle);
12159
- }
12160
- }
12309
+ this._updateParticlesPhase2(delta, particlesToDelete);
12161
12310
  if (particlesToDelete.size) {
12162
12311
  for (const particle of particlesToDelete) {
12163
12312
  this.remove(particle);
12164
12313
  }
12165
12314
  }
12166
12315
  delete this._resizeFactor;
12167
- if (this._needsSort) {
12168
- const zArray = this._zArray;
12169
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
12170
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
12171
- if (!firstItem || !lastItem) {
12172
- return;
12173
- }
12174
- this._maxZIndex = firstItem.position.z;
12175
- this._minZIndex = lastItem.position.z;
12176
- this._needsSort = false;
12177
- }
12178
12316
  }
12179
12317
  _addToPool = (...particles) => {
12180
12318
  this._pool.push(...particles);
@@ -12204,13 +12342,52 @@
12204
12342
  this.removeQuantity(particlesCount - particlesNumber, group);
12205
12343
  }
12206
12344
  };
12345
+ _createBuckets = (zLayers) => {
12346
+ const bucketCount = Math.max(Math.floor(zLayers), one);
12347
+ return Array.from({ length: bucketCount }, () => []);
12348
+ };
12349
+ _getBucketIndex = (zIndex) => {
12350
+ const maxBucketIndex = this._zBuckets.length - one;
12351
+ if (maxBucketIndex <= minIndex) {
12352
+ return minIndex;
12353
+ }
12354
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
12355
+ };
12356
+ _getParticleInsertIndex = (bucket, particleId) => {
12357
+ let start = minIndex, end = bucket.length;
12358
+ while (start < end) {
12359
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
12360
+ if (!middleParticle) {
12361
+ end = middle;
12362
+ continue;
12363
+ }
12364
+ if (middleParticle.id < particleId) {
12365
+ start = middle + one;
12366
+ }
12367
+ else {
12368
+ end = middle;
12369
+ }
12370
+ }
12371
+ return start;
12372
+ };
12207
12373
  _initDensityFactor = densityOptions => {
12208
12374
  const container = this._container;
12209
- if (!container.canvas.element || !densityOptions.enable) {
12375
+ if (!densityOptions.enable) {
12210
12376
  return defaultDensityFactor;
12211
12377
  }
12212
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
12213
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp$3);
12378
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
12379
+ if (!canvasSize.width || !canvasSize.height) {
12380
+ return defaultDensityFactor;
12381
+ }
12382
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp$3));
12383
+ };
12384
+ _insertParticleIntoBucket = (particle) => {
12385
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
12386
+ if (!bucket) {
12387
+ return;
12388
+ }
12389
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
12390
+ this._particleBuckets.set(particle.id, bucketIndex);
12214
12391
  };
12215
12392
  _removeParticle = (index, group, override) => {
12216
12393
  const particle = this._array[index];
@@ -12220,9 +12397,8 @@
12220
12397
  if (particle.group !== group) {
12221
12398
  return false;
12222
12399
  }
12223
- const zIdx = this._zArray.indexOf(particle);
12224
12400
  this._array.splice(index, deleteCount);
12225
- this._zArray.splice(zIdx, deleteCount);
12401
+ this._removeParticleFromBucket(particle);
12226
12402
  particle.destroy(override);
12227
12403
  this._container.dispatchEvent(exports.EventType.particleRemoved, {
12228
12404
  particle,
@@ -12230,6 +12406,98 @@
12230
12406
  this._addToPool(particle);
12231
12407
  return true;
12232
12408
  };
12409
+ _removeParticleFromBucket = (particle) => {
12410
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
12411
+ if (!bucket) {
12412
+ this._particleBuckets.delete(particle.id);
12413
+ return;
12414
+ }
12415
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
12416
+ if (bucket[particleIndex]?.id !== particle.id) {
12417
+ this._particleBuckets.delete(particle.id);
12418
+ return;
12419
+ }
12420
+ bucket.splice(particleIndex, deleteCount);
12421
+ this._particleBuckets.delete(particle.id);
12422
+ };
12423
+ _resetBuckets = (zLayers) => {
12424
+ const bucketCount = Math.max(Math.floor(zLayers), one);
12425
+ if (this._zBuckets.length !== bucketCount) {
12426
+ this._zBuckets = this._createBuckets(bucketCount);
12427
+ return;
12428
+ }
12429
+ for (const bucket of this._zBuckets) {
12430
+ bucket.length = minIndex;
12431
+ }
12432
+ };
12433
+ _updateParticleBucket = (particle) => {
12434
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
12435
+ if (currentBucketIndex === undefined) {
12436
+ this._insertParticleIntoBucket(particle);
12437
+ return;
12438
+ }
12439
+ if (currentBucketIndex === newBucketIndex) {
12440
+ return;
12441
+ }
12442
+ const currentBucket = this._zBuckets[currentBucketIndex];
12443
+ if (currentBucket) {
12444
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
12445
+ if (currentBucket[particleIndex]?.id === particle.id) {
12446
+ currentBucket.splice(particleIndex, deleteCount);
12447
+ }
12448
+ }
12449
+ const newBucket = this._zBuckets[newBucketIndex];
12450
+ if (!newBucket) {
12451
+ this._particleBuckets.set(particle.id, newBucketIndex);
12452
+ return;
12453
+ }
12454
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
12455
+ this._particleBuckets.set(particle.id, newBucketIndex);
12456
+ };
12457
+ _updateParticlesPhase1 = (delta) => {
12458
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
12459
+ for (const particle of this._array) {
12460
+ if (resizeFactor && !particle.ignoresResizeRatio) {
12461
+ particle.position.x *= resizeFactor.width;
12462
+ particle.position.y *= resizeFactor.height;
12463
+ particle.initialPosition.x *= resizeFactor.width;
12464
+ particle.initialPosition.y *= resizeFactor.height;
12465
+ }
12466
+ particle.ignoresResizeRatio = false;
12467
+ for (const plugin of this._particleResetPlugins) {
12468
+ plugin.particleReset?.(particle);
12469
+ }
12470
+ for (const plugin of this._particleUpdatePlugins) {
12471
+ if (particle.destroyed) {
12472
+ break;
12473
+ }
12474
+ plugin.particleUpdate?.(particle, delta);
12475
+ }
12476
+ if (particle.destroyed) {
12477
+ particlesToDelete.add(particle);
12478
+ continue;
12479
+ }
12480
+ this.grid.insert(particle);
12481
+ }
12482
+ return particlesToDelete;
12483
+ };
12484
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
12485
+ for (const particle of this._array) {
12486
+ if (particle.destroyed) {
12487
+ particlesToDelete.add(particle);
12488
+ continue;
12489
+ }
12490
+ for (const updater of this._container.particleUpdaters) {
12491
+ updater.update(particle, delta);
12492
+ }
12493
+ if (!particle.spawning) {
12494
+ for (const plugin of this._postParticleUpdatePlugins) {
12495
+ plugin.postParticleUpdate?.(particle, delta);
12496
+ }
12497
+ }
12498
+ this._updateParticleBucket(particle);
12499
+ }
12500
+ };
12233
12501
  }
12234
12502
 
12235
12503
  class Retina {
@@ -12245,9 +12513,8 @@
12245
12513
  const container = this.container, options = container.actualOptions;
12246
12514
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio$1;
12247
12515
  this.reduceFactor = defaultReduceFactor;
12248
- const ratio = this.pixelRatio, canvas = container.canvas;
12249
- if (canvas.element) {
12250
- const element = canvas.element;
12516
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
12517
+ if (element) {
12251
12518
  canvas.size.width = element.offsetWidth * ratio;
12252
12519
  canvas.size.height = element.offsetHeight * ratio;
12253
12520
  }
@@ -12719,7 +12986,7 @@
12719
12986
  return;
12720
12987
  }
12721
12988
  const html = interactivityEl, canvas = container.canvas;
12722
- canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
12989
+ canvas.setPointerEvents(html === canvas.domElement ? "initial" : "none");
12723
12990
  if (add && !(options.interactivity?.events.onHover.enable || options.interactivity?.events.onClick.enable)) {
12724
12991
  return;
12725
12992
  }
@@ -12746,7 +13013,7 @@
12746
13013
  manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
12747
13014
  };
12748
13015
  _manageListeners = add => {
12749
- const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.element;
13016
+ const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.domElement;
12750
13017
  if (detectType === InteractivityDetect.window) {
12751
13018
  interactionManager.interactivityData.element = safeDocument();
12752
13019
  }
@@ -12793,7 +13060,7 @@
12793
13060
  mouse.clicking = false;
12794
13061
  };
12795
13062
  _mouseTouchMove = e => {
12796
- const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.element;
13063
+ const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.domElement;
12797
13064
  if (!interactivity.element) {
12798
13065
  return;
12799
13066
  }
@@ -12954,7 +13221,7 @@
12954
13221
  if (!lastTouch) {
12955
13222
  return;
12956
13223
  }
12957
- const element = container.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
13224
+ const element = container.canvas.domElement, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
12958
13225
  x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
12959
13226
  y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
12960
13227
  };