@tsparticles/interaction-external-bubble 4.0.0-alpha.2 → 4.0.0-alpha.4

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/132.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 132.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[]).push([[132],{132(e,i,t){t.d(i,{Bubbler:()=>r});var o,b=t(303),n=t(702),l=t(443);function s(e,i,t,o){if(i>=t){const n=e+(i-t)*o;return(0,b.clamp)(n,e,i)}if(i<t){const n=e-(t-i)*o;return(0,b.clamp)(n,i,e)}}!function(e){e.color="color",e.opacity="opacity",e.size="size"}(o||(o={}));const a="bubble";class r extends n.ExternalInteractorBase{constructor(e,i){super(i),this._clickBubble=e=>{const i=this.container,t=i.actualOptions,n=e.mouse.clickPosition,l=t.interactivity?.modes.bubble;if(!l||!n)return;i.bubble??={};const s=i.retina.bubbleModeDistance;if(!s||s<0)return;const a=i.particles.quadTree.queryCircle(n,s,(i=>this.isEnabled(e,i))),{bubble:r}=i;for(const t of a){if(!r.clicking)continue;t.bubble.inRange=!r.durationEnd;const a=t.getPosition(),c=(0,b.getDistance)(a,n),u=((new Date).getTime()-(e.mouse.clickTime??0))/b.millisecondsToSeconds;u>l.duration&&(r.durationEnd=!0),u>l.duration*b.double&&(r.clicking=!1,r.durationEnd=!1);const d={bubbleObj:{optValue:i.retina.bubbleModeSize,value:t.bubble.radius},particlesObj:{optValue:(0,b.getRangeMax)(t.options.size.value)*i.retina.pixelRatio,value:t.size.value},type:o.size};this._process(t,c,u,d);const p={bubbleObj:{optValue:l.opacity,value:t.bubble.opacity},particlesObj:{optValue:(0,b.getRangeMax)(t.options.opacity.value),value:t.opacity?.value??1},type:o.opacity};this._process(t,c,u,p),!r.durationEnd&&c<=s?this._hoverBubbleColor(t,c):delete t.bubble.color}},this._hoverBubble=e=>{const i=this.container,t=e.mouse.position,o=i.retina.bubbleModeDistance;if(!o||o<0||!t)return;const l=i.particles.quadTree.queryCircle(t,o,(i=>this.isEnabled(e,i)));for(const i of l){i.bubble.inRange=!0;const l=i.getPosition(),s=(0,b.getDistance)(l,t),a=1-s/o;s<=o?a>=0&&e.status===n.mouseMoveEvent&&(this._hoverBubbleSize(i,a),this._hoverBubbleOpacity(i,a),this._hoverBubbleColor(i,a)):this.reset(e,i),e.status===n.mouseLeaveEvent&&this.reset(e,i)}},this._hoverBubbleColor=(e,i,t)=>{const o=this.container.actualOptions,n=t??o.interactivity?.modes.bubble;if(n){if(!e.bubble.finalColor){const i=n.color;if(!i)return;const t=(0,b.itemFromSingleOrMultiple)(i);e.bubble.finalColor=(0,b.rangeColorToHsl)(this._engine,t)}if(e.bubble.finalColor)if(n.mix){e.bubble.color=void 0;const t=e.getFillColor();e.bubble.color=t?(0,b.rgbToHsl)((0,b.colorMix)(t,e.bubble.finalColor,1-i,i)):e.bubble.finalColor}else e.bubble.color=e.bubble.finalColor}},this._hoverBubbleOpacity=(e,i,t)=>{const o=this.container.actualOptions,n=t?.opacity??o.interactivity?.modes.bubble?.opacity;if(!n)return;const l=e.options.opacity.value,a=s(e.opacity?.value??1,n,(0,b.getRangeMax)(l),i);void 0!==a&&(e.bubble.opacity=a)},this._hoverBubbleSize=(e,i,t)=>{const o=this.container,n=t?.size?t.size*o.retina.pixelRatio:o.retina.bubbleModeSize;if(void 0===n)return;const l=(0,b.getRangeMax)(e.options.size.value)*o.retina.pixelRatio,a=s(e.size.value,n,l,i);void 0!==a&&(e.bubble.radius=a)},this._process=(e,i,t,b)=>{const n=this.container,l=b.bubbleObj.optValue,s=n.actualOptions,a=s.interactivity?.modes.bubble;if(!a||void 0===l)return;const r=a.duration,c=n.retina.bubbleModeDistance,u=b.particlesObj.optValue,d=b.bubbleObj.value,p=b.particlesObj.value??0,h=b.type;if(c&&!(c<0)&&l!==u)if(n.bubble??={},n.bubble.durationEnd)d&&(h===o.size&&delete e.bubble.radius,h===o.opacity&&delete e.bubble.opacity);else if(i<=c){if((d??p)!==l){const i=p-t*(p-l)/r;h===o.size&&(e.bubble.radius=i),h===o.opacity&&(e.bubble.opacity=i)}}else h===o.size&&delete e.bubble.radius,h===o.opacity&&delete e.bubble.opacity},this._singleSelectorHover=(e,i,t,o)=>{const l=this.container,s=(0,b.safeDocument)().querySelectorAll(t),a=l.actualOptions.interactivity?.modes.bubble;a&&s.length&&s.forEach((t=>{const s=t,r=l.retina.pixelRatio,c={x:(s.offsetLeft+s.offsetWidth*b.half)*r,y:(s.offsetTop+s.offsetHeight*b.half)*r},u=s.offsetWidth*b.half*r,d=o.type===n.DivType.circle?new b.Circle(c.x,c.y,u):new b.Rectangle(s.offsetLeft*r,s.offsetTop*r,s.offsetWidth*r,s.offsetHeight*r),p=l.particles.quadTree.query(d,(i=>this.isEnabled(e,i)));for(const e of p){if(!d.contains(e.getPosition()))continue;e.bubble.inRange=!0;const t=a.divs,o=(0,n.divMode)(t,s);e.bubble.div&&e.bubble.div===s||(this.clear(e,i,!0),e.bubble.div=s),this._hoverBubbleSize(e,1,o),this._hoverBubbleOpacity(e,1,o),this._hoverBubbleColor(e,1,o)}}))},this._engine=e,i.bubble??={},this.handleClickMode=e=>{e===a&&(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(){const 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){const t=this.container.actualOptions,o=t.interactivity?.events;if(!o)return;const l=o.onHover,s=o.onClick,r=l.enable,c=l.mode,u=s.enable,d=s.mode,p=o.onDiv;r&&(0,b.isInArray)(a,c)?this._hoverBubble(e):u&&(0,b.isInArray)(a,d)?this._clickBubble(e):(0,n.divModeExecute)(a,p,((t,o)=>{this._singleSelectorHover(e,i,t,o)}))}isEnabled(e,i){const t=this.container.actualOptions,o=e.mouse,l=(i?.interactivity??t.interactivity)?.events;if(!l)return!1;const{onClick:s,onDiv:r,onHover:c}=l,u=(0,n.isDivModeEnabled)(a,r);return!!(u||c.enable&&o.position||s.enable&&o.clickPosition)&&((0,b.isInArray)(a,c.mode)||(0,b.isInArray)(a,s.mode)||u)}loadModeOptions(e,...i){e.bubble??=new l.Z;for(const t of i)e.bubble.load(t?.bubble)}reset(e,i){i.bubble.inRange=!1}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Bubble External Interaction v4.0.0-alpha.4 by Matteo Bruni */
@@ -1,13 +1,14 @@
1
- import { Circle, DivType, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, safeDocument, } from "@tsparticles/engine";
1
+ import { Circle, Rectangle, colorMix, double, getDistance, getRangeMax, half, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, rangeColorToHsl, rgbToHsl, safeDocument, } from "@tsparticles/engine";
2
+ import { DivType, ExternalInteractorBase, divMode, divModeExecute, isDivModeEnabled, mouseLeaveEvent, mouseMoveEvent, } from "@tsparticles/plugin-interactivity";
2
3
  import { Bubble } from "./Options/Classes/Bubble.js";
3
4
  import { ProcessBubbleType } from "./Enums.js";
4
5
  import { calculateBubbleValue } from "./Utils.js";
5
- const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
6
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, defaultRatio = 1;
6
7
  export class Bubbler extends ExternalInteractorBase {
7
8
  constructor(engine, container) {
8
9
  super(container);
9
- this._clickBubble = () => {
10
- const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
10
+ this._clickBubble = interactivityData => {
11
+ const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
11
12
  if (!bubbleOptions || !mouseClickPos) {
12
13
  return;
13
14
  }
@@ -16,13 +17,13 @@ export class Bubbler extends ExternalInteractorBase {
16
17
  if (!distance || distance < minDistance) {
17
18
  return;
18
19
  }
19
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p)), { bubble } = container;
20
+ const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
20
21
  for (const particle of query) {
21
22
  if (!bubble.clicking) {
22
23
  continue;
23
24
  }
24
25
  particle.bubble.inRange = !bubble.durationEnd;
25
- const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
26
+ const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (interactivityData.mouse.clickTime ?? defaultClickTime)) /
26
27
  millisecondsToSeconds;
27
28
  if (timeSpent > bubbleOptions.duration) {
28
29
  bubble.durationEnd = true;
@@ -63,32 +64,32 @@ export class Bubbler extends ExternalInteractorBase {
63
64
  }
64
65
  }
65
66
  };
66
- this._hoverBubble = () => {
67
- const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
67
+ this._hoverBubble = interactivityData => {
68
+ const container = this.container, mousePos = interactivityData.mouse.position, distance = container.retina.bubbleModeDistance;
68
69
  if (!distance || distance < minDistance || !mousePos) {
69
70
  return;
70
71
  }
71
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
72
+ const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
72
73
  for (const particle of query) {
73
74
  particle.bubble.inRange = true;
74
75
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
75
76
  if (pointDistance <= distance) {
76
- if (ratio >= minRatio && container.interactivity.status === mouseMoveEvent) {
77
+ if (ratio >= minRatio && interactivityData.status === mouseMoveEvent) {
77
78
  this._hoverBubbleSize(particle, ratio);
78
79
  this._hoverBubbleOpacity(particle, ratio);
79
80
  this._hoverBubbleColor(particle, ratio);
80
81
  }
81
82
  }
82
83
  else {
83
- this.reset(particle);
84
+ this.reset(interactivityData, particle);
84
85
  }
85
- if (container.interactivity.status === mouseLeaveEvent) {
86
- this.reset(particle);
86
+ if (interactivityData.status === mouseLeaveEvent) {
87
+ this.reset(interactivityData, particle);
87
88
  }
88
89
  }
89
90
  };
90
91
  this._hoverBubbleColor = (particle, ratio, divBubble) => {
91
- const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
92
+ const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;
92
93
  if (!bubbleOptions) {
93
94
  return;
94
95
  }
@@ -115,7 +116,7 @@ export class Bubbler extends ExternalInteractorBase {
115
116
  }
116
117
  };
117
118
  this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
118
- const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
119
+ const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;
119
120
  if (!modeOpacity) {
120
121
  return;
121
122
  }
@@ -135,7 +136,7 @@ export class Bubbler extends ExternalInteractorBase {
135
136
  }
136
137
  };
137
138
  this._process = (particle, distMouse, timeSpent, data) => {
138
- const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
139
+ const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity?.modes.bubble;
139
140
  if (!bubbleOptions || bubbleParam === undefined) {
140
141
  return;
141
142
  }
@@ -177,8 +178,8 @@ export class Bubbler extends ExternalInteractorBase {
177
178
  }
178
179
  }
179
180
  };
180
- this._singleSelectorHover = (delta, selector, div) => {
181
- const container = this.container, selectors = safeDocument().querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
181
+ this._singleSelectorHover = (interactivityData, delta, selector, div) => {
182
+ const container = this.container, selectors = safeDocument().querySelectorAll(selector), bubble = container.actualOptions.interactivity?.modes.bubble;
182
183
  if (!bubble || !selectors.length) {
183
184
  return;
184
185
  }
@@ -188,7 +189,7 @@ export class Bubbler extends ExternalInteractorBase {
188
189
  y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
189
190
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
190
191
  ? new Circle(pos.x, pos.y, repulseRadius)
191
- : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, p => this.isEnabled(p));
192
+ : 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));
192
193
  for (const particle of query) {
193
194
  if (!area.contains(particle.getPosition())) {
194
195
  continue;
@@ -225,7 +226,7 @@ export class Bubbler extends ExternalInteractorBase {
225
226
  delete particle.bubble.color;
226
227
  }
227
228
  init() {
228
- const container = this.container, bubble = container.actualOptions.interactivity.modes.bubble;
229
+ const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
229
230
  if (!bubble) {
230
231
  return;
231
232
  }
@@ -234,22 +235,30 @@ export class Bubbler extends ExternalInteractorBase {
234
235
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
235
236
  }
236
237
  }
237
- interact(delta) {
238
- const options = this.container.actualOptions, events = options.interactivity.events, onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
238
+ interact(interactivityData, delta) {
239
+ const options = this.container.actualOptions, events = options.interactivity?.events;
240
+ if (!events) {
241
+ return;
242
+ }
243
+ const onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
239
244
  if (hoverEnabled && isInArray(bubbleMode, hoverMode)) {
240
- this._hoverBubble();
245
+ this._hoverBubble(interactivityData);
241
246
  }
242
247
  else if (clickEnabled && isInArray(bubbleMode, clickMode)) {
243
- this._clickBubble();
248
+ this._clickBubble(interactivityData);
244
249
  }
245
250
  else {
246
251
  divModeExecute(bubbleMode, divs, (selector, div) => {
247
- this._singleSelectorHover(delta, selector, div);
252
+ this._singleSelectorHover(interactivityData, delta, selector, div);
248
253
  });
249
254
  }
250
255
  }
251
- isEnabled(particle) {
252
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled(bubbleMode, onDiv);
256
+ isEnabled(interactivityData, particle) {
257
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
258
+ if (!events) {
259
+ return false;
260
+ }
261
+ const { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled(bubbleMode, onDiv);
253
262
  if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
254
263
  return false;
255
264
  }
@@ -261,7 +270,7 @@ export class Bubbler extends ExternalInteractorBase {
261
270
  options.bubble.load(source?.bubble);
262
271
  }
263
272
  }
264
- reset(particle) {
273
+ reset(_interactivityData, particle) {
265
274
  particle.bubble.inRange = false;
266
275
  }
267
276
  }
package/browser/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  export function loadExternalBubbleInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.2");
3
- engine.register(e => {
4
- e.addInteractor("externalBubble", async (container) => {
2
+ engine.checkVersion("4.0.0-alpha.4");
3
+ engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity");
5
+ loadInteractivityPlugin(e);
6
+ e.addInteractor?.("externalBubble", async (container) => {
5
7
  const { Bubbler } = await import("./Bubbler.js");
6
8
  return new Bubbler(e, container);
7
9
  });
package/cjs/Bubbler.js CHANGED
@@ -1,13 +1,14 @@
1
- import { Circle, DivType, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, safeDocument, } from "@tsparticles/engine";
1
+ import { Circle, Rectangle, colorMix, double, getDistance, getRangeMax, half, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, rangeColorToHsl, rgbToHsl, safeDocument, } from "@tsparticles/engine";
2
+ import { DivType, ExternalInteractorBase, divMode, divModeExecute, isDivModeEnabled, mouseLeaveEvent, mouseMoveEvent, } from "@tsparticles/plugin-interactivity";
2
3
  import { Bubble } from "./Options/Classes/Bubble.js";
3
4
  import { ProcessBubbleType } from "./Enums.js";
4
5
  import { calculateBubbleValue } from "./Utils.js";
5
- const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
6
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, defaultRatio = 1;
6
7
  export class Bubbler extends ExternalInteractorBase {
7
8
  constructor(engine, container) {
8
9
  super(container);
9
- this._clickBubble = () => {
10
- const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
10
+ this._clickBubble = interactivityData => {
11
+ const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
11
12
  if (!bubbleOptions || !mouseClickPos) {
12
13
  return;
13
14
  }
@@ -16,13 +17,13 @@ export class Bubbler extends ExternalInteractorBase {
16
17
  if (!distance || distance < minDistance) {
17
18
  return;
18
19
  }
19
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p)), { bubble } = container;
20
+ const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
20
21
  for (const particle of query) {
21
22
  if (!bubble.clicking) {
22
23
  continue;
23
24
  }
24
25
  particle.bubble.inRange = !bubble.durationEnd;
25
- const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
26
+ const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (interactivityData.mouse.clickTime ?? defaultClickTime)) /
26
27
  millisecondsToSeconds;
27
28
  if (timeSpent > bubbleOptions.duration) {
28
29
  bubble.durationEnd = true;
@@ -63,32 +64,32 @@ export class Bubbler extends ExternalInteractorBase {
63
64
  }
64
65
  }
65
66
  };
66
- this._hoverBubble = () => {
67
- const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
67
+ this._hoverBubble = interactivityData => {
68
+ const container = this.container, mousePos = interactivityData.mouse.position, distance = container.retina.bubbleModeDistance;
68
69
  if (!distance || distance < minDistance || !mousePos) {
69
70
  return;
70
71
  }
71
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
72
+ const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
72
73
  for (const particle of query) {
73
74
  particle.bubble.inRange = true;
74
75
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
75
76
  if (pointDistance <= distance) {
76
- if (ratio >= minRatio && container.interactivity.status === mouseMoveEvent) {
77
+ if (ratio >= minRatio && interactivityData.status === mouseMoveEvent) {
77
78
  this._hoverBubbleSize(particle, ratio);
78
79
  this._hoverBubbleOpacity(particle, ratio);
79
80
  this._hoverBubbleColor(particle, ratio);
80
81
  }
81
82
  }
82
83
  else {
83
- this.reset(particle);
84
+ this.reset(interactivityData, particle);
84
85
  }
85
- if (container.interactivity.status === mouseLeaveEvent) {
86
- this.reset(particle);
86
+ if (interactivityData.status === mouseLeaveEvent) {
87
+ this.reset(interactivityData, particle);
87
88
  }
88
89
  }
89
90
  };
90
91
  this._hoverBubbleColor = (particle, ratio, divBubble) => {
91
- const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
92
+ const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;
92
93
  if (!bubbleOptions) {
93
94
  return;
94
95
  }
@@ -115,7 +116,7 @@ export class Bubbler extends ExternalInteractorBase {
115
116
  }
116
117
  };
117
118
  this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
118
- const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
119
+ const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;
119
120
  if (!modeOpacity) {
120
121
  return;
121
122
  }
@@ -135,7 +136,7 @@ export class Bubbler extends ExternalInteractorBase {
135
136
  }
136
137
  };
137
138
  this._process = (particle, distMouse, timeSpent, data) => {
138
- const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
139
+ const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity?.modes.bubble;
139
140
  if (!bubbleOptions || bubbleParam === undefined) {
140
141
  return;
141
142
  }
@@ -177,8 +178,8 @@ export class Bubbler extends ExternalInteractorBase {
177
178
  }
178
179
  }
179
180
  };
180
- this._singleSelectorHover = (delta, selector, div) => {
181
- const container = this.container, selectors = safeDocument().querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
181
+ this._singleSelectorHover = (interactivityData, delta, selector, div) => {
182
+ const container = this.container, selectors = safeDocument().querySelectorAll(selector), bubble = container.actualOptions.interactivity?.modes.bubble;
182
183
  if (!bubble || !selectors.length) {
183
184
  return;
184
185
  }
@@ -188,7 +189,7 @@ export class Bubbler extends ExternalInteractorBase {
188
189
  y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
189
190
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
190
191
  ? new Circle(pos.x, pos.y, repulseRadius)
191
- : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, p => this.isEnabled(p));
192
+ : 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));
192
193
  for (const particle of query) {
193
194
  if (!area.contains(particle.getPosition())) {
194
195
  continue;
@@ -225,7 +226,7 @@ export class Bubbler extends ExternalInteractorBase {
225
226
  delete particle.bubble.color;
226
227
  }
227
228
  init() {
228
- const container = this.container, bubble = container.actualOptions.interactivity.modes.bubble;
229
+ const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
229
230
  if (!bubble) {
230
231
  return;
231
232
  }
@@ -234,22 +235,30 @@ export class Bubbler extends ExternalInteractorBase {
234
235
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
235
236
  }
236
237
  }
237
- interact(delta) {
238
- const options = this.container.actualOptions, events = options.interactivity.events, onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
238
+ interact(interactivityData, delta) {
239
+ const options = this.container.actualOptions, events = options.interactivity?.events;
240
+ if (!events) {
241
+ return;
242
+ }
243
+ const onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
239
244
  if (hoverEnabled && isInArray(bubbleMode, hoverMode)) {
240
- this._hoverBubble();
245
+ this._hoverBubble(interactivityData);
241
246
  }
242
247
  else if (clickEnabled && isInArray(bubbleMode, clickMode)) {
243
- this._clickBubble();
248
+ this._clickBubble(interactivityData);
244
249
  }
245
250
  else {
246
251
  divModeExecute(bubbleMode, divs, (selector, div) => {
247
- this._singleSelectorHover(delta, selector, div);
252
+ this._singleSelectorHover(interactivityData, delta, selector, div);
248
253
  });
249
254
  }
250
255
  }
251
- isEnabled(particle) {
252
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled(bubbleMode, onDiv);
256
+ isEnabled(interactivityData, particle) {
257
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
258
+ if (!events) {
259
+ return false;
260
+ }
261
+ const { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled(bubbleMode, onDiv);
253
262
  if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
254
263
  return false;
255
264
  }
@@ -261,7 +270,7 @@ export class Bubbler extends ExternalInteractorBase {
261
270
  options.bubble.load(source?.bubble);
262
271
  }
263
272
  }
264
- reset(particle) {
273
+ reset(_interactivityData, particle) {
265
274
  particle.bubble.inRange = false;
266
275
  }
267
276
  }
package/cjs/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  export function loadExternalBubbleInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.2");
3
- engine.register(e => {
4
- e.addInteractor("externalBubble", async (container) => {
2
+ engine.checkVersion("4.0.0-alpha.4");
3
+ engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity");
5
+ loadInteractivityPlugin(e);
6
+ e.addInteractor?.("externalBubble", async (container) => {
5
7
  const { Bubbler } = await import("./Bubbler.js");
6
8
  return new Bubbler(e, container);
7
9
  });
@@ -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.2
7
+ * v4.0.0-alpha.4
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 _Options_Classes_Bubble_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Options/Classes/Bubble.js */ \"./dist/browser/Options/Classes/Bubble.js\");\n/* harmony import */ var _Enums_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Enums.js */ \"./dist/browser/Enums.js\");\n/* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Utils.js */ \"./dist/browser/Utils.js\");\n\n\n\n\nconst bubbleMode = \"bubble\",\n minDistance = 0,\n defaultClickTime = 0,\n double = 2,\n defaultOpacity = 1,\n ratioOffset = 1,\n defaultBubbleValue = 0,\n minRatio = 0,\n half = 0.5,\n defaultRatio = 1;\nclass Bubbler extends _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.ExternalInteractorBase {\n constructor(engine, container) {\n super(container);\n this._clickBubble = () => {\n const container = this.container,\n options = container.actualOptions,\n mouseClickPos = container.interactivity.mouse.clickPosition,\n 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(p)),\n {\n bubble\n } = 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(),\n distMouse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mouseClickPos),\n timeSpent = (new Date().getTime() - (container.interactivity.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 * 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_2__.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_2__.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 this._hoverBubble = () => {\n const container = this.container,\n mousePos = container.interactivity.mouse.position,\n 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(p));\n for (const particle of query) {\n particle.bubble.inRange = true;\n const pos = particle.getPosition(),\n pointDistance = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mousePos),\n ratio = ratioOffset - pointDistance / distance;\n if (pointDistance <= distance) {\n if (ratio >= minRatio && container.interactivity.status === _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.mouseMoveEvent) {\n this._hoverBubbleSize(particle, ratio);\n this._hoverBubbleOpacity(particle, ratio);\n this._hoverBubbleColor(particle, ratio);\n }\n } else {\n this.reset(particle);\n }\n if (container.interactivity.status === _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.mouseLeaveEvent) {\n this.reset(particle);\n }\n }\n };\n this._hoverBubbleColor = (particle, ratio, divBubble) => {\n const options = this.container.actualOptions,\n 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 this._hoverBubbleOpacity = (particle, ratio, divBubble) => {\n const container = this.container,\n options = container.actualOptions,\n modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;\n if (!modeOpacity) {\n return;\n }\n const optOpacity = particle.options.opacity.value,\n pOpacity = particle.opacity?.value ?? defaultOpacity,\n opacity = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__.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 this._hoverBubbleSize = (particle, ratio, divBubble) => {\n const container = this.container,\n 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,\n pSize = particle.size.value,\n size = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__.calculateBubbleValue)(pSize, modeSize, optSize, ratio);\n if (size !== undefined) {\n particle.bubble.radius = size;\n }\n };\n this._process = (particle, distMouse, timeSpent, data) => {\n const container = this.container,\n bubbleParam = data.bubbleObj.optValue,\n options = container.actualOptions,\n bubbleOptions = options.interactivity.modes.bubble;\n if (!bubbleOptions || bubbleParam === undefined) {\n return;\n }\n const bubbleDuration = bubbleOptions.duration,\n bubbleDistance = container.retina.bubbleModeDistance,\n particlesParam = data.particlesObj.optValue,\n pObjBubble = data.bubbleObj.value,\n pObj = data.particlesObj.value ?? defaultBubbleValue,\n 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_2__.ProcessBubbleType.size) {\n delete particle.bubble.radius;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_2__.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_2__.ProcessBubbleType.size) {\n particle.bubble.radius = value;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_2__.ProcessBubbleType.opacity) {\n particle.bubble.opacity = value;\n }\n }\n } else {\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_2__.ProcessBubbleType.size) {\n delete particle.bubble.radius;\n }\n if (type === _Enums_js__WEBPACK_IMPORTED_MODULE_2__.ProcessBubbleType.opacity) {\n delete particle.bubble.opacity;\n }\n }\n }\n };\n this._singleSelectorHover = (delta, selector, div) => {\n const container = this.container,\n selectors = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.safeDocument)().querySelectorAll(selector),\n bubble = container.actualOptions.interactivity.modes.bubble;\n if (!bubble || !selectors.length) {\n return;\n }\n selectors.forEach(item => {\n const elem = item,\n pxRatio = container.retina.pixelRatio,\n pos = {\n x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio\n },\n repulseRadius = elem.offsetWidth * half * pxRatio,\n area = div.type === _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.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),\n query = container.particles.quadTree.query(area, p => this.isEnabled(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,\n divBubble = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.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 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,\n 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(delta) {\n const options = this.container.actualOptions,\n events = options.interactivity.events,\n onHover = events.onHover,\n onClick = events.onClick,\n hoverEnabled = onHover.enable,\n hoverMode = onHover.mode,\n clickEnabled = onClick.enable,\n clickMode = onClick.mode,\n divs = events.onDiv;\n if (hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, hoverMode)) {\n this._hoverBubble();\n } else if (clickEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(bubbleMode, clickMode)) {\n this._clickBubble();\n } else {\n (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.divModeExecute)(bubbleMode, divs, (selector, div) => {\n this._singleSelectorHover(delta, selector, div);\n });\n }\n }\n isEnabled(particle) {\n const container = this.container,\n options = container.actualOptions,\n mouse = container.interactivity.mouse,\n events = (particle?.interactivity ?? options.interactivity).events,\n {\n onClick,\n onDiv,\n onHover\n } = events,\n divBubble = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.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_1__.Bubble();\n for (const source of sources) {\n options.bubble.load(source?.bubble);\n }\n }\n reset(particle) {\n particle.bubble.inRange = false;\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\",\n minDistance = 0,\n defaultClickTime = 0,\n defaultOpacity = 1,\n ratioOffset = 1,\n defaultBubbleValue = 0,\n minRatio = 0,\n defaultRatio = 1;\nclass Bubbler extends _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.ExternalInteractorBase {\n constructor(engine, container) {\n super(container);\n this._clickBubble = interactivityData => {\n const container = this.container,\n options = container.actualOptions,\n mouseClickPos = interactivityData.mouse.clickPosition,\n 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)),\n {\n bubble\n } = 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(),\n distMouse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mouseClickPos),\n timeSpent = (new Date().getTime() - (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 this._hoverBubble = interactivityData => {\n const container = this.container,\n mousePos = interactivityData.mouse.position,\n 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(),\n pointDistance = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(pos, mousePos),\n 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 this._hoverBubbleColor = (particle, ratio, divBubble) => {\n const options = this.container.actualOptions,\n 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 this._hoverBubbleOpacity = (particle, ratio, divBubble) => {\n const container = this.container,\n options = container.actualOptions,\n modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;\n if (!modeOpacity) {\n return;\n }\n const optOpacity = particle.options.opacity.value,\n pOpacity = particle.opacity?.value ?? defaultOpacity,\n 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 this._hoverBubbleSize = (particle, ratio, divBubble) => {\n const container = this.container,\n 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,\n pSize = particle.size.value,\n 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 this._process = (particle, distMouse, timeSpent, data) => {\n const container = this.container,\n bubbleParam = data.bubbleObj.optValue,\n options = container.actualOptions,\n bubbleOptions = options.interactivity?.modes.bubble;\n if (!bubbleOptions || bubbleParam === undefined) {\n return;\n }\n const bubbleDuration = bubbleOptions.duration,\n bubbleDistance = container.retina.bubbleModeDistance,\n particlesParam = data.particlesObj.optValue,\n pObjBubble = data.bubbleObj.value,\n pObj = data.particlesObj.value ?? defaultBubbleValue,\n 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 this._singleSelectorHover = (interactivityData, delta, selector, div) => {\n const container = this.container,\n selectors = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.safeDocument)().querySelectorAll(selector),\n bubble = container.actualOptions.interactivity?.modes.bubble;\n if (!bubble || !selectors.length) {\n return;\n }\n selectors.forEach(item => {\n const elem = item,\n pxRatio = container.retina.pixelRatio,\n 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 },\n repulseRadius = elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half * pxRatio,\n 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),\n 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,\n 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 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,\n 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,\n events = options.interactivity?.events;\n if (!events) {\n return;\n }\n const onHover = events.onHover,\n onClick = events.onClick,\n hoverEnabled = onHover.enable,\n hoverMode = onHover.mode,\n clickEnabled = onClick.enable,\n clickMode = onClick.mode,\n 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,\n options = container.actualOptions,\n mouse = interactivityData.mouse,\n events = (particle?.interactivity ?? options.interactivity)?.events;\n if (!events) {\n return false;\n }\n const {\n onClick,\n onDiv,\n onHover\n } = events,\n 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}\n\n//# sourceURL=webpack://@tsparticles/interaction-external-bubble/./dist/browser/Bubbler.js?\n}");
27
27
 
28
28
  /***/ },
29
29
 
package/esm/Bubbler.js CHANGED
@@ -1,13 +1,14 @@
1
- import { Circle, DivType, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, safeDocument, } from "@tsparticles/engine";
1
+ import { Circle, Rectangle, colorMix, double, getDistance, getRangeMax, half, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, rangeColorToHsl, rgbToHsl, safeDocument, } from "@tsparticles/engine";
2
+ import { DivType, ExternalInteractorBase, divMode, divModeExecute, isDivModeEnabled, mouseLeaveEvent, mouseMoveEvent, } from "@tsparticles/plugin-interactivity";
2
3
  import { Bubble } from "./Options/Classes/Bubble.js";
3
4
  import { ProcessBubbleType } from "./Enums.js";
4
5
  import { calculateBubbleValue } from "./Utils.js";
5
- const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
6
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, defaultRatio = 1;
6
7
  export class Bubbler extends ExternalInteractorBase {
7
8
  constructor(engine, container) {
8
9
  super(container);
9
- this._clickBubble = () => {
10
- const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
10
+ this._clickBubble = interactivityData => {
11
+ const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
11
12
  if (!bubbleOptions || !mouseClickPos) {
12
13
  return;
13
14
  }
@@ -16,13 +17,13 @@ export class Bubbler extends ExternalInteractorBase {
16
17
  if (!distance || distance < minDistance) {
17
18
  return;
18
19
  }
19
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p)), { bubble } = container;
20
+ const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
20
21
  for (const particle of query) {
21
22
  if (!bubble.clicking) {
22
23
  continue;
23
24
  }
24
25
  particle.bubble.inRange = !bubble.durationEnd;
25
- const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
26
+ const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (interactivityData.mouse.clickTime ?? defaultClickTime)) /
26
27
  millisecondsToSeconds;
27
28
  if (timeSpent > bubbleOptions.duration) {
28
29
  bubble.durationEnd = true;
@@ -63,32 +64,32 @@ export class Bubbler extends ExternalInteractorBase {
63
64
  }
64
65
  }
65
66
  };
66
- this._hoverBubble = () => {
67
- const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
67
+ this._hoverBubble = interactivityData => {
68
+ const container = this.container, mousePos = interactivityData.mouse.position, distance = container.retina.bubbleModeDistance;
68
69
  if (!distance || distance < minDistance || !mousePos) {
69
70
  return;
70
71
  }
71
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
72
+ const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
72
73
  for (const particle of query) {
73
74
  particle.bubble.inRange = true;
74
75
  const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
75
76
  if (pointDistance <= distance) {
76
- if (ratio >= minRatio && container.interactivity.status === mouseMoveEvent) {
77
+ if (ratio >= minRatio && interactivityData.status === mouseMoveEvent) {
77
78
  this._hoverBubbleSize(particle, ratio);
78
79
  this._hoverBubbleOpacity(particle, ratio);
79
80
  this._hoverBubbleColor(particle, ratio);
80
81
  }
81
82
  }
82
83
  else {
83
- this.reset(particle);
84
+ this.reset(interactivityData, particle);
84
85
  }
85
- if (container.interactivity.status === mouseLeaveEvent) {
86
- this.reset(particle);
86
+ if (interactivityData.status === mouseLeaveEvent) {
87
+ this.reset(interactivityData, particle);
87
88
  }
88
89
  }
89
90
  };
90
91
  this._hoverBubbleColor = (particle, ratio, divBubble) => {
91
- const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
92
+ const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;
92
93
  if (!bubbleOptions) {
93
94
  return;
94
95
  }
@@ -115,7 +116,7 @@ export class Bubbler extends ExternalInteractorBase {
115
116
  }
116
117
  };
117
118
  this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
118
- const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
119
+ const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;
119
120
  if (!modeOpacity) {
120
121
  return;
121
122
  }
@@ -135,7 +136,7 @@ export class Bubbler extends ExternalInteractorBase {
135
136
  }
136
137
  };
137
138
  this._process = (particle, distMouse, timeSpent, data) => {
138
- const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
139
+ const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity?.modes.bubble;
139
140
  if (!bubbleOptions || bubbleParam === undefined) {
140
141
  return;
141
142
  }
@@ -177,8 +178,8 @@ export class Bubbler extends ExternalInteractorBase {
177
178
  }
178
179
  }
179
180
  };
180
- this._singleSelectorHover = (delta, selector, div) => {
181
- const container = this.container, selectors = safeDocument().querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
181
+ this._singleSelectorHover = (interactivityData, delta, selector, div) => {
182
+ const container = this.container, selectors = safeDocument().querySelectorAll(selector), bubble = container.actualOptions.interactivity?.modes.bubble;
182
183
  if (!bubble || !selectors.length) {
183
184
  return;
184
185
  }
@@ -188,7 +189,7 @@ export class Bubbler extends ExternalInteractorBase {
188
189
  y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
189
190
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
190
191
  ? new Circle(pos.x, pos.y, repulseRadius)
191
- : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, p => this.isEnabled(p));
192
+ : 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));
192
193
  for (const particle of query) {
193
194
  if (!area.contains(particle.getPosition())) {
194
195
  continue;
@@ -225,7 +226,7 @@ export class Bubbler extends ExternalInteractorBase {
225
226
  delete particle.bubble.color;
226
227
  }
227
228
  init() {
228
- const container = this.container, bubble = container.actualOptions.interactivity.modes.bubble;
229
+ const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
229
230
  if (!bubble) {
230
231
  return;
231
232
  }
@@ -234,22 +235,30 @@ export class Bubbler extends ExternalInteractorBase {
234
235
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
235
236
  }
236
237
  }
237
- interact(delta) {
238
- const options = this.container.actualOptions, events = options.interactivity.events, onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
238
+ interact(interactivityData, delta) {
239
+ const options = this.container.actualOptions, events = options.interactivity?.events;
240
+ if (!events) {
241
+ return;
242
+ }
243
+ const onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
239
244
  if (hoverEnabled && isInArray(bubbleMode, hoverMode)) {
240
- this._hoverBubble();
245
+ this._hoverBubble(interactivityData);
241
246
  }
242
247
  else if (clickEnabled && isInArray(bubbleMode, clickMode)) {
243
- this._clickBubble();
248
+ this._clickBubble(interactivityData);
244
249
  }
245
250
  else {
246
251
  divModeExecute(bubbleMode, divs, (selector, div) => {
247
- this._singleSelectorHover(delta, selector, div);
252
+ this._singleSelectorHover(interactivityData, delta, selector, div);
248
253
  });
249
254
  }
250
255
  }
251
- isEnabled(particle) {
252
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled(bubbleMode, onDiv);
256
+ isEnabled(interactivityData, particle) {
257
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
258
+ if (!events) {
259
+ return false;
260
+ }
261
+ const { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled(bubbleMode, onDiv);
253
262
  if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
254
263
  return false;
255
264
  }
@@ -261,7 +270,7 @@ export class Bubbler extends ExternalInteractorBase {
261
270
  options.bubble.load(source?.bubble);
262
271
  }
263
272
  }
264
- reset(particle) {
273
+ reset(_interactivityData, particle) {
265
274
  particle.bubble.inRange = false;
266
275
  }
267
276
  }
package/esm/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  export function loadExternalBubbleInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.2");
3
- engine.register(e => {
4
- e.addInteractor("externalBubble", async (container) => {
2
+ engine.checkVersion("4.0.0-alpha.4");
3
+ engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity");
5
+ loadInteractivityPlugin(e);
6
+ e.addInteractor?.("externalBubble", async (container) => {
5
7
  const { Bubbler } = await import("./Bubbler.js");
6
8
  return new Bubbler(e, container);
7
9
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/interaction-external-bubble",
3
- "version": "4.0.0-alpha.2",
3
+ "version": "4.0.0-alpha.4",
4
4
  "description": "tsParticles bubble external interaction",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -87,7 +87,8 @@
87
87
  "./package.json": "./package.json"
88
88
  },
89
89
  "dependencies": {
90
- "@tsparticles/engine": "4.0.0-alpha.2"
90
+ "@tsparticles/engine": "4.0.0-alpha.4",
91
+ "@tsparticles/plugin-interactivity": "4.0.0-alpha.4"
91
92
  },
92
93
  "publishConfig": {
93
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 [8 Jan 2026 at 10:01]</title>
6
+ <title>@tsparticles/interaction-external-bubble [21 Jan 2026 at 14:42]</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.2
7
+ * v4.0.0-alpha.4
8
8
  */
9
9
  /*
10
10
  * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
@@ -16,14 +16,14 @@
16
16
  */
17
17
  (function webpackUniversalModuleDefinition(root, factory) {
18
18
  if(typeof exports === 'object' && typeof module === 'object')
19
- module.exports = factory(require("@tsparticles/engine"));
19
+ module.exports = factory(require("@tsparticles/engine"), require("@tsparticles/plugin-interactivity"));
20
20
  else if(typeof define === 'function' && define.amd)
21
- define(["@tsparticles/engine"], factory);
21
+ define(["@tsparticles/engine", "@tsparticles/plugin-interactivity"], factory);
22
22
  else {
23
- var a = typeof exports === 'object' ? factory(require("@tsparticles/engine")) : factory(root["window"]);
23
+ var a = typeof exports === 'object' ? factory(require("@tsparticles/engine"), require("@tsparticles/plugin-interactivity")) : factory(root["window"], root["window"]);
24
24
  for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
25
25
  }
26
- })(this, (__WEBPACK_EXTERNAL_MODULE__tsparticles_engine__) => {
26
+ })(this, (__WEBPACK_EXTERNAL_MODULE__tsparticles_engine__, __WEBPACK_EXTERNAL_MODULE__tsparticles_plugin_interactivity__) => {
27
27
  return /******/ (() => { // webpackBootstrap
28
28
  /******/ "use strict";
29
29
  /******/ var __webpack_modules__ = ({
@@ -64,7 +64,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
64
64
  \*******************************/
65
65
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
66
66
 
67
- 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\");\nfunction loadExternalBubbleInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.2\");\n engine.register(e => {\n e.addInteractor(\"externalBubble\", async container => {\n const {\n Bubbler\n } = 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//# sourceURL=webpack://@tsparticles/interaction-external-bubble/./dist/browser/index.js?\n}");
67
+ 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\");\nfunction loadExternalBubbleInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.4\");\n engine.register(async e => {\n const {\n loadInteractivityPlugin\n } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\", 19));\n loadInteractivityPlugin(e);\n e.addInteractor?.(\"externalBubble\", async container => {\n const {\n Bubbler\n } = 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//# sourceURL=webpack://@tsparticles/interaction-external-bubble/./dist/browser/index.js?\n}");
68
68
 
69
69
  /***/ },
70
70
 
@@ -76,6 +76,16 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
76
76
 
77
77
  module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
78
78
 
79
+ /***/ },
80
+
81
+ /***/ "@tsparticles/plugin-interactivity"
82
+ /*!***************************************************************************************************************************************************************************!*\
83
+ !*** external {"commonjs":"@tsparticles/plugin-interactivity","commonjs2":"@tsparticles/plugin-interactivity","amd":"@tsparticles/plugin-interactivity","root":"window"} ***!
84
+ \***************************************************************************************************************************************************************************/
85
+ (module) {
86
+
87
+ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_plugin_interactivity__;
88
+
79
89
  /***/ }
80
90
 
81
91
  /******/ });
@@ -114,6 +124,36 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
114
124
  /******/ __webpack_require__.m = __webpack_modules__;
115
125
  /******/
116
126
  /************************************************************************/
127
+ /******/ /* webpack/runtime/create fake namespace object */
128
+ /******/ (() => {
129
+ /******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
130
+ /******/ var leafPrototypes;
131
+ /******/ // create a fake namespace object
132
+ /******/ // mode & 1: value is a module id, require it
133
+ /******/ // mode & 2: merge all properties of value into the ns
134
+ /******/ // mode & 4: return value when already ns object
135
+ /******/ // mode & 16: return value when it's Promise-like
136
+ /******/ // mode & 8|1: behave like require
137
+ /******/ __webpack_require__.t = function(value, mode) {
138
+ /******/ if(mode & 1) value = this(value);
139
+ /******/ if(mode & 8) return value;
140
+ /******/ if(typeof value === 'object' && value) {
141
+ /******/ if((mode & 4) && value.__esModule) return value;
142
+ /******/ if((mode & 16) && typeof value.then === 'function') return value;
143
+ /******/ }
144
+ /******/ var ns = Object.create(null);
145
+ /******/ __webpack_require__.r(ns);
146
+ /******/ var def = {};
147
+ /******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
148
+ /******/ for(var current = mode & 2 && value; (typeof current == 'object' || typeof current == 'function') && !~leafPrototypes.indexOf(current); current = getProto(current)) {
149
+ /******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
150
+ /******/ }
151
+ /******/ def['default'] = () => (value);
152
+ /******/ __webpack_require__.d(ns, def);
153
+ /******/ return ns;
154
+ /******/ };
155
+ /******/ })();
156
+ /******/
117
157
  /******/ /* webpack/runtime/define property getters */
118
158
  /******/ (() => {
119
159
  /******/ // define getter functions for harmony exports
@@ -148,18 +188,6 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
148
188
  /******/ };
149
189
  /******/ })();
150
190
  /******/
151
- /******/ /* webpack/runtime/global */
152
- /******/ (() => {
153
- /******/ __webpack_require__.g = (function() {
154
- /******/ if (typeof globalThis === 'object') return globalThis;
155
- /******/ try {
156
- /******/ return this || new Function('return this')();
157
- /******/ } catch (e) {
158
- /******/ if (typeof window === 'object') return window;
159
- /******/ }
160
- /******/ })();
161
- /******/ })();
162
- /******/
163
191
  /******/ /* webpack/runtime/hasOwnProperty shorthand */
164
192
  /******/ (() => {
165
193
  /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
@@ -224,8 +252,8 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
224
252
  /******/ /* webpack/runtime/publicPath */
225
253
  /******/ (() => {
226
254
  /******/ var scriptUrl;
227
- /******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
228
- /******/ var document = __webpack_require__.g.document;
255
+ /******/ if (globalThis.importScripts) scriptUrl = globalThis.location + "";
256
+ /******/ var document = globalThis.document;
229
257
  /******/ if (!scriptUrl && document) {
230
258
  /******/ if (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT')
231
259
  /******/ scriptUrl = document.currentScript.src;
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see tsparticles.interaction.external.bubble.min.js.LICENSE.txt */
2
- !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var r="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in r)("object"==typeof exports?exports:e)[o]=r[o]}}(this,(e=>(()=>{var t,r,o={105(e,t,r){r.d(t,{u:()=>i});var o=r(303);class i{constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(e){if(!(0,o.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){const t=(0,o.isArray)(this.color)?void 0:this.color;this.color=(0,o.executeOnSingleOrMultiple)(e.color,(e=>o.OptionsColor.create(t,e)))}void 0!==e.size&&(this.size=e.size)}}}},303(t){t.exports=e},729(e,t,r){r.d(t,{C:()=>n});var o=r(303),i=r(105);class n extends i.u{constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,o.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}},888(e,t,r){r.d(t,{Z:()=>a});var o=r(303),i=r(105),n=r(729);class a extends i.u{load(e){super.load(e),(0,o.isNull)(e)||(this.divs=(0,o.executeOnSingleOrMultiple)(e.divs,(e=>{const t=new n.C;return t.load(e),t})))}}}},i={};function n(e){var t=i[e];if(void 0!==t)return t.exports;var r=i[e]={exports:{}};return o[e](r,r.exports,n),r.exports}n.m=o,n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.f={},n.e=e=>Promise.all(Object.keys(n.f).reduce(((t,r)=>(n.f[r](e,t),t)),[])),n.u=e=>e+".min.js",n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),t={},r="@tsparticles/interaction-external-bubble:",n.l=(e,o,i,a)=>{if(t[e])t[e].push(o);else{var s,l;if(void 0!==i)for(var c=document.getElementsByTagName("script"),u=0;u<c.length;u++){var d=c[u];if(d.getAttribute("src")==e||d.getAttribute("data-webpack")==r+i){s=d;break}}s||(l=!0,(s=document.createElement("script")).charset="utf-8",n.nc&&s.setAttribute("nonce",n.nc),s.setAttribute("data-webpack",r+i),s.src=e),t[e]=[o];var p=(r,o)=>{s.onerror=s.onload=null,clearTimeout(b);var i=t[e];if(delete t[e],s.parentNode&&s.parentNode.removeChild(s),i&&i.forEach((e=>e(o))),r)return r(o)},b=setTimeout(p.bind(null,void 0,{type:"timeout",target:s}),12e4);s.onerror=p.bind(null,s.onerror),s.onload=p.bind(null,s.onload),l&&document.head.appendChild(s)}},n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;n.g.importScripts&&(e=n.g.location+"");var t=n.g.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var r=t.getElementsByTagName("script");if(r.length)for(var o=r.length-1;o>-1&&(!e||!/^http(s?):/.test(e));)e=r[o--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),n.p=e})(),(()=>{var e={108:0};n.f.j=(t,r)=>{var o=n.o(e,t)?e[t]:void 0;if(0!==o)if(o)r.push(o[2]);else{var i=new Promise(((r,i)=>o=e[t]=[r,i]));r.push(o[2]=i);var a=n.p+n.u(t),s=new Error;n.l(a,(r=>{if(n.o(e,t)&&(0!==(o=e[t])&&(e[t]=void 0),o)){var i=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;s.message="Loading chunk "+t+" failed.\n("+i+": "+a+")",s.name="ChunkLoadError",s.type=i,s.request=a,o[1](s)}}),"chunk-"+t,t)}};var t=(t,r)=>{var o,i,[a,s,l]=r,c=0;if(a.some((t=>0!==e[t]))){for(o in s)n.o(s,o)&&(n.m[o]=s[o]);if(l)l(n)}for(t&&t(r);c<a.length;c++)i=a[c],n.o(e,i)&&e[i]&&e[i][0](),e[i]=0},r=this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var a={};n.r(a),n.d(a,{Bubble:()=>c.Z,BubbleBase:()=>s.u,BubbleDiv:()=>l.C,loadExternalBubbleInteraction:()=>u});var s=n(105),l=n(729),c=n(888);function u(e){e.checkVersion("4.0.0-alpha.2"),e.register((e=>{e.addInteractor("externalBubble",(async t=>{const{Bubbler:r}=await n.e(809).then(n.bind(n,809));return new r(e,t)}))}))}return a})()));
2
+ !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)=>(()=>{var r,i,o,n,a={52(e,t,r){r.d(t,{C:()=>n});var i=r(303),o=r(618);class n extends o.u{constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,i.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}},303(t){t.exports=e},443(e,t,r){r.d(t,{Z:()=>a});var i=r(303),o=r(618),n=r(52);class a extends o.u{load(e){super.load(e),(0,i.isNull)(e)||(this.divs=(0,i.executeOnSingleOrMultiple)(e.divs,(e=>{const t=new n.C;return t.load(e),t})))}}},618(e,t,r){r.d(t,{u:()=>o});var i=r(303);class o{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){const 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)}}}},702(e){e.exports=t}},s={};function l(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}};return a[e](r,r.exports,l),r.exports}l.m=a,i=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,l.t=function(e,t){if(1&t&&(e=this(e)),8&t)return e;if("object"==typeof e&&e){if(4&t&&e.__esModule)return e;if(16&t&&"function"==typeof e.then)return e}var o=Object.create(null);l.r(o);var n={};r=r||[null,i({}),i([]),i(i)];for(var a=2&t&&e;("object"==typeof a||"function"==typeof a)&&!~r.indexOf(a);a=i(a))Object.getOwnPropertyNames(a).forEach((t=>n[t]=()=>e[t]));return n.default=()=>e,l.d(o,n),o},l.d=(e,t)=>{for(var r in t)l.o(t,r)&&!l.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},l.f={},l.e=e=>Promise.all(Object.keys(l.f).reduce(((t,r)=>(l.f[r](e,t),t)),[])),l.u=e=>e+".min.js",l.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o={},n="@tsparticles/interaction-external-bubble:",l.l=(e,t,r,i)=>{if(o[e])o[e].push(t);else{var a,s;if(void 0!==r)for(var c=document.getElementsByTagName("script"),u=0;u<c.length;u++){var p=c[u];if(p.getAttribute("src")==e||p.getAttribute("data-webpack")==n+r){a=p;break}}a||(s=!0,(a=document.createElement("script")).charset="utf-8",l.nc&&a.setAttribute("nonce",l.nc),a.setAttribute("data-webpack",n+r),a.src=e),o[e]=[t];var d=(t,r)=>{a.onerror=a.onload=null,clearTimeout(f);var i=o[e];if(delete o[e],a.parentNode&&a.parentNode.removeChild(a),i&&i.forEach((e=>e(r))),t)return t(r)},f=setTimeout(d.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=d.bind(null,a.onerror),a.onload=d.bind(null,a.onload),s&&document.head.appendChild(a)}},l.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;globalThis.importScripts&&(e=globalThis.location+"");var t=globalThis.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var r=t.getElementsByTagName("script");if(r.length)for(var i=r.length-1;i>-1&&(!e||!/^http(s?):/.test(e));)e=r[i--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),l.p=e})(),(()=>{var e={108:0};l.f.j=(t,r)=>{var i=l.o(e,t)?e[t]:void 0;if(0!==i)if(i)r.push(i[2]);else{var o=new Promise(((r,o)=>i=e[t]=[r,o]));r.push(i[2]=o);var n=l.p+l.u(t),a=new Error;l.l(n,(r=>{if(l.o(e,t)&&(0!==(i=e[t])&&(e[t]=void 0),i)){var o=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;a.message="Loading chunk "+t+" failed.\n("+o+": "+n+")",a.name="ChunkLoadError",a.type=o,a.request=n,i[1](a)}}),"chunk-"+t,t)}};var t=(t,r)=>{var i,o,[n,a,s]=r,c=0;if(n.some((t=>0!==e[t]))){for(i in a)l.o(a,i)&&(l.m[i]=a[i]);if(s)s(l)}for(t&&t(r);c<n.length;c++)o=n[c],l.o(e,o)&&e[o]&&e[o][0](),e[o]=0},r=this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var c={};l.r(c),l.d(c,{Bubble:()=>d.Z,BubbleBase:()=>u.u,BubbleDiv:()=>p.C,loadExternalBubbleInteraction:()=>f});var u=l(618),p=l(52),d=l(443);function f(e){e.checkVersion("4.0.0-alpha.4"),e.register((async e=>{const{loadInteractivityPlugin:t}=await Promise.resolve().then(l.t.bind(l,702,19));t(e),e.addInteractor?.("externalBubble",(async t=>{const{Bubbler:r}=await l.e(132).then(l.bind(l,132));return new r(e,t)}))}))}return c})()));
@@ -1 +1 @@
1
- /*! tsParticles Bubble External Interaction v4.0.0-alpha.2 by Matteo Bruni */
1
+ /*! tsParticles Bubble External Interaction v4.0.0-alpha.4 by Matteo Bruni */
@@ -1,15 +1,16 @@
1
1
  import type { BubbleContainer, BubbleMode, IBubbleMode } from "./Types.js";
2
- import { type Engine, ExternalInteractorBase, type IDelta, type IModes, type Modes, type Particle, type RecursivePartial } from "@tsparticles/engine";
2
+ import { type Engine, type IDelta, type Particle, type RecursivePartial } from "@tsparticles/engine";
3
+ import { ExternalInteractorBase, type IInteractivityData, type IModes, type InteractivityParticle, type Modes } from "@tsparticles/plugin-interactivity";
3
4
  export declare class Bubbler extends ExternalInteractorBase<BubbleContainer> {
4
- handleClickMode: (mode: string) => void;
5
+ handleClickMode: (mode: string, interactivityData: IInteractivityData) => void;
5
6
  private readonly _engine;
6
7
  constructor(engine: Engine, container: BubbleContainer);
7
8
  clear(particle: Particle, _delta: IDelta, force?: boolean): void;
8
9
  init(): void;
9
- interact(delta: IDelta): void;
10
- isEnabled(particle?: Particle): boolean;
10
+ interact(interactivityData: IInteractivityData, delta: IDelta): void;
11
+ isEnabled(interactivityData: IInteractivityData, particle?: InteractivityParticle): boolean;
11
12
  loadModeOptions(options: Modes & BubbleMode, ...sources: RecursivePartial<(IModes & IBubbleMode) | undefined>[]): void;
12
- reset(particle: Particle): void;
13
+ reset(_interactivityData: IInteractivityData, particle: Particle): void;
13
14
  private readonly _clickBubble;
14
15
  private readonly _hoverBubble;
15
16
  private readonly _hoverBubbleColor;
@@ -1,7 +1,7 @@
1
1
  import type { BubbleMode } from "../../Types.js";
2
- import type { Options } from "@tsparticles/engine";
3
- export type BubbleOptions = Options & {
4
- interactivity: {
2
+ import type { InteractivityOptions } from "@tsparticles/plugin-interactivity";
3
+ export type BubbleOptions = InteractivityOptions & {
4
+ interactivity?: {
5
5
  modes: BubbleMode;
6
6
  };
7
7
  };
@@ -1,4 +1,4 @@
1
1
  import type { IBubbleBase } from "./IBubbleBase.js";
2
- import type { IModeDiv } from "@tsparticles/engine";
2
+ import type { IModeDiv } from "@tsparticles/plugin-interactivity";
3
3
  export interface IBubbleDiv extends IBubbleBase, IModeDiv {
4
4
  }
package/types/Types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Bubble } from "./Options/Classes/Bubble.js";
2
2
  import type { BubbleOptions } from "./Options/Classes/BubbleOptions.js";
3
- import type { Container } from "@tsparticles/engine";
4
3
  import type { IBubble } from "./Options/Interfaces/IBubble.js";
4
+ import type { InteractivityContainer } from "@tsparticles/plugin-interactivity";
5
5
  export interface IBubbleMode {
6
6
  bubble: IBubble;
7
7
  }
@@ -12,7 +12,7 @@ interface IContainerBubble {
12
12
  clicking?: boolean;
13
13
  durationEnd?: boolean;
14
14
  }
15
- export type BubbleContainer = Container & {
15
+ export type BubbleContainer = InteractivityContainer & {
16
16
  actualOptions: BubbleOptions;
17
17
  bubble?: IContainerBubble;
18
18
  retina: {
package/umd/Bubbler.js CHANGED
@@ -4,22 +4,23 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "@tsparticles/engine", "./Options/Classes/Bubble.js", "./Enums.js", "./Utils.js"], factory);
7
+ define(["require", "exports", "@tsparticles/engine", "@tsparticles/plugin-interactivity", "./Options/Classes/Bubble.js", "./Enums.js", "./Utils.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.Bubbler = void 0;
13
13
  const engine_1 = require("@tsparticles/engine");
14
+ const plugin_interactivity_1 = require("@tsparticles/plugin-interactivity");
14
15
  const Bubble_js_1 = require("./Options/Classes/Bubble.js");
15
16
  const Enums_js_1 = require("./Enums.js");
16
17
  const Utils_js_1 = require("./Utils.js");
17
- const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
18
- class Bubbler extends engine_1.ExternalInteractorBase {
18
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, defaultRatio = 1;
19
+ class Bubbler extends plugin_interactivity_1.ExternalInteractorBase {
19
20
  constructor(engine, container) {
20
21
  super(container);
21
- this._clickBubble = () => {
22
- const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
22
+ this._clickBubble = interactivityData => {
23
+ const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
23
24
  if (!bubbleOptions || !mouseClickPos) {
24
25
  return;
25
26
  }
@@ -28,18 +29,18 @@
28
29
  if (!distance || distance < minDistance) {
29
30
  return;
30
31
  }
31
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p)), { bubble } = container;
32
+ const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(interactivityData, p)), { bubble } = container;
32
33
  for (const particle of query) {
33
34
  if (!bubble.clicking) {
34
35
  continue;
35
36
  }
36
37
  particle.bubble.inRange = !bubble.durationEnd;
37
- const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
38
+ const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (interactivityData.mouse.clickTime ?? defaultClickTime)) /
38
39
  engine_1.millisecondsToSeconds;
39
40
  if (timeSpent > bubbleOptions.duration) {
40
41
  bubble.durationEnd = true;
41
42
  }
42
- if (timeSpent > bubbleOptions.duration * double) {
43
+ if (timeSpent > bubbleOptions.duration * engine_1.double) {
43
44
  bubble.clicking = false;
44
45
  bubble.durationEnd = false;
45
46
  }
@@ -75,32 +76,32 @@
75
76
  }
76
77
  }
77
78
  };
78
- this._hoverBubble = () => {
79
- const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
79
+ this._hoverBubble = interactivityData => {
80
+ const container = this.container, mousePos = interactivityData.mouse.position, distance = container.retina.bubbleModeDistance;
80
81
  if (!distance || distance < minDistance || !mousePos) {
81
82
  return;
82
83
  }
83
- const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
84
+ const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
84
85
  for (const particle of query) {
85
86
  particle.bubble.inRange = true;
86
87
  const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
87
88
  if (pointDistance <= distance) {
88
- if (ratio >= minRatio && container.interactivity.status === engine_1.mouseMoveEvent) {
89
+ if (ratio >= minRatio && interactivityData.status === plugin_interactivity_1.mouseMoveEvent) {
89
90
  this._hoverBubbleSize(particle, ratio);
90
91
  this._hoverBubbleOpacity(particle, ratio);
91
92
  this._hoverBubbleColor(particle, ratio);
92
93
  }
93
94
  }
94
95
  else {
95
- this.reset(particle);
96
+ this.reset(interactivityData, particle);
96
97
  }
97
- if (container.interactivity.status === engine_1.mouseLeaveEvent) {
98
- this.reset(particle);
98
+ if (interactivityData.status === plugin_interactivity_1.mouseLeaveEvent) {
99
+ this.reset(interactivityData, particle);
99
100
  }
100
101
  }
101
102
  };
102
103
  this._hoverBubbleColor = (particle, ratio, divBubble) => {
103
- const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
104
+ const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;
104
105
  if (!bubbleOptions) {
105
106
  return;
106
107
  }
@@ -127,7 +128,7 @@
127
128
  }
128
129
  };
129
130
  this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
130
- const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
131
+ const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity?.modes.bubble?.opacity;
131
132
  if (!modeOpacity) {
132
133
  return;
133
134
  }
@@ -147,7 +148,7 @@
147
148
  }
148
149
  };
149
150
  this._process = (particle, distMouse, timeSpent, data) => {
150
- const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
151
+ const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity?.modes.bubble;
151
152
  if (!bubbleOptions || bubbleParam === undefined) {
152
153
  return;
153
154
  }
@@ -189,24 +190,24 @@
189
190
  }
190
191
  }
191
192
  };
192
- this._singleSelectorHover = (delta, selector, div) => {
193
- const container = this.container, selectors = (0, engine_1.safeDocument)().querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
193
+ this._singleSelectorHover = (interactivityData, delta, selector, div) => {
194
+ const container = this.container, selectors = (0, engine_1.safeDocument)().querySelectorAll(selector), bubble = container.actualOptions.interactivity?.modes.bubble;
194
195
  if (!bubble || !selectors.length) {
195
196
  return;
196
197
  }
197
198
  selectors.forEach(item => {
198
199
  const elem = item, pxRatio = container.retina.pixelRatio, pos = {
199
- x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
200
- y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
201
- }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === engine_1.DivType.circle
200
+ x: (elem.offsetLeft + elem.offsetWidth * engine_1.half) * pxRatio,
201
+ y: (elem.offsetTop + elem.offsetHeight * engine_1.half) * pxRatio,
202
+ }, repulseRadius = elem.offsetWidth * engine_1.half * pxRatio, area = div.type === plugin_interactivity_1.DivType.circle
202
203
  ? new engine_1.Circle(pos.x, pos.y, repulseRadius)
203
- : 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(p));
204
+ : 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));
204
205
  for (const particle of query) {
205
206
  if (!area.contains(particle.getPosition())) {
206
207
  continue;
207
208
  }
208
209
  particle.bubble.inRange = true;
209
- const divs = bubble.divs, divBubble = (0, engine_1.divMode)(divs, elem);
210
+ const divs = bubble.divs, divBubble = (0, plugin_interactivity_1.divMode)(divs, elem);
210
211
  if (!particle.bubble.div || particle.bubble.div !== elem) {
211
212
  this.clear(particle, delta, true);
212
213
  particle.bubble.div = elem;
@@ -237,7 +238,7 @@
237
238
  delete particle.bubble.color;
238
239
  }
239
240
  init() {
240
- const container = this.container, bubble = container.actualOptions.interactivity.modes.bubble;
241
+ const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
241
242
  if (!bubble) {
242
243
  return;
243
244
  }
@@ -246,22 +247,30 @@
246
247
  container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
247
248
  }
248
249
  }
249
- interact(delta) {
250
- const options = this.container.actualOptions, events = options.interactivity.events, onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
250
+ interact(interactivityData, delta) {
251
+ const options = this.container.actualOptions, events = options.interactivity?.events;
252
+ if (!events) {
253
+ return;
254
+ }
255
+ const onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
251
256
  if (hoverEnabled && (0, engine_1.isInArray)(bubbleMode, hoverMode)) {
252
- this._hoverBubble();
257
+ this._hoverBubble(interactivityData);
253
258
  }
254
259
  else if (clickEnabled && (0, engine_1.isInArray)(bubbleMode, clickMode)) {
255
- this._clickBubble();
260
+ this._clickBubble(interactivityData);
256
261
  }
257
262
  else {
258
- (0, engine_1.divModeExecute)(bubbleMode, divs, (selector, div) => {
259
- this._singleSelectorHover(delta, selector, div);
263
+ (0, plugin_interactivity_1.divModeExecute)(bubbleMode, divs, (selector, div) => {
264
+ this._singleSelectorHover(interactivityData, delta, selector, div);
260
265
  });
261
266
  }
262
267
  }
263
- isEnabled(particle) {
264
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = (0, engine_1.isDivModeEnabled)(bubbleMode, onDiv);
268
+ isEnabled(interactivityData, particle) {
269
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
270
+ if (!events) {
271
+ return false;
272
+ }
273
+ const { onClick, onDiv, onHover } = events, divBubble = (0, plugin_interactivity_1.isDivModeEnabled)(bubbleMode, onDiv);
265
274
  if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
266
275
  return false;
267
276
  }
@@ -273,7 +282,7 @@
273
282
  options.bubble.load(source?.bubble);
274
283
  }
275
284
  }
276
- reset(particle) {
285
+ reset(_interactivityData, particle) {
277
286
  particle.bubble.inRange = false;
278
287
  }
279
288
  }
package/umd/index.js CHANGED
@@ -48,10 +48,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
49
  exports.loadExternalBubbleInteraction = loadExternalBubbleInteraction;
50
50
  function loadExternalBubbleInteraction(engine) {
51
- engine.checkVersion("4.0.0-alpha.2");
52
- engine.register(e => {
53
- e.addInteractor("externalBubble", async (container) => {
54
- const { Bubbler } = await (__syncRequire ? Promise.resolve().then(() => __importStar(require("./Bubbler.js"))) : new Promise((resolve_1, reject_1) => { require(["./Bubbler.js"], resolve_1, reject_1); }).then(__importStar));
51
+ engine.checkVersion("4.0.0-alpha.4");
52
+ engine.register(async (e) => {
53
+ const { loadInteractivityPlugin } = 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
+ loadInteractivityPlugin(e);
55
+ e.addInteractor?.("externalBubble", async (container) => {
56
+ const { Bubbler } = await (__syncRequire ? Promise.resolve().then(() => __importStar(require("./Bubbler.js"))) : new Promise((resolve_2, reject_2) => { require(["./Bubbler.js"], resolve_2, reject_2); }).then(__importStar));
55
57
  return new Bubbler(e, container);
56
58
  });
57
59
  });
package/809.min.js DELETED
@@ -1,2 +0,0 @@
1
- /*! For license information please see 809.min.js.LICENSE.txt */
2
- (this.webpackChunk_tsparticles_interaction_external_bubble=this.webpackChunk_tsparticles_interaction_external_bubble||[]).push([[809],{809(e,i,t){t.d(i,{Bubbler:()=>a});var o,b=t(303),n=t(888);function l(e,i,t,o){if(i>=t){const n=e+(i-t)*o;return(0,b.clamp)(n,e,i)}if(i<t){const n=e-(t-i)*o;return(0,b.clamp)(n,i,e)}}!function(e){e.color="color",e.opacity="opacity",e.size="size"}(o||(o={}));const s="bubble";class a extends b.ExternalInteractorBase{constructor(e,i){super(i),this._clickBubble=()=>{const e=this.container,i=e.actualOptions,t=e.interactivity.mouse.clickPosition,n=i.interactivity.modes.bubble;if(!n||!t)return;e.bubble??={};const l=e.retina.bubbleModeDistance;if(!l||l<0)return;const s=e.particles.quadTree.queryCircle(t,l,(e=>this.isEnabled(e))),{bubble:a}=e;for(const i of s){if(!a.clicking)continue;i.bubble.inRange=!a.durationEnd;const s=i.getPosition(),r=(0,b.getDistance)(s,t),c=((new Date).getTime()-(e.interactivity.mouse.clickTime??0))/b.millisecondsToSeconds;c>n.duration&&(a.durationEnd=!0),c>2*n.duration&&(a.clicking=!1,a.durationEnd=!1);const u={bubbleObj:{optValue:e.retina.bubbleModeSize,value:i.bubble.radius},particlesObj:{optValue:(0,b.getRangeMax)(i.options.size.value)*e.retina.pixelRatio,value:i.size.value},type:o.size};this._process(i,r,c,u);const d={bubbleObj:{optValue:n.opacity,value:i.bubble.opacity},particlesObj:{optValue:(0,b.getRangeMax)(i.options.opacity.value),value:i.opacity?.value??1},type:o.opacity};this._process(i,r,c,d),!a.durationEnd&&r<=l?this._hoverBubbleColor(i,r):delete i.bubble.color}},this._hoverBubble=()=>{const e=this.container,i=e.interactivity.mouse.position,t=e.retina.bubbleModeDistance;if(!t||t<0||!i)return;const o=e.particles.quadTree.queryCircle(i,t,(e=>this.isEnabled(e)));for(const n of o){n.bubble.inRange=!0;const o=n.getPosition(),l=(0,b.getDistance)(o,i),s=1-l/t;l<=t?s>=0&&e.interactivity.status===b.mouseMoveEvent&&(this._hoverBubbleSize(n,s),this._hoverBubbleOpacity(n,s),this._hoverBubbleColor(n,s)):this.reset(n),e.interactivity.status===b.mouseLeaveEvent&&this.reset(n)}},this._hoverBubbleColor=(e,i,t)=>{const o=this.container.actualOptions,n=t??o.interactivity.modes.bubble;if(n){if(!e.bubble.finalColor){const i=n.color;if(!i)return;const t=(0,b.itemFromSingleOrMultiple)(i);e.bubble.finalColor=(0,b.rangeColorToHsl)(this._engine,t)}if(e.bubble.finalColor)if(n.mix){e.bubble.color=void 0;const t=e.getFillColor();e.bubble.color=t?(0,b.rgbToHsl)((0,b.colorMix)(t,e.bubble.finalColor,1-i,i)):e.bubble.finalColor}else e.bubble.color=e.bubble.finalColor}},this._hoverBubbleOpacity=(e,i,t)=>{const o=this.container.actualOptions,n=t?.opacity??o.interactivity.modes.bubble?.opacity;if(!n)return;const s=e.options.opacity.value,a=l(e.opacity?.value??1,n,(0,b.getRangeMax)(s),i);void 0!==a&&(e.bubble.opacity=a)},this._hoverBubbleSize=(e,i,t)=>{const o=this.container,n=t?.size?t.size*o.retina.pixelRatio:o.retina.bubbleModeSize;if(void 0===n)return;const s=(0,b.getRangeMax)(e.options.size.value)*o.retina.pixelRatio,a=l(e.size.value,n,s,i);void 0!==a&&(e.bubble.radius=a)},this._process=(e,i,t,b)=>{const n=this.container,l=b.bubbleObj.optValue,s=n.actualOptions.interactivity.modes.bubble;if(!s||void 0===l)return;const a=s.duration,r=n.retina.bubbleModeDistance,c=b.particlesObj.optValue,u=b.bubbleObj.value,d=b.particlesObj.value??0,p=b.type;if(r&&!(r<0)&&l!==c)if(n.bubble??={},n.bubble.durationEnd)u&&(p===o.size&&delete e.bubble.radius,p===o.opacity&&delete e.bubble.opacity);else if(i<=r){if((u??d)!==l){const i=d-t*(d-l)/a;p===o.size&&(e.bubble.radius=i),p===o.opacity&&(e.bubble.opacity=i)}}else p===o.size&&delete e.bubble.radius,p===o.opacity&&delete e.bubble.opacity},this._singleSelectorHover=(e,i,t)=>{const o=this.container,n=(0,b.safeDocument)().querySelectorAll(i),l=o.actualOptions.interactivity.modes.bubble;l&&n.length&&n.forEach((i=>{const n=i,s=o.retina.pixelRatio,a={x:(n.offsetLeft+.5*n.offsetWidth)*s,y:(n.offsetTop+.5*n.offsetHeight)*s},r=.5*n.offsetWidth*s,c=t.type===b.DivType.circle?new b.Circle(a.x,a.y,r):new b.Rectangle(n.offsetLeft*s,n.offsetTop*s,n.offsetWidth*s,n.offsetHeight*s),u=o.particles.quadTree.query(c,(e=>this.isEnabled(e)));for(const i of u){if(!c.contains(i.getPosition()))continue;i.bubble.inRange=!0;const t=l.divs,o=(0,b.divMode)(t,n);i.bubble.div&&i.bubble.div===n||(this.clear(i,e,!0),i.bubble.div=n),this._hoverBubbleSize(i,1,o),this._hoverBubbleOpacity(i,1,o),this._hoverBubbleColor(i,1,o)}}))},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(){const 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){const i=this.container.actualOptions.interactivity.events,t=i.onHover,o=i.onClick,n=t.enable,l=t.mode,a=o.enable,r=o.mode,c=i.onDiv;n&&(0,b.isInArray)(s,l)?this._hoverBubble():a&&(0,b.isInArray)(s,r)?this._clickBubble():(0,b.divModeExecute)(s,c,((i,t)=>{this._singleSelectorHover(e,i,t)}))}isEnabled(e){const i=this.container,t=i.actualOptions,o=i.interactivity.mouse,n=(e?.interactivity??t.interactivity).events,{onClick:l,onDiv:a,onHover:r}=n,c=(0,b.isDivModeEnabled)(s,a);return!!(c||r.enable&&o.position||l.enable&&o.clickPosition)&&((0,b.isInArray)(s,r.mode)||(0,b.isInArray)(s,l.mode)||c)}loadModeOptions(e,...i){e.bubble??=new n.Z;for(const t of i)e.bubble.load(t?.bubble)}reset(e){e.bubble.inRange=!1}}}}]);
@@ -1 +0,0 @@
1
- /*! tsParticles Bubble External Interaction v4.0.0-alpha.2 by Matteo Bruni */