@tsparticles/interaction-external-bubble 4.0.0-alpha.24 → 4.0.0-alpha.26

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.
package/602.min.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";(this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[]).push([[602],{602(e,i,t){t.d(i,{Bubbler:()=>u});var l,b,o=t(303),a=t(702),n=t(512);function r(e,i,t,l){return i>=t?(0,o.clamp)(e+(i-t)*l,e,i):i<t?(0,o.clamp)(e-(t-i)*l,i,e):void 0}(l=b||(b={})).color="color",l.opacity="opacity",l.size="size";let s="bubble";class u extends a.ExternalInteractorBase{handleClickMode;_engine;_maxDistance;constructor(e,i){super(i),this._engine=e,this._maxDistance=0,i.bubble??={},this.handleClickMode=e=>{e===s&&(i.bubble??={},i.bubble.clicking=!0)}}get maxDistance(){return this._maxDistance}clear(e,i,t){(!e.bubble.inRange||t)&&(delete e.bubble.div,delete e.bubble.opacity,delete e.bubble.radius,delete e.bubble.color)}init(){let e=this.container,i=e.actualOptions.interactivity?.modes.bubble;i&&(this._maxDistance=i.distance,e.retina.bubbleModeDistance=i.distance*e.retina.pixelRatio,void 0!==i.size&&(e.retina.bubbleModeSize=i.size*e.retina.pixelRatio))}interact(e,i){let t=this.container.actualOptions,l=t.interactivity?.events;if(!l)return;let b=l.onHover,n=l.onClick,r=b.enable,u=b.mode,c=n.enable,d=n.mode,p=l.onDiv;r&&(0,o.isInArray)(s,u)?this._hoverBubble(e):c&&(0,o.isInArray)(s,d)?this._clickBubble(e):(0,a.divModeExecute)(s,p,(t,l)=>{this._singleSelectorHover(e,i,t,l)})}isEnabled(e,i){let t=this.container.actualOptions,l=e.mouse,b=(i?.interactivity??t.interactivity)?.events;if(!b)return!1;let{onClick:n,onDiv:r,onHover:u}=b,c=(0,a.isDivModeEnabled)(s,r);return!!(c||u.enable&&l.position||n.enable&&l.clickPosition)&&((0,o.isInArray)(s,u.mode)||(0,o.isInArray)(s,n.mode)||c)}loadModeOptions(e,...i){for(let t of(e.bubble??=new n.Z,i))e.bubble.load(t?.bubble)}reset(e,i){i.bubble.inRange=!1}_clickBubble=e=>{let i=this.container,t=i.actualOptions,l=e.mouse.clickPosition,a=t.interactivity?.modes.bubble;if(!a||!l)return;i.bubble??={};let n=i.retina.bubbleModeDistance;if(!n||n<0)return;let r=i.particles.grid.queryCircle(l,n,i=>this.isEnabled(e,i)),{bubble:s}=i;for(let t of r){if(!s.clicking)continue;t.bubble.inRange=!s.durationEnd;let r=t.getPosition(),u=(0,o.getDistance)(r,l),c=(performance.now()-(e.mouse.clickTime??0))/o.millisecondsToSeconds;c>a.duration&&(s.durationEnd=!0),c>a.duration*o.double&&(s.clicking=!1,s.durationEnd=!1);let d={bubbleObj:{optValue:i.retina.bubbleModeSize,value:t.bubble.radius},particlesObj:{optValue:(0,o.getRangeMax)(t.options.size.value)*i.retina.pixelRatio,value:t.size.value},type:b.size};this._process(t,u,c,d);let p={bubbleObj:{optValue:a.opacity,value:t.bubble.opacity},particlesObj:{optValue:(0,o.getRangeMax)(t.options.opacity.value),value:t.opacity?.value??1},type:b.opacity};this._process(t,u,c,p),!s.durationEnd&&u<=n?this._hoverBubbleColor(t,u):delete t.bubble.color}};_hoverBubble=e=>{let i=this.container,t=e.mouse.position,l=i.retina.bubbleModeDistance;if(l&&!(l<0)&&t)for(let b of i.particles.grid.queryCircle(t,l,i=>this.isEnabled(e,i))){b.bubble.inRange=!0;let i=b.getPosition(),n=(0,o.getDistance)(i,t),r=1-n/l;n<=l?r>=0&&e.status===a.mouseMoveEvent&&(this._hoverBubbleSize(b,r),this._hoverBubbleOpacity(b,r),this._hoverBubbleColor(b,r)):this.reset(e,b),e.status===a.mouseLeaveEvent&&this.reset(e,b)}};_hoverBubbleColor=(e,i,t)=>{let l=this.container.actualOptions,b=t??l.interactivity?.modes.bubble;if(b){if(!e.bubble.finalColor){let i=b.color;if(!i)return;let t=(0,o.itemFromSingleOrMultiple)(i);e.bubble.finalColor=(0,o.rangeColorToHsl)(this._engine,t)}if(e.bubble.finalColor)if(b.mix){e.bubble.color=void 0;let t=e.getFillColor();e.bubble.color=t?(0,o.rgbToHsl)((0,o.colorMix)(t,e.bubble.finalColor,1-i,i)):e.bubble.finalColor}else e.bubble.color=e.bubble.finalColor}};_hoverBubbleOpacity=(e,i,t)=>{let l=this.container.actualOptions,b=t?.opacity??l.interactivity?.modes.bubble?.opacity;if(!b)return;let a=e.options.opacity.value,n=r(e.opacity?.value??1,b,(0,o.getRangeMax)(a),i);void 0!==n&&(e.bubble.opacity=n)};_hoverBubbleSize=(e,i,t)=>{let l=this.container,b=t?.size?t.size*l.retina.pixelRatio:l.retina.bubbleModeSize;if(void 0===b)return;let a=(0,o.getRangeMax)(e.options.size.value)*l.retina.pixelRatio,n=r(e.size.value,b,a,i);void 0!==n&&(e.bubble.radius=n)};_process=(e,i,t,l)=>{let o=this.container,a=l.bubbleObj.optValue,n=o.actualOptions,r=n.interactivity?.modes.bubble;if(!r||void 0===a)return;let s=r.duration,u=o.retina.bubbleModeDistance,c=l.particlesObj.optValue,d=l.bubbleObj.value,p=l.particlesObj.value??0,h=l.type;if(u&&!(u<0)&&a!==c)if(o.bubble??={},o.bubble.durationEnd)d&&(h===b.size&&delete e.bubble.radius,h===b.opacity&&delete e.bubble.opacity);else if(i<=u){if((d??p)!==a){let i=p-t*(p-a)/s;h===b.size&&(e.bubble.radius=i),h===b.opacity&&(e.bubble.opacity=i)}}else h===b.size&&delete e.bubble.radius,h===b.opacity&&delete e.bubble.opacity};_singleSelectorHover=(e,i,t,l)=>{let b=this.container,n=(0,o.safeDocument)().querySelectorAll(t),r=b.actualOptions.interactivity?.modes.bubble;r&&n.length&&n.forEach(t=>{let n=b.retina.pixelRatio,s={x:(t.offsetLeft+t.offsetWidth*o.half)*n,y:(t.offsetTop+t.offsetHeight*o.half)*n},u=t.offsetWidth*o.half*n,c=l.type===a.DivType.circle?new o.Circle(s.x,s.y,u):new o.Rectangle(t.offsetLeft*n,t.offsetTop*n,t.offsetWidth*n,t.offsetHeight*n);for(let l of b.particles.grid.query(c,i=>this.isEnabled(e,i))){if(!c.contains(l.getPosition()))continue;l.bubble.inRange=!0;let e=r.divs,b=(0,a.divMode)(e,t);l.bubble.div&&l.bubble.div===t||(this.clear(l,i,!0),l.bubble.div=t),this._hoverBubbleSize(l,1,b),this._hoverBubbleOpacity(l,1,b),this._hoverBubbleColor(l,1,b)}})}}}}]);
@@ -7,9 +7,11 @@ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, defaultOpaci
7
7
  export class Bubbler extends ExternalInteractorBase {
8
8
  handleClickMode;
9
9
  _engine;
10
+ _maxDistance;
10
11
  constructor(engine, container) {
11
12
  super(container);
12
13
  this._engine = engine;
14
+ this._maxDistance = 0;
13
15
  container.bubble ??= {};
14
16
  this.handleClickMode = (mode) => {
15
17
  if (mode !== bubbleMode) {
@@ -19,6 +21,9 @@ export class Bubbler extends ExternalInteractorBase {
19
21
  container.bubble.clicking = true;
20
22
  };
21
23
  }
24
+ get maxDistance() {
25
+ return this._maxDistance;
26
+ }
22
27
  clear(particle, _delta, force) {
23
28
  if (particle.bubble.inRange && !force) {
24
29
  return;
@@ -33,6 +38,7 @@ export class Bubbler extends ExternalInteractorBase {
33
38
  if (!bubble) {
34
39
  return;
35
40
  }
41
+ this._maxDistance = bubble.distance;
36
42
  container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;
37
43
  if (bubble.size !== undefined) {
38
44
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
@@ -86,7 +92,7 @@ export class Bubbler extends ExternalInteractorBase {
86
92
  if (!distance || distance < minDistance) {
87
93
  return;
88
94
  }
89
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
95
+ const query = container.particles.grid.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
90
96
  for (const particle of query) {
91
97
  if (!bubble.clicking) {
92
98
  continue;
@@ -137,7 +143,7 @@ export class Bubbler extends ExternalInteractorBase {
137
143
  if (!distance || distance < minDistance || !mousePos) {
138
144
  return;
139
145
  }
140
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
146
+ const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
141
147
  for (const particle of query) {
142
148
  particle.bubble.inRange = true;
143
149
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
@@ -257,7 +263,7 @@ export class Bubbler extends ExternalInteractorBase {
257
263
  y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
258
264
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
259
265
  ? new Circle(pos.x, pos.y, repulseRadius)
260
- : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p));
266
+ : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p));
261
267
  for (const particle of query) {
262
268
  if (!area.contains(particle.getPosition())) {
263
269
  continue;
package/browser/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export async function loadExternalBubbleInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.24");
2
+ engine.checkVersion("4.0.0-alpha.26");
3
3
  await engine.register(async (e) => {
4
4
  const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity");
5
5
  ensureInteractivityPluginLoaded(e);
package/cjs/Bubbler.js CHANGED
@@ -7,9 +7,11 @@ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, defaultOpaci
7
7
  export class Bubbler extends ExternalInteractorBase {
8
8
  handleClickMode;
9
9
  _engine;
10
+ _maxDistance;
10
11
  constructor(engine, container) {
11
12
  super(container);
12
13
  this._engine = engine;
14
+ this._maxDistance = 0;
13
15
  container.bubble ??= {};
14
16
  this.handleClickMode = (mode) => {
15
17
  if (mode !== bubbleMode) {
@@ -19,6 +21,9 @@ export class Bubbler extends ExternalInteractorBase {
19
21
  container.bubble.clicking = true;
20
22
  };
21
23
  }
24
+ get maxDistance() {
25
+ return this._maxDistance;
26
+ }
22
27
  clear(particle, _delta, force) {
23
28
  if (particle.bubble.inRange && !force) {
24
29
  return;
@@ -33,6 +38,7 @@ export class Bubbler extends ExternalInteractorBase {
33
38
  if (!bubble) {
34
39
  return;
35
40
  }
41
+ this._maxDistance = bubble.distance;
36
42
  container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;
37
43
  if (bubble.size !== undefined) {
38
44
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
@@ -86,7 +92,7 @@ export class Bubbler extends ExternalInteractorBase {
86
92
  if (!distance || distance < minDistance) {
87
93
  return;
88
94
  }
89
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
95
+ const query = container.particles.grid.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
90
96
  for (const particle of query) {
91
97
  if (!bubble.clicking) {
92
98
  continue;
@@ -137,7 +143,7 @@ export class Bubbler extends ExternalInteractorBase {
137
143
  if (!distance || distance < minDistance || !mousePos) {
138
144
  return;
139
145
  }
140
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
146
+ const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
141
147
  for (const particle of query) {
142
148
  particle.bubble.inRange = true;
143
149
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
@@ -257,7 +263,7 @@ export class Bubbler extends ExternalInteractorBase {
257
263
  y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
258
264
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
259
265
  ? new Circle(pos.x, pos.y, repulseRadius)
260
- : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p));
266
+ : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p));
261
267
  for (const particle of query) {
262
268
  if (!area.contains(particle.getPosition())) {
263
269
  continue;
package/cjs/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export async function loadExternalBubbleInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.24");
2
+ engine.checkVersion("4.0.0-alpha.26");
3
3
  await engine.register(async (e) => {
4
4
  const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity");
5
5
  ensureInteractivityPluginLoaded(e);
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v4.0.0-alpha.24
7
+ * v4.0.0-alpha.26
8
8
  */
9
9
  "use strict";
10
10
  /*
@@ -23,7 +23,7 @@
23
23
  \*********************************/
24
24
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
25
25
 
26
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Bubbler: () => (/* binding */ Bubbler)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\");\n/* harmony import */ var _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Bubble.js */ \"./dist/browser/Options/Classes/Bubble.js\");\n/* harmony import */ var _Enums_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Enums.js */ \"./dist/browser/Enums.js\");\n/* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Utils.js */ \"./dist/browser/Utils.js\");\n\n\n\n\n\nconst bubbleMode = \"bubble\", minDistance = 0, defaultClickTime = 0, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, defaultRatio = 1;\nclass Bubbler extends _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.ExternalInteractorBase {\n handleClickMode;\n _engine;\n constructor(engine, container){\n super(container);\n this._engine = engine;\n container.bubble ??= {};\n this.handleClickMode = (mode)=>{\n if (mode !== bubbleMode) {\n return;\n }\n container.bubble ??= {};\n container.bubble.clicking = true;\n };\n }\n clear(particle, _delta, force) {\n if (particle.bubble.inRange && !force) {\n return;\n }\n delete particle.bubble.div;\n delete particle.bubble.opacity;\n delete particle.bubble.radius;\n delete particle.bubble.color;\n }\n init() {\n const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;\n if (!bubble) {\n return;\n }\n container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;\n if (bubble.size !== undefined) {\n container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;\n }\n }\n interact(interactivityData, delta) {\n const options = this.container.actualOptions, events = options.interactivity?.events;\n if (!events) {\n return;\n }\n const onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;\n if (hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, hoverMode)) {\n this._hoverBubble(interactivityData);\n } else if (clickEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, clickMode)) {\n this._clickBubble(interactivityData);\n } else {\n (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divModeExecute)(bubbleMode, divs, (selector, div)=>{\n this._singleSelectorHover(interactivityData, delta, selector, div);\n });\n }\n }\n isEnabled(interactivityData, particle) {\n const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;\n if (!events) {\n return false;\n }\n const { onClick, onDiv, onHover } = events, divBubble = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.isDivModeEnabled)(bubbleMode, onDiv);\n if (!(divBubble || onHover.enable && !!mouse.position || onClick.enable && mouse.clickPosition)) {\n return false;\n }\n return (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, onHover.mode) || (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, onClick.mode) || divBubble;\n }\n loadModeOptions(options, ...sources) {\n options.bubble ??= new _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__.Bubble();\n for (const source of sources){\n options.bubble.load(source?.bubble);\n }\n }\n reset(_interactivityData, particle) {\n particle.bubble.inRange = false;\n }\n _clickBubble = (interactivityData)=>{\n const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;\n if (!bubbleOptions || !mouseClickPos) {\n return;\n }\n container.bubble ??= {};\n const distance = container.retina.bubbleModeDistance;\n if (!distance || distance < minDistance) {\n return;\n }\n const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p)=>this.isEnabled(interactivityData, p)), { bubble } = container;\n for (const particle of query){\n if (!bubble.clicking) {\n continue;\n }\n particle.bubble.inRange = !bubble.durationEnd;\n const pos = particle.getPosition(), distMouse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mouseClickPos), timeSpent = (performance.now() - (interactivityData.mouse.clickTime ?? defaultClickTime)) / _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.millisecondsToSeconds;\n if (timeSpent > bubbleOptions.duration) {\n bubble.durationEnd = true;\n }\n if (timeSpent > bubbleOptions.duration * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.double) {\n bubble.clicking = false;\n bubble.durationEnd = false;\n }\n const sizeData = {\n bubbleObj: {\n optValue: container.retina.bubbleModeSize,\n value: particle.bubble.radius\n },\n particlesObj: {\n optValue: (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,\n value: particle.size.value\n },\n type: _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size\n };\n this._process(particle, distMouse, timeSpent, sizeData);\n const opacityData = {\n bubbleObj: {\n optValue: bubbleOptions.opacity,\n value: particle.bubble.opacity\n },\n particlesObj: {\n optValue: (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(particle.options.opacity.value),\n value: particle.opacity?.value ?? defaultOpacity\n },\n type: _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity\n };\n this._process(particle, distMouse, timeSpent, opacityData);\n if (!bubble.durationEnd && distMouse <= distance) {\n this._hoverBubbleColor(particle, distMouse);\n } else {\n delete particle.bubble.color;\n }\n }\n };\n _hoverBubble = (interactivityData)=>{\n const container = this.container, mousePos = interactivityData.mouse.position, distance = container.retina.bubbleModeDistance;\n if (!distance || distance < minDistance || !mousePos) {\n return;\n }\n const query = container.particles.quadTree.queryCircle(mousePos, distance, (p)=>this.isEnabled(interactivityData, p));\n for (const particle of query){\n particle.bubble.inRange = true;\n const pos = particle.getPosition(), pointDistance = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mousePos), ratio = ratioOffset - pointDistance / distance;\n if (pointDistance <= distance) {\n if (ratio >= minRatio && interactivityData.status === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.mouseMoveEvent) {\n this._hoverBubbleSize(particle, ratio);\n this._hoverBubbleOpacity(particle, ratio);\n this._hoverBubbleColor(particle, ratio);\n }\n } else {\n this.reset(interactivityData, particle);\n }\n if (interactivityData.status === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.mouseLeaveEvent) {\n this.reset(interactivityData, particle);\n }\n }\n };\n _hoverBubbleColor = (particle, ratio, divBubble)=>{\n const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;\n if (!bubbleOptions) {\n return;\n }\n if (!particle.bubble.finalColor) {\n const modeColor = bubbleOptions.color;\n if (!modeColor) {\n return;\n }\n const bubbleColor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.itemFromSingleOrMultiple)(modeColor);\n particle.bubble.finalColor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.rangeColorToHsl)(this._engine, bubbleColor);\n }\n if (!particle.bubble.finalColor) {\n return;\n }\n if (bubbleOptions.mix) {\n particle.bubble.color = undefined;\n const pColor = particle.getFillColor();\n particle.bubble.color = pColor ? (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.rgbToHsl)((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.colorMix)(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio)) : particle.bubble.finalColor;\n } else {\n particle.bubble.color = particle.bubble.finalColor;\n }\n };\n _hoverBubbleOpacity = (particle, ratio, divBubble)=>{\n const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;\n if (!modeOpacity) {\n return;\n }\n const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? defaultOpacity, opacity = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__.calculateBubbleValue)(pOpacity, modeOpacity, (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(optOpacity), ratio);\n if (opacity !== undefined) {\n particle.bubble.opacity = opacity;\n }\n };\n _hoverBubbleSize = (particle, ratio, divBubble)=>{\n const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;\n if (modeSize === undefined) {\n return;\n }\n const optSize = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio, pSize = particle.size.value, size = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__.calculateBubbleValue)(pSize, modeSize, optSize, ratio);\n if (size !== undefined) {\n particle.bubble.radius = size;\n }\n };\n _process = (particle, distMouse, timeSpent, data)=>{\n const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity?.modes.bubble;\n if (!bubbleOptions || bubbleParam === undefined) {\n return;\n }\n const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value ?? defaultBubbleValue, type = data.type;\n if (!bubbleDistance || bubbleDistance < minDistance || bubbleParam === particlesParam) {\n return;\n }\n container.bubble ??= {};\n if (container.bubble.durationEnd) {\n if (pObjBubble) {\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size) {\n delete particle.bubble.radius;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity) {\n delete particle.bubble.opacity;\n }\n }\n } else {\n if (distMouse <= bubbleDistance) {\n const obj = pObjBubble ?? pObj;\n if (obj !== bubbleParam) {\n const value = pObj - timeSpent * (pObj - bubbleParam) / bubbleDuration;\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size) {\n particle.bubble.radius = value;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity) {\n particle.bubble.opacity = value;\n }\n }\n } else {\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size) {\n delete particle.bubble.radius;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity) {\n delete particle.bubble.opacity;\n }\n }\n }\n };\n _singleSelectorHover = (interactivityData, delta, selector, div)=>{\n const container = this.container, selectors = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.safeDocument)().querySelectorAll(selector), bubble = container.actualOptions.interactivity?.modes.bubble;\n if (!bubble || !selectors.length) {\n return;\n }\n selectors.forEach((item)=>{\n const elem = item, pxRatio = container.retina.pixelRatio, pos = {\n x: (elem.offsetLeft + elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio\n }, repulseRadius = elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half * pxRatio, area = div.type === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.DivType.circle ? new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(pos.x, pos.y, repulseRadius) : new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p)=>this.isEnabled(interactivityData, p));\n for (const particle of query){\n if (!area.contains(particle.getPosition())) {\n continue;\n }\n particle.bubble.inRange = true;\n const divs = bubble.divs, divBubble = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divMode)(divs, elem);\n if (!particle.bubble.div || particle.bubble.div !== elem) {\n this.clear(particle, delta, true);\n particle.bubble.div = elem;\n }\n this._hoverBubbleSize(particle, defaultRatio, divBubble);\n this._hoverBubbleOpacity(particle, defaultRatio, divBubble);\n this._hoverBubbleColor(particle, defaultRatio, divBubble);\n }\n });\n };\n}\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-bubble/./dist/browser/Bubbler.js?\n}");
26
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Bubbler: () => (/* binding */ Bubbler)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\");\n/* harmony import */ var _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Bubble.js */ \"./dist/browser/Options/Classes/Bubble.js\");\n/* harmony import */ var _Enums_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Enums.js */ \"./dist/browser/Enums.js\");\n/* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Utils.js */ \"./dist/browser/Utils.js\");\n\n\n\n\n\nconst bubbleMode = \"bubble\", minDistance = 0, defaultClickTime = 0, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, defaultRatio = 1;\nclass Bubbler extends _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.ExternalInteractorBase {\n handleClickMode;\n _engine;\n _maxDistance;\n constructor(engine, container){\n super(container);\n this._engine = engine;\n this._maxDistance = 0;\n container.bubble ??= {};\n this.handleClickMode = (mode)=>{\n if (mode !== bubbleMode) {\n return;\n }\n container.bubble ??= {};\n container.bubble.clicking = true;\n };\n }\n get maxDistance() {\n return this._maxDistance;\n }\n clear(particle, _delta, force) {\n if (particle.bubble.inRange && !force) {\n return;\n }\n delete particle.bubble.div;\n delete particle.bubble.opacity;\n delete particle.bubble.radius;\n delete particle.bubble.color;\n }\n init() {\n const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;\n if (!bubble) {\n return;\n }\n this._maxDistance = bubble.distance;\n container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;\n if (bubble.size !== undefined) {\n container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;\n }\n }\n interact(interactivityData, delta) {\n const options = this.container.actualOptions, events = options.interactivity?.events;\n if (!events) {\n return;\n }\n const onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;\n if (hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, hoverMode)) {\n this._hoverBubble(interactivityData);\n } else if (clickEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, clickMode)) {\n this._clickBubble(interactivityData);\n } else {\n (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divModeExecute)(bubbleMode, divs, (selector, div)=>{\n this._singleSelectorHover(interactivityData, delta, selector, div);\n });\n }\n }\n isEnabled(interactivityData, particle) {\n const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;\n if (!events) {\n return false;\n }\n const { onClick, onDiv, onHover } = events, divBubble = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.isDivModeEnabled)(bubbleMode, onDiv);\n if (!(divBubble || onHover.enable && !!mouse.position || onClick.enable && mouse.clickPosition)) {\n return false;\n }\n return (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, onHover.mode) || (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, onClick.mode) || divBubble;\n }\n loadModeOptions(options, ...sources) {\n options.bubble ??= new _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__.Bubble();\n for (const source of sources){\n options.bubble.load(source?.bubble);\n }\n }\n reset(_interactivityData, particle) {\n particle.bubble.inRange = false;\n }\n _clickBubble = (interactivityData)=>{\n const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;\n if (!bubbleOptions || !mouseClickPos) {\n return;\n }\n container.bubble ??= {};\n const distance = container.retina.bubbleModeDistance;\n if (!distance || distance < minDistance) {\n return;\n }\n const query = container.particles.grid.queryCircle(mouseClickPos, distance, (p)=>this.isEnabled(interactivityData, p)), { bubble } = container;\n for (const particle of query){\n if (!bubble.clicking) {\n continue;\n }\n particle.bubble.inRange = !bubble.durationEnd;\n const pos = particle.getPosition(), distMouse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mouseClickPos), timeSpent = (performance.now() - (interactivityData.mouse.clickTime ?? defaultClickTime)) / _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.millisecondsToSeconds;\n if (timeSpent > bubbleOptions.duration) {\n bubble.durationEnd = true;\n }\n if (timeSpent > bubbleOptions.duration * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.double) {\n bubble.clicking = false;\n bubble.durationEnd = false;\n }\n const sizeData = {\n bubbleObj: {\n optValue: container.retina.bubbleModeSize,\n value: particle.bubble.radius\n },\n particlesObj: {\n optValue: (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,\n value: particle.size.value\n },\n type: _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size\n };\n this._process(particle, distMouse, timeSpent, sizeData);\n const opacityData = {\n bubbleObj: {\n optValue: bubbleOptions.opacity,\n value: particle.bubble.opacity\n },\n particlesObj: {\n optValue: (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(particle.options.opacity.value),\n value: particle.opacity?.value ?? defaultOpacity\n },\n type: _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity\n };\n this._process(particle, distMouse, timeSpent, opacityData);\n if (!bubble.durationEnd && distMouse <= distance) {\n this._hoverBubbleColor(particle, distMouse);\n } else {\n delete particle.bubble.color;\n }\n }\n };\n _hoverBubble = (interactivityData)=>{\n const container = this.container, mousePos = interactivityData.mouse.position, distance = container.retina.bubbleModeDistance;\n if (!distance || distance < minDistance || !mousePos) {\n return;\n }\n const query = container.particles.grid.queryCircle(mousePos, distance, (p)=>this.isEnabled(interactivityData, p));\n for (const particle of query){\n particle.bubble.inRange = true;\n const pos = particle.getPosition(), pointDistance = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mousePos), ratio = ratioOffset - pointDistance / distance;\n if (pointDistance <= distance) {\n if (ratio >= minRatio && interactivityData.status === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.mouseMoveEvent) {\n this._hoverBubbleSize(particle, ratio);\n this._hoverBubbleOpacity(particle, ratio);\n this._hoverBubbleColor(particle, ratio);\n }\n } else {\n this.reset(interactivityData, particle);\n }\n if (interactivityData.status === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.mouseLeaveEvent) {\n this.reset(interactivityData, particle);\n }\n }\n };\n _hoverBubbleColor = (particle, ratio, divBubble)=>{\n const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;\n if (!bubbleOptions) {\n return;\n }\n if (!particle.bubble.finalColor) {\n const modeColor = bubbleOptions.color;\n if (!modeColor) {\n return;\n }\n const bubbleColor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.itemFromSingleOrMultiple)(modeColor);\n particle.bubble.finalColor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.rangeColorToHsl)(this._engine, bubbleColor);\n }\n if (!particle.bubble.finalColor) {\n return;\n }\n if (bubbleOptions.mix) {\n particle.bubble.color = undefined;\n const pColor = particle.getFillColor();\n particle.bubble.color = pColor ? (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.rgbToHsl)((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.colorMix)(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio)) : particle.bubble.finalColor;\n } else {\n particle.bubble.color = particle.bubble.finalColor;\n }\n };\n _hoverBubbleOpacity = (particle, ratio, divBubble)=>{\n const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;\n if (!modeOpacity) {\n return;\n }\n const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? defaultOpacity, opacity = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__.calculateBubbleValue)(pOpacity, modeOpacity, (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(optOpacity), ratio);\n if (opacity !== undefined) {\n particle.bubble.opacity = opacity;\n }\n };\n _hoverBubbleSize = (particle, ratio, divBubble)=>{\n const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;\n if (modeSize === undefined) {\n return;\n }\n const optSize = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio, pSize = particle.size.value, size = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__.calculateBubbleValue)(pSize, modeSize, optSize, ratio);\n if (size !== undefined) {\n particle.bubble.radius = size;\n }\n };\n _process = (particle, distMouse, timeSpent, data)=>{\n const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity?.modes.bubble;\n if (!bubbleOptions || bubbleParam === undefined) {\n return;\n }\n const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value ?? defaultBubbleValue, type = data.type;\n if (!bubbleDistance || bubbleDistance < minDistance || bubbleParam === particlesParam) {\n return;\n }\n container.bubble ??= {};\n if (container.bubble.durationEnd) {\n if (pObjBubble) {\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size) {\n delete particle.bubble.radius;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity) {\n delete particle.bubble.opacity;\n }\n }\n } else {\n if (distMouse <= bubbleDistance) {\n const obj = pObjBubble ?? pObj;\n if (obj !== bubbleParam) {\n const value = pObj - timeSpent * (pObj - bubbleParam) / bubbleDuration;\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size) {\n particle.bubble.radius = value;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity) {\n particle.bubble.opacity = value;\n }\n }\n } else {\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.size) {\n delete particle.bubble.radius;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_3__.ProcessBubbleType.opacity) {\n delete particle.bubble.opacity;\n }\n }\n }\n };\n _singleSelectorHover = (interactivityData, delta, selector, div)=>{\n const container = this.container, selectors = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.safeDocument)().querySelectorAll(selector), bubble = container.actualOptions.interactivity?.modes.bubble;\n if (!bubble || !selectors.length) {\n return;\n }\n selectors.forEach((item)=>{\n const elem = item, pxRatio = container.retina.pixelRatio, pos = {\n x: (elem.offsetLeft + elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio\n }, repulseRadius = elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half * pxRatio, area = div.type === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.DivType.circle ? new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(pos.x, pos.y, repulseRadius) : new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.grid.query(area, (p)=>this.isEnabled(interactivityData, p));\n for (const particle of query){\n if (!area.contains(particle.getPosition())) {\n continue;\n }\n particle.bubble.inRange = true;\n const divs = bubble.divs, divBubble = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divMode)(divs, elem);\n if (!particle.bubble.div || particle.bubble.div !== elem) {\n this.clear(particle, delta, true);\n particle.bubble.div = elem;\n }\n this._hoverBubbleSize(particle, defaultRatio, divBubble);\n this._hoverBubbleOpacity(particle, defaultRatio, divBubble);\n this._hoverBubbleColor(particle, defaultRatio, divBubble);\n }\n });\n };\n}\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-bubble/./dist/browser/Bubbler.js?\n}");
27
27
 
28
28
  /***/ },
29
29
 
package/esm/Bubbler.js CHANGED
@@ -7,9 +7,11 @@ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, defaultOpaci
7
7
  export class Bubbler extends ExternalInteractorBase {
8
8
  handleClickMode;
9
9
  _engine;
10
+ _maxDistance;
10
11
  constructor(engine, container) {
11
12
  super(container);
12
13
  this._engine = engine;
14
+ this._maxDistance = 0;
13
15
  container.bubble ??= {};
14
16
  this.handleClickMode = (mode) => {
15
17
  if (mode !== bubbleMode) {
@@ -19,6 +21,9 @@ export class Bubbler extends ExternalInteractorBase {
19
21
  container.bubble.clicking = true;
20
22
  };
21
23
  }
24
+ get maxDistance() {
25
+ return this._maxDistance;
26
+ }
22
27
  clear(particle, _delta, force) {
23
28
  if (particle.bubble.inRange && !force) {
24
29
  return;
@@ -33,6 +38,7 @@ export class Bubbler extends ExternalInteractorBase {
33
38
  if (!bubble) {
34
39
  return;
35
40
  }
41
+ this._maxDistance = bubble.distance;
36
42
  container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;
37
43
  if (bubble.size !== undefined) {
38
44
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
@@ -86,7 +92,7 @@ export class Bubbler extends ExternalInteractorBase {
86
92
  if (!distance || distance < minDistance) {
87
93
  return;
88
94
  }
89
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
95
+ const query = container.particles.grid.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
90
96
  for (const particle of query) {
91
97
  if (!bubble.clicking) {
92
98
  continue;
@@ -137,7 +143,7 @@ export class Bubbler extends ExternalInteractorBase {
137
143
  if (!distance || distance < minDistance || !mousePos) {
138
144
  return;
139
145
  }
140
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
146
+ const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
141
147
  for (const particle of query) {
142
148
  particle.bubble.inRange = true;
143
149
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
@@ -257,7 +263,7 @@ export class Bubbler extends ExternalInteractorBase {
257
263
  y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
258
264
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
259
265
  ? new Circle(pos.x, pos.y, repulseRadius)
260
- : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p));
266
+ : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p));
261
267
  for (const particle of query) {
262
268
  if (!area.contains(particle.getPosition())) {
263
269
  continue;
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export async function loadExternalBubbleInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.24");
2
+ engine.checkVersion("4.0.0-alpha.26");
3
3
  await engine.register(async (e) => {
4
4
  const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity");
5
5
  ensureInteractivityPluginLoaded(e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/interaction-external-bubble",
3
- "version": "4.0.0-alpha.24",
3
+ "version": "4.0.0-alpha.26",
4
4
  "description": "tsParticles bubble external interaction",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -87,8 +87,8 @@
87
87
  "./package.json": "./package.json"
88
88
  },
89
89
  "dependencies": {
90
- "@tsparticles/engine": "4.0.0-alpha.24",
91
- "@tsparticles/plugin-interactivity": "4.0.0-alpha.24"
90
+ "@tsparticles/engine": "4.0.0-alpha.26",
91
+ "@tsparticles/plugin-interactivity": "4.0.0-alpha.26"
92
92
  },
93
93
  "publishConfig": {
94
94
  "access": "public"
package/report.html CHANGED
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8"/>
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
6
- <title>@tsparticles/interaction-external-bubble [12 Feb 2026 at 18:50]</title>
6
+ <title>@tsparticles/interaction-external-bubble [26 Feb 2026 at 18:06]</title>
7
7
  <link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" />
8
8
 
9
9
  <script>
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v4.0.0-alpha.24
7
+ * v4.0.0-alpha.26
8
8
  */
9
9
  /*
10
10
  * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
@@ -84,7 +84,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
84
84
  \*******************************/
85
85
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
86
86
 
87
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Bubble: () => (/* reexport safe */ _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__.Bubble),\n/* harmony export */ BubbleBase: () => (/* reexport safe */ _Options_Classes_BubbleBase_js__WEBPACK_IMPORTED_MODULE_0__.BubbleBase),\n/* harmony export */ BubbleDiv: () => (/* reexport safe */ _Options_Classes_BubbleDiv_js__WEBPACK_IMPORTED_MODULE_1__.BubbleDiv),\n/* harmony export */ loadExternalBubbleInteraction: () => (/* binding */ loadExternalBubbleInteraction)\n/* harmony export */ });\n/* harmony import */ var _Options_Classes_BubbleBase_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Options/Classes/BubbleBase.js */ \"./dist/browser/Options/Classes/BubbleBase.js\");\n/* harmony import */ var _Options_Classes_BubbleDiv_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Options/Classes/BubbleDiv.js */ \"./dist/browser/Options/Classes/BubbleDiv.js\");\n/* harmony import */ var _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Bubble.js */ \"./dist/browser/Options/Classes/Bubble.js\");\nasync function loadExternalBubbleInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.24\");\n await engine.register(async (e)=>{\n const { ensureInteractivityPluginLoaded } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\", 19));\n ensureInteractivityPluginLoaded(e);\n e.addInteractor?.(\"externalBubble\", async (container)=>{\n const { Bubbler } = await __webpack_require__.e(/*! import() */ \"dist_browser_Bubbler_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./Bubbler.js */ \"./dist/browser/Bubbler.js\"));\n return new Bubbler(e, container);\n });\n });\n}\n\n\n\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-bubble/./dist/browser/index.js?\n}");
87
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Bubble: () => (/* reexport safe */ _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__.Bubble),\n/* harmony export */ BubbleBase: () => (/* reexport safe */ _Options_Classes_BubbleBase_js__WEBPACK_IMPORTED_MODULE_0__.BubbleBase),\n/* harmony export */ BubbleDiv: () => (/* reexport safe */ _Options_Classes_BubbleDiv_js__WEBPACK_IMPORTED_MODULE_1__.BubbleDiv),\n/* harmony export */ loadExternalBubbleInteraction: () => (/* binding */ loadExternalBubbleInteraction)\n/* harmony export */ });\n/* harmony import */ var _Options_Classes_BubbleBase_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Options/Classes/BubbleBase.js */ \"./dist/browser/Options/Classes/BubbleBase.js\");\n/* harmony import */ var _Options_Classes_BubbleDiv_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Options/Classes/BubbleDiv.js */ \"./dist/browser/Options/Classes/BubbleDiv.js\");\n/* harmony import */ var _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Bubble.js */ \"./dist/browser/Options/Classes/Bubble.js\");\nasync function loadExternalBubbleInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.26\");\n await engine.register(async (e)=>{\n const { ensureInteractivityPluginLoaded } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\", 19));\n ensureInteractivityPluginLoaded(e);\n e.addInteractor?.(\"externalBubble\", async (container)=>{\n const { Bubbler } = await __webpack_require__.e(/*! import() */ \"dist_browser_Bubbler_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./Bubbler.js */ \"./dist/browser/Bubbler.js\"));\n return new Bubbler(e, container);\n });\n });\n}\n\n\n\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-bubble/./dist/browser/index.js?\n}");
88
88
 
89
89
  /***/ }
90
90
 
@@ -1,2 +1,2 @@
1
- !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine","@tsparticles/plugin-interactivity"],t);else{var r="object"==typeof exports?t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity")):t(e.window,e.window);for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(this,(e,t)=>(()=>{"use strict";var r,i,o,n={303(t){t.exports=e},702(e){e.exports=t},804(e,t,r){r.d(t,{Z:()=>a});var i=r(303),o=r(245),n=r(213);class a extends o.u{divs;load(e){super.load(e),(0,i.isNull)(e)||(this.divs=(0,i.executeOnSingleOrMultiple)(e.divs,e=>{let t=new n.C;return t.load(e),t}))}}},245(e,t,r){r.d(t,{u:()=>o});var i=r(303);class o{color;distance;duration;mix;opacity;size;constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(e){if(!(0,i.isNull)(e)){if(void 0!==e.distance&&(this.distance=e.distance),void 0!==e.duration&&(this.duration=e.duration),void 0!==e.mix&&(this.mix=e.mix),void 0!==e.opacity&&(this.opacity=e.opacity),void 0!==e.color){let t=(0,i.isArray)(this.color)?void 0:this.color;this.color=(0,i.executeOnSingleOrMultiple)(e.color,e=>i.OptionsColor.create(t,e))}void 0!==e.size&&(this.size=e.size)}}}},213(e,t,r){r.d(t,{C:()=>n});var i=r(303),o=r(245);class n extends o.u{selectors;constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,i.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}}},a={};function s(e){var t=a[e];if(void 0!==t)return t.exports;var r=a[e]={exports:{}};return n[e](r,r.exports,s),r.exports}s.m=n,c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,s.t=function(e,t){if(1&t&&(e=this(e)),8&t||"object"==typeof e&&e&&(4&t&&e.__esModule||16&t&&"function"==typeof e.then))return e;var r=Object.create(null);s.r(r);var i={};l=l||[null,c({}),c([]),c(c)];for(var o=2&t&&e;("object"==typeof o||"function"==typeof o)&&!~l.indexOf(o);o=c(o))Object.getOwnPropertyNames(o).forEach(t=>i[t]=()=>e[t]);return i.default=()=>e,s.d(r,i),r},s.d=(e,t)=>{for(var r in t)s.o(t,r)&&!s.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},s.f={},s.e=e=>Promise.all(Object.keys(s.f).reduce((t,r)=>(s.f[r](e,t),t),[])),s.u=e=>""+e+".min.js",s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),s.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),u={},s.l=(e,t,r,i)=>{if(u[e])return void u[e].push(t);if(void 0!==r)for(var o,n,a=document.getElementsByTagName("script"),l=0;l<a.length;l++){var c=a[l];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")=="@tsparticles/interaction-external-bubble:"+r){o=c;break}}o||(n=!0,(o=document.createElement("script")).charset="utf-8",s.nc&&o.setAttribute("nonce",s.nc),o.setAttribute("data-webpack","@tsparticles/interaction-external-bubble:"+r),o.src=e),u[e]=[t];var p=(t,r)=>{o.onerror=o.onload=null,clearTimeout(d);var i=u[e];if(delete u[e],o.parentNode&&o.parentNode.removeChild(o),i&&i.forEach(e=>e(r)),t)return t(r)},d=setTimeout(p.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=p.bind(null,o.onerror),o.onload=p.bind(null,o.onload),n&&document.head.appendChild(o)},s.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.g.importScripts&&(p=s.g.location+"");var l,c,u,p,d=s.g.document;if(!p&&d&&(d.currentScript&&"SCRIPT"===d.currentScript.tagName.toUpperCase()&&(p=d.currentScript.src),!p)){var b=d.getElementsByTagName("script");if(b.length)for(var f=b.length-1;f>-1&&(!p||!/^http(s?):/.test(p));)p=b[f--].src}if(!p)throw Error("Automatic publicPath is not supported in this browser");s.p=p=p.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r={108:0},s.f.j=(e,t)=>{var i=s.o(r,e)?r[e]:void 0;if(0!==i)if(i)t.push(i[2]);else{var o=new Promise((t,o)=>i=r[e]=[t,o]);t.push(i[2]=o);var n=s.p+s.u(e),a=Error();s.l(n,t=>{if(s.o(r,e)&&(0!==(i=r[e])&&(r[e]=void 0),i)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;a.message="Loading chunk "+e+` failed.
2
- (`+o+": "+n+")",a.name="ChunkLoadError",a.type=o,a.request=n,i[1](a)}},"chunk-"+e,e)}},i=(e,t)=>{var i,o,[n,a,l]=t,c=0;if(n.some(e=>0!==r[e])){for(i in a)s.o(a,i)&&(s.m[i]=a[i]);l&&l(s)}for(e&&e(t);c<n.length;c++)o=n[c],s.o(r,o)&&r[o]&&r[o][0](),r[o]=0},(o=this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[]).forEach(i.bind(null,0)),o.push=i.bind(null,o.push.bind(o));var h={};s.r(h),s.d(h,{Bubble:()=>g.Z,BubbleBase:()=>v.u,BubbleDiv:()=>y.C,loadExternalBubbleInteraction:()=>m});var v=s(245),y=s(213),g=s(804);async function m(e){e.checkVersion("4.0.0-alpha.24"),await e.register(async e=>{let{ensureInteractivityPluginLoaded:t}=await Promise.resolve().then(s.t.bind(s,702,19));t(e),e.addInteractor?.("externalBubble",async t=>{let{Bubbler:r}=await s.e(896).then(s.bind(s,896));return new r(e,t)})})}return h})());
1
+ !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine","@tsparticles/plugin-interactivity"],t);else{var r="object"==typeof exports?t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity")):t(e.window,e.window);for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(this,(e,t)=>(()=>{"use strict";var r,i,o,n={303(t){t.exports=e},702(e){e.exports=t},512(e,t,r){r.d(t,{Z:()=>a});var i=r(303),o=r(633),n=r(81);class a extends o.u{divs;load(e){super.load(e),(0,i.isNull)(e)||(this.divs=(0,i.executeOnSingleOrMultiple)(e.divs,e=>{let t=new n.C;return t.load(e),t}))}}},633(e,t,r){r.d(t,{u:()=>o});var i=r(303);class o{color;distance;duration;mix;opacity;size;constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(e){if(!(0,i.isNull)(e)){if(void 0!==e.distance&&(this.distance=e.distance),void 0!==e.duration&&(this.duration=e.duration),void 0!==e.mix&&(this.mix=e.mix),void 0!==e.opacity&&(this.opacity=e.opacity),void 0!==e.color){let t=(0,i.isArray)(this.color)?void 0:this.color;this.color=(0,i.executeOnSingleOrMultiple)(e.color,e=>i.OptionsColor.create(t,e))}void 0!==e.size&&(this.size=e.size)}}}},81(e,t,r){r.d(t,{C:()=>n});var i=r(303),o=r(633);class n extends o.u{selectors;constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,i.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}}},a={};function s(e){var t=a[e];if(void 0!==t)return t.exports;var r=a[e]={exports:{}};return n[e](r,r.exports,s),r.exports}s.m=n,c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,s.t=function(e,t){if(1&t&&(e=this(e)),8&t||"object"==typeof e&&e&&(4&t&&e.__esModule||16&t&&"function"==typeof e.then))return e;var r=Object.create(null);s.r(r);var i={};l=l||[null,c({}),c([]),c(c)];for(var o=2&t&&e;("object"==typeof o||"function"==typeof o)&&!~l.indexOf(o);o=c(o))Object.getOwnPropertyNames(o).forEach(t=>i[t]=()=>e[t]);return i.default=()=>e,s.d(r,i),r},s.d=(e,t)=>{for(var r in t)s.o(t,r)&&!s.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},s.f={},s.e=e=>Promise.all(Object.keys(s.f).reduce((t,r)=>(s.f[r](e,t),t),[])),s.u=e=>""+e+".min.js",s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),s.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),u={},s.l=(e,t,r,i)=>{if(u[e])return void u[e].push(t);if(void 0!==r)for(var o,n,a=document.getElementsByTagName("script"),l=0;l<a.length;l++){var c=a[l];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")=="@tsparticles/interaction-external-bubble:"+r){o=c;break}}o||(n=!0,(o=document.createElement("script")).charset="utf-8",s.nc&&o.setAttribute("nonce",s.nc),o.setAttribute("data-webpack","@tsparticles/interaction-external-bubble:"+r),o.src=e),u[e]=[t];var p=(t,r)=>{o.onerror=o.onload=null,clearTimeout(d);var i=u[e];if(delete u[e],o.parentNode&&o.parentNode.removeChild(o),i&&i.forEach(e=>e(r)),t)return t(r)},d=setTimeout(p.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=p.bind(null,o.onerror),o.onload=p.bind(null,o.onload),n&&document.head.appendChild(o)},s.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.g.importScripts&&(p=s.g.location+"");var l,c,u,p,d=s.g.document;if(!p&&d&&(d.currentScript&&"SCRIPT"===d.currentScript.tagName.toUpperCase()&&(p=d.currentScript.src),!p)){var b=d.getElementsByTagName("script");if(b.length)for(var f=b.length-1;f>-1&&(!p||!/^http(s?):/.test(p));)p=b[f--].src}if(!p)throw Error("Automatic publicPath is not supported in this browser");s.p=p=p.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r={108:0},s.f.j=(e,t)=>{var i=s.o(r,e)?r[e]:void 0;if(0!==i)if(i)t.push(i[2]);else{var o=new Promise((t,o)=>i=r[e]=[t,o]);t.push(i[2]=o);var n=s.p+s.u(e),a=Error();s.l(n,t=>{if(s.o(r,e)&&(0!==(i=r[e])&&(r[e]=void 0),i)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;a.message="Loading chunk "+e+` failed.
2
+ (`+o+": "+n+")",a.name="ChunkLoadError",a.type=o,a.request=n,i[1](a)}},"chunk-"+e,e)}},i=(e,t)=>{var i,o,[n,a,l]=t,c=0;if(n.some(e=>0!==r[e])){for(i in a)s.o(a,i)&&(s.m[i]=a[i]);l&&l(s)}for(e&&e(t);c<n.length;c++)o=n[c],s.o(r,o)&&r[o]&&r[o][0](),r[o]=0},(o=this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[]).forEach(i.bind(null,0)),o.push=i.bind(null,o.push.bind(o));var h={};s.r(h),s.d(h,{Bubble:()=>g.Z,BubbleBase:()=>v.u,BubbleDiv:()=>y.C,loadExternalBubbleInteraction:()=>m});var v=s(633),y=s(81),g=s(512);async function m(e){e.checkVersion("4.0.0-alpha.26"),await e.register(async e=>{let{ensureInteractivityPluginLoaded:t}=await Promise.resolve().then(s.t.bind(s,702,19));t(e),e.addInteractor?.("externalBubble",async t=>{let{Bubbler:r}=await s.e(602).then(s.bind(s,602));return new r(e,t)})})}return h})());
@@ -4,7 +4,9 @@ import { ExternalInteractorBase, type IInteractivityData, type IModes, type Inte
4
4
  export declare class Bubbler extends ExternalInteractorBase<BubbleContainer> {
5
5
  handleClickMode: (mode: string, interactivityData: IInteractivityData) => void;
6
6
  private readonly _engine;
7
+ private _maxDistance;
7
8
  constructor(engine: Engine, container: BubbleContainer);
9
+ get maxDistance(): number;
8
10
  clear(particle: Particle, _delta: IDelta, force?: boolean): void;
9
11
  init(): void;
10
12
  interact(interactivityData: IInteractivityData, delta: IDelta): void;
package/umd/Bubbler.js CHANGED
@@ -19,9 +19,11 @@
19
19
  class Bubbler extends plugin_interactivity_1.ExternalInteractorBase {
20
20
  handleClickMode;
21
21
  _engine;
22
+ _maxDistance;
22
23
  constructor(engine, container) {
23
24
  super(container);
24
25
  this._engine = engine;
26
+ this._maxDistance = 0;
25
27
  container.bubble ??= {};
26
28
  this.handleClickMode = (mode) => {
27
29
  if (mode !== bubbleMode) {
@@ -31,6 +33,9 @@
31
33
  container.bubble.clicking = true;
32
34
  };
33
35
  }
36
+ get maxDistance() {
37
+ return this._maxDistance;
38
+ }
34
39
  clear(particle, _delta, force) {
35
40
  if (particle.bubble.inRange && !force) {
36
41
  return;
@@ -45,6 +50,7 @@
45
50
  if (!bubble) {
46
51
  return;
47
52
  }
53
+ this._maxDistance = bubble.distance;
48
54
  container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;
49
55
  if (bubble.size !== undefined) {
50
56
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
@@ -98,7 +104,7 @@
98
104
  if (!distance || distance < minDistance) {
99
105
  return;
100
106
  }
101
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
107
+ const query = container.particles.grid.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
102
108
  for (const particle of query) {
103
109
  if (!bubble.clicking) {
104
110
  continue;
@@ -149,7 +155,7 @@
149
155
  if (!distance || distance < minDistance || !mousePos) {
150
156
  return;
151
157
  }
152
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
158
+ const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
153
159
  for (const particle of query) {
154
160
  particle.bubble.inRange = true;
155
161
  const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
@@ -269,7 +275,7 @@
269
275
  y: (elem.offsetTop + elem.offsetHeight * engine_1.half) * pxRatio,
270
276
  }, repulseRadius = elem.offsetWidth * engine_1.half * pxRatio, area = div.type === plugin_interactivity_1.DivType.circle
271
277
  ? new engine_1.Circle(pos.x, pos.y, repulseRadius)
272
- : new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p));
278
+ : new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p));
273
279
  for (const particle of query) {
274
280
  if (!area.contains(particle.getPosition())) {
275
281
  continue;
package/umd/index.js CHANGED
@@ -48,7 +48,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
49
  exports.loadExternalBubbleInteraction = loadExternalBubbleInteraction;
50
50
  async function loadExternalBubbleInteraction(engine) {
51
- engine.checkVersion("4.0.0-alpha.24");
51
+ engine.checkVersion("4.0.0-alpha.26");
52
52
  await engine.register(async (e) => {
53
53
  const { ensureInteractivityPluginLoaded } = await (__syncRequire ? Promise.resolve().then(() => __importStar(require("@tsparticles/plugin-interactivity"))) : new Promise((resolve_1, reject_1) => { require(["@tsparticles/plugin-interactivity"], resolve_1, reject_1); }).then(__importStar));
54
54
  ensureInteractivityPluginLoaded(e);
package/896.min.js DELETED
@@ -1 +0,0 @@
1
- "use strict";(this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[]).push([[896],{896(e,i,t){t.d(i,{Bubbler:()=>u});var l,b,o=t(303),a=t(702),n=t(804);function r(e,i,t,l){return i>=t?(0,o.clamp)(e+(i-t)*l,e,i):i<t?(0,o.clamp)(e-(t-i)*l,i,e):void 0}(l=b||(b={})).color="color",l.opacity="opacity",l.size="size";let s="bubble";class u extends a.ExternalInteractorBase{handleClickMode;_engine;constructor(e,i){super(i),this._engine=e,i.bubble??={},this.handleClickMode=e=>{e===s&&(i.bubble??={},i.bubble.clicking=!0)}}clear(e,i,t){(!e.bubble.inRange||t)&&(delete e.bubble.div,delete e.bubble.opacity,delete e.bubble.radius,delete e.bubble.color)}init(){let e=this.container,i=e.actualOptions.interactivity?.modes.bubble;i&&(e.retina.bubbleModeDistance=i.distance*e.retina.pixelRatio,void 0!==i.size&&(e.retina.bubbleModeSize=i.size*e.retina.pixelRatio))}interact(e,i){let t=this.container.actualOptions,l=t.interactivity?.events;if(!l)return;let b=l.onHover,n=l.onClick,r=b.enable,u=b.mode,c=n.enable,d=n.mode,p=l.onDiv;r&&(0,o.isInArray)(s,u)?this._hoverBubble(e):c&&(0,o.isInArray)(s,d)?this._clickBubble(e):(0,a.divModeExecute)(s,p,(t,l)=>{this._singleSelectorHover(e,i,t,l)})}isEnabled(e,i){let t=this.container.actualOptions,l=e.mouse,b=(i?.interactivity??t.interactivity)?.events;if(!b)return!1;let{onClick:n,onDiv:r,onHover:u}=b,c=(0,a.isDivModeEnabled)(s,r);return!!(c||u.enable&&l.position||n.enable&&l.clickPosition)&&((0,o.isInArray)(s,u.mode)||(0,o.isInArray)(s,n.mode)||c)}loadModeOptions(e,...i){for(let t of(e.bubble??=new n.Z,i))e.bubble.load(t?.bubble)}reset(e,i){i.bubble.inRange=!1}_clickBubble=e=>{let i=this.container,t=i.actualOptions,l=e.mouse.clickPosition,a=t.interactivity?.modes.bubble;if(!a||!l)return;i.bubble??={};let n=i.retina.bubbleModeDistance;if(!n||n<0)return;let r=i.particles.quadTree.queryCircle(l,n,i=>this.isEnabled(e,i)),{bubble:s}=i;for(let t of r){if(!s.clicking)continue;t.bubble.inRange=!s.durationEnd;let r=t.getPosition(),u=(0,o.getDistance)(r,l),c=(performance.now()-(e.mouse.clickTime??0))/o.millisecondsToSeconds;c>a.duration&&(s.durationEnd=!0),c>a.duration*o.double&&(s.clicking=!1,s.durationEnd=!1);let d={bubbleObj:{optValue:i.retina.bubbleModeSize,value:t.bubble.radius},particlesObj:{optValue:(0,o.getRangeMax)(t.options.size.value)*i.retina.pixelRatio,value:t.size.value},type:b.size};this._process(t,u,c,d);let p={bubbleObj:{optValue:a.opacity,value:t.bubble.opacity},particlesObj:{optValue:(0,o.getRangeMax)(t.options.opacity.value),value:t.opacity?.value??1},type:b.opacity};this._process(t,u,c,p),!s.durationEnd&&u<=n?this._hoverBubbleColor(t,u):delete t.bubble.color}};_hoverBubble=e=>{let i=this.container,t=e.mouse.position,l=i.retina.bubbleModeDistance;if(l&&!(l<0)&&t)for(let b of i.particles.quadTree.queryCircle(t,l,i=>this.isEnabled(e,i))){b.bubble.inRange=!0;let i=b.getPosition(),n=(0,o.getDistance)(i,t),r=1-n/l;n<=l?r>=0&&e.status===a.mouseMoveEvent&&(this._hoverBubbleSize(b,r),this._hoverBubbleOpacity(b,r),this._hoverBubbleColor(b,r)):this.reset(e,b),e.status===a.mouseLeaveEvent&&this.reset(e,b)}};_hoverBubbleColor=(e,i,t)=>{let l=this.container.actualOptions,b=t??l.interactivity?.modes.bubble;if(b){if(!e.bubble.finalColor){let i=b.color;if(!i)return;let t=(0,o.itemFromSingleOrMultiple)(i);e.bubble.finalColor=(0,o.rangeColorToHsl)(this._engine,t)}if(e.bubble.finalColor)if(b.mix){e.bubble.color=void 0;let t=e.getFillColor();e.bubble.color=t?(0,o.rgbToHsl)((0,o.colorMix)(t,e.bubble.finalColor,1-i,i)):e.bubble.finalColor}else e.bubble.color=e.bubble.finalColor}};_hoverBubbleOpacity=(e,i,t)=>{let l=this.container.actualOptions,b=t?.opacity??l.interactivity?.modes.bubble?.opacity;if(!b)return;let a=e.options.opacity.value,n=r(e.opacity?.value??1,b,(0,o.getRangeMax)(a),i);void 0!==n&&(e.bubble.opacity=n)};_hoverBubbleSize=(e,i,t)=>{let l=this.container,b=t?.size?t.size*l.retina.pixelRatio:l.retina.bubbleModeSize;if(void 0===b)return;let a=(0,o.getRangeMax)(e.options.size.value)*l.retina.pixelRatio,n=r(e.size.value,b,a,i);void 0!==n&&(e.bubble.radius=n)};_process=(e,i,t,l)=>{let o=this.container,a=l.bubbleObj.optValue,n=o.actualOptions,r=n.interactivity?.modes.bubble;if(!r||void 0===a)return;let s=r.duration,u=o.retina.bubbleModeDistance,c=l.particlesObj.optValue,d=l.bubbleObj.value,p=l.particlesObj.value??0,v=l.type;if(u&&!(u<0)&&a!==c)if(o.bubble??={},o.bubble.durationEnd)d&&(v===b.size&&delete e.bubble.radius,v===b.opacity&&delete e.bubble.opacity);else if(i<=u){if((d??p)!==a){let i=p-t*(p-a)/s;v===b.size&&(e.bubble.radius=i),v===b.opacity&&(e.bubble.opacity=i)}}else v===b.size&&delete e.bubble.radius,v===b.opacity&&delete e.bubble.opacity};_singleSelectorHover=(e,i,t,l)=>{let b=this.container,n=(0,o.safeDocument)().querySelectorAll(t),r=b.actualOptions.interactivity?.modes.bubble;r&&n.length&&n.forEach(t=>{let n=b.retina.pixelRatio,s={x:(t.offsetLeft+t.offsetWidth*o.half)*n,y:(t.offsetTop+t.offsetHeight*o.half)*n},u=t.offsetWidth*o.half*n,c=l.type===a.DivType.circle?new o.Circle(s.x,s.y,u):new o.Rectangle(t.offsetLeft*n,t.offsetTop*n,t.offsetWidth*n,t.offsetHeight*n);for(let l of b.particles.quadTree.query(c,i=>this.isEnabled(e,i))){if(!c.contains(l.getPosition()))continue;l.bubble.inRange=!0;let e=r.divs,b=(0,a.divMode)(e,t);l.bubble.div&&l.bubble.div===t||(this.clear(l,i,!0),l.bubble.div=t),this._hoverBubbleSize(l,1,b),this._hoverBubbleOpacity(l,1,b),this._hoverBubbleColor(l,1,b)}})}}}}]);