@tsparticles/interaction-external-bubble 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
- import { Circle, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
1
+ import { Circle, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
2
2
  import { Bubble } from "./Options/Classes/Bubble.js";
3
3
  import { calculateBubbleValue } from "./Utils.js";
4
- const bubbleMode = "bubble";
4
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
5
5
  export class Bubbler extends ExternalInteractorBase {
6
6
  constructor(container) {
7
7
  super(container);
@@ -14,7 +14,7 @@ export class Bubbler extends ExternalInteractorBase {
14
14
  container.bubble = {};
15
15
  }
16
16
  const distance = container.retina.bubbleModeDistance;
17
- if (!distance || distance < 0) {
17
+ if (!distance || distance < minDistance) {
18
18
  return;
19
19
  }
20
20
  const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
@@ -23,11 +23,12 @@ export class Bubbler extends ExternalInteractorBase {
23
23
  continue;
24
24
  }
25
25
  particle.bubble.inRange = !bubble.durationEnd;
26
- const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
26
+ const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
27
+ millisecondsToSeconds;
27
28
  if (timeSpent > bubbleOptions.duration) {
28
29
  bubble.durationEnd = true;
29
30
  }
30
- if (timeSpent > bubbleOptions.duration * 2) {
31
+ if (timeSpent > bubbleOptions.duration * double) {
31
32
  bubble.clicking = false;
32
33
  bubble.durationEnd = false;
33
34
  }
@@ -50,7 +51,7 @@ export class Bubbler extends ExternalInteractorBase {
50
51
  },
51
52
  particlesObj: {
52
53
  optValue: getRangeMax(particle.options.opacity.value),
53
- value: particle.opacity?.value ?? 1,
54
+ value: particle.opacity?.value ?? defaultOpacity,
54
55
  },
55
56
  type: "opacity",
56
57
  };
@@ -65,15 +66,15 @@ export class Bubbler extends ExternalInteractorBase {
65
66
  };
66
67
  this._hoverBubble = () => {
67
68
  const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
68
- if (!distance || distance < 0 || mousePos === undefined) {
69
+ if (!distance || distance < minDistance || !mousePos) {
69
70
  return;
70
71
  }
71
72
  const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
72
73
  for (const particle of query) {
73
74
  particle.bubble.inRange = true;
74
- const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
75
+ const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
75
76
  if (pointDistance <= distance) {
76
- if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
77
+ if (ratio >= minRatio && container.interactivity.status === mouseMoveEvent) {
77
78
  this._hoverBubbleSize(particle, ratio);
78
79
  this._hoverBubbleOpacity(particle, ratio);
79
80
  this._hoverBubbleColor(particle, ratio);
@@ -107,7 +108,7 @@ export class Bubbler extends ExternalInteractorBase {
107
108
  particle.bubble.color = undefined;
108
109
  const pColor = particle.getFillColor();
109
110
  particle.bubble.color = pColor
110
- ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
111
+ ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio))
111
112
  : particle.bubble.finalColor;
112
113
  }
113
114
  else {
@@ -119,7 +120,7 @@ export class Bubbler extends ExternalInteractorBase {
119
120
  if (!modeOpacity) {
120
121
  return;
121
122
  }
122
- const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
123
+ const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? defaultOpacity, opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
123
124
  if (opacity !== undefined) {
124
125
  particle.bubble.opacity = opacity;
125
126
  }
@@ -139,8 +140,8 @@ export class Bubbler extends ExternalInteractorBase {
139
140
  if (!bubbleOptions || bubbleParam === undefined) {
140
141
  return;
141
142
  }
142
- const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
143
- if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
143
+ const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value ?? defaultBubbleValue, type = data.type;
144
+ if (!bubbleDistance || bubbleDistance < minDistance || bubbleParam === particlesParam) {
144
145
  return;
145
146
  }
146
147
  if (!container.bubble) {
@@ -186,9 +187,9 @@ export class Bubbler extends ExternalInteractorBase {
186
187
  }
187
188
  selectors.forEach((item) => {
188
189
  const elem = item, pxRatio = container.retina.pixelRatio, pos = {
189
- x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
190
- y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
191
- }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
190
+ x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
191
+ y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
192
+ }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === "circle"
192
193
  ? new Circle(pos.x, pos.y, repulseRadius)
193
194
  : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
194
195
  for (const particle of query) {
@@ -201,9 +202,9 @@ export class Bubbler extends ExternalInteractorBase {
201
202
  this.clear(particle, delta, true);
202
203
  particle.bubble.div = elem;
203
204
  }
204
- this._hoverBubbleSize(particle, 1, divBubble);
205
- this._hoverBubbleOpacity(particle, 1, divBubble);
206
- this._hoverBubbleColor(particle, 1, divBubble);
205
+ this._hoverBubbleSize(particle, defaultRatio, divBubble);
206
+ this._hoverBubbleOpacity(particle, defaultRatio, divBubble);
207
+ this._hoverBubbleColor(particle, defaultRatio, divBubble);
207
208
  }
208
209
  });
209
210
  };
@@ -250,10 +251,11 @@ export class Bubbler extends ExternalInteractorBase {
250
251
  else {
251
252
  divModeExecute(bubbleMode, divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
252
253
  }
254
+ await Promise.resolve();
253
255
  }
254
256
  isEnabled(particle) {
255
257
  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
- if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
258
+ if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
257
259
  return false;
258
260
  }
259
261
  return isInArray(bubbleMode, onHover.mode) || isInArray(bubbleMode, onClick.mode) || divBubble;
package/cjs/Bubbler.js CHANGED
@@ -4,7 +4,7 @@ exports.Bubbler = void 0;
4
4
  const engine_1 = require("@tsparticles/engine");
5
5
  const Bubble_js_1 = require("./Options/Classes/Bubble.js");
6
6
  const Utils_js_1 = require("./Utils.js");
7
- const bubbleMode = "bubble";
7
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
8
8
  class Bubbler extends engine_1.ExternalInteractorBase {
9
9
  constructor(container) {
10
10
  super(container);
@@ -17,7 +17,7 @@ class Bubbler extends engine_1.ExternalInteractorBase {
17
17
  container.bubble = {};
18
18
  }
19
19
  const distance = container.retina.bubbleModeDistance;
20
- if (!distance || distance < 0) {
20
+ if (!distance || distance < minDistance) {
21
21
  return;
22
22
  }
23
23
  const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
@@ -26,11 +26,12 @@ class Bubbler extends engine_1.ExternalInteractorBase {
26
26
  continue;
27
27
  }
28
28
  particle.bubble.inRange = !bubble.durationEnd;
29
- const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
29
+ const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
30
+ engine_1.millisecondsToSeconds;
30
31
  if (timeSpent > bubbleOptions.duration) {
31
32
  bubble.durationEnd = true;
32
33
  }
33
- if (timeSpent > bubbleOptions.duration * 2) {
34
+ if (timeSpent > bubbleOptions.duration * double) {
34
35
  bubble.clicking = false;
35
36
  bubble.durationEnd = false;
36
37
  }
@@ -53,7 +54,7 @@ class Bubbler extends engine_1.ExternalInteractorBase {
53
54
  },
54
55
  particlesObj: {
55
56
  optValue: (0, engine_1.getRangeMax)(particle.options.opacity.value),
56
- value: particle.opacity?.value ?? 1,
57
+ value: particle.opacity?.value ?? defaultOpacity,
57
58
  },
58
59
  type: "opacity",
59
60
  };
@@ -68,15 +69,15 @@ class Bubbler extends engine_1.ExternalInteractorBase {
68
69
  };
69
70
  this._hoverBubble = () => {
70
71
  const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
71
- if (!distance || distance < 0 || mousePos === undefined) {
72
+ if (!distance || distance < minDistance || !mousePos) {
72
73
  return;
73
74
  }
74
75
  const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
75
76
  for (const particle of query) {
76
77
  particle.bubble.inRange = true;
77
- const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = 1 - pointDistance / distance;
78
+ const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
78
79
  if (pointDistance <= distance) {
79
- if (ratio >= 0 && container.interactivity.status === engine_1.mouseMoveEvent) {
80
+ if (ratio >= minRatio && container.interactivity.status === engine_1.mouseMoveEvent) {
80
81
  this._hoverBubbleSize(particle, ratio);
81
82
  this._hoverBubbleOpacity(particle, ratio);
82
83
  this._hoverBubbleColor(particle, ratio);
@@ -110,7 +111,7 @@ class Bubbler extends engine_1.ExternalInteractorBase {
110
111
  particle.bubble.color = undefined;
111
112
  const pColor = particle.getFillColor();
112
113
  particle.bubble.color = pColor
113
- ? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
114
+ ? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio))
114
115
  : particle.bubble.finalColor;
115
116
  }
116
117
  else {
@@ -122,7 +123,7 @@ class Bubbler extends engine_1.ExternalInteractorBase {
122
123
  if (!modeOpacity) {
123
124
  return;
124
125
  }
125
- const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = (0, Utils_js_1.calculateBubbleValue)(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
126
+ const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? defaultOpacity, opacity = (0, Utils_js_1.calculateBubbleValue)(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
126
127
  if (opacity !== undefined) {
127
128
  particle.bubble.opacity = opacity;
128
129
  }
@@ -142,8 +143,8 @@ class Bubbler extends engine_1.ExternalInteractorBase {
142
143
  if (!bubbleOptions || bubbleParam === undefined) {
143
144
  return;
144
145
  }
145
- const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
146
- if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
146
+ const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value ?? defaultBubbleValue, type = data.type;
147
+ if (!bubbleDistance || bubbleDistance < minDistance || bubbleParam === particlesParam) {
147
148
  return;
148
149
  }
149
150
  if (!container.bubble) {
@@ -189,9 +190,9 @@ class Bubbler extends engine_1.ExternalInteractorBase {
189
190
  }
190
191
  selectors.forEach((item) => {
191
192
  const elem = item, pxRatio = container.retina.pixelRatio, pos = {
192
- x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
193
- y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
194
- }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
193
+ x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
194
+ y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
195
+ }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === "circle"
195
196
  ? new engine_1.Circle(pos.x, pos.y, repulseRadius)
196
197
  : 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));
197
198
  for (const particle of query) {
@@ -204,9 +205,9 @@ class Bubbler extends engine_1.ExternalInteractorBase {
204
205
  this.clear(particle, delta, true);
205
206
  particle.bubble.div = elem;
206
207
  }
207
- this._hoverBubbleSize(particle, 1, divBubble);
208
- this._hoverBubbleOpacity(particle, 1, divBubble);
209
- this._hoverBubbleColor(particle, 1, divBubble);
208
+ this._hoverBubbleSize(particle, defaultRatio, divBubble);
209
+ this._hoverBubbleOpacity(particle, defaultRatio, divBubble);
210
+ this._hoverBubbleColor(particle, defaultRatio, divBubble);
210
211
  }
211
212
  });
212
213
  };
@@ -253,10 +254,11 @@ class Bubbler extends engine_1.ExternalInteractorBase {
253
254
  else {
254
255
  (0, engine_1.divModeExecute)(bubbleMode, divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
255
256
  }
257
+ await Promise.resolve();
256
258
  }
257
259
  isEnabled(particle) {
258
260
  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);
259
- if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
261
+ if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
260
262
  return false;
261
263
  }
262
264
  return (0, engine_1.isInArray)(bubbleMode, onHover.mode) || (0, engine_1.isInArray)(bubbleMode, onClick.mode) || divBubble;
package/esm/Bubbler.js CHANGED
@@ -1,7 +1,7 @@
1
- import { Circle, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
1
+ import { Circle, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, millisecondsToSeconds, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
2
2
  import { Bubble } from "./Options/Classes/Bubble.js";
3
3
  import { calculateBubbleValue } from "./Utils.js";
4
- const bubbleMode = "bubble";
4
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
5
5
  export class Bubbler extends ExternalInteractorBase {
6
6
  constructor(container) {
7
7
  super(container);
@@ -14,7 +14,7 @@ export class Bubbler extends ExternalInteractorBase {
14
14
  container.bubble = {};
15
15
  }
16
16
  const distance = container.retina.bubbleModeDistance;
17
- if (!distance || distance < 0) {
17
+ if (!distance || distance < minDistance) {
18
18
  return;
19
19
  }
20
20
  const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
@@ -23,11 +23,12 @@ export class Bubbler extends ExternalInteractorBase {
23
23
  continue;
24
24
  }
25
25
  particle.bubble.inRange = !bubble.durationEnd;
26
- const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
26
+ const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
27
+ millisecondsToSeconds;
27
28
  if (timeSpent > bubbleOptions.duration) {
28
29
  bubble.durationEnd = true;
29
30
  }
30
- if (timeSpent > bubbleOptions.duration * 2) {
31
+ if (timeSpent > bubbleOptions.duration * double) {
31
32
  bubble.clicking = false;
32
33
  bubble.durationEnd = false;
33
34
  }
@@ -50,7 +51,7 @@ export class Bubbler extends ExternalInteractorBase {
50
51
  },
51
52
  particlesObj: {
52
53
  optValue: getRangeMax(particle.options.opacity.value),
53
- value: particle.opacity?.value ?? 1,
54
+ value: particle.opacity?.value ?? defaultOpacity,
54
55
  },
55
56
  type: "opacity",
56
57
  };
@@ -65,15 +66,15 @@ export class Bubbler extends ExternalInteractorBase {
65
66
  };
66
67
  this._hoverBubble = () => {
67
68
  const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
68
- if (!distance || distance < 0 || mousePos === undefined) {
69
+ if (!distance || distance < minDistance || !mousePos) {
69
70
  return;
70
71
  }
71
72
  const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
72
73
  for (const particle of query) {
73
74
  particle.bubble.inRange = true;
74
- const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
75
+ const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
75
76
  if (pointDistance <= distance) {
76
- if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
77
+ if (ratio >= minRatio && container.interactivity.status === mouseMoveEvent) {
77
78
  this._hoverBubbleSize(particle, ratio);
78
79
  this._hoverBubbleOpacity(particle, ratio);
79
80
  this._hoverBubbleColor(particle, ratio);
@@ -107,7 +108,7 @@ export class Bubbler extends ExternalInteractorBase {
107
108
  particle.bubble.color = undefined;
108
109
  const pColor = particle.getFillColor();
109
110
  particle.bubble.color = pColor
110
- ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
111
+ ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio))
111
112
  : particle.bubble.finalColor;
112
113
  }
113
114
  else {
@@ -119,7 +120,7 @@ export class Bubbler extends ExternalInteractorBase {
119
120
  if (!modeOpacity) {
120
121
  return;
121
122
  }
122
- const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
123
+ const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? defaultOpacity, opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
123
124
  if (opacity !== undefined) {
124
125
  particle.bubble.opacity = opacity;
125
126
  }
@@ -139,8 +140,8 @@ export class Bubbler extends ExternalInteractorBase {
139
140
  if (!bubbleOptions || bubbleParam === undefined) {
140
141
  return;
141
142
  }
142
- const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
143
- if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
143
+ const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value ?? defaultBubbleValue, type = data.type;
144
+ if (!bubbleDistance || bubbleDistance < minDistance || bubbleParam === particlesParam) {
144
145
  return;
145
146
  }
146
147
  if (!container.bubble) {
@@ -186,9 +187,9 @@ export class Bubbler extends ExternalInteractorBase {
186
187
  }
187
188
  selectors.forEach((item) => {
188
189
  const elem = item, pxRatio = container.retina.pixelRatio, pos = {
189
- x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
190
- y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
191
- }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
190
+ x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
191
+ y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
192
+ }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === "circle"
192
193
  ? new Circle(pos.x, pos.y, repulseRadius)
193
194
  : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
194
195
  for (const particle of query) {
@@ -201,9 +202,9 @@ export class Bubbler extends ExternalInteractorBase {
201
202
  this.clear(particle, delta, true);
202
203
  particle.bubble.div = elem;
203
204
  }
204
- this._hoverBubbleSize(particle, 1, divBubble);
205
- this._hoverBubbleOpacity(particle, 1, divBubble);
206
- this._hoverBubbleColor(particle, 1, divBubble);
205
+ this._hoverBubbleSize(particle, defaultRatio, divBubble);
206
+ this._hoverBubbleOpacity(particle, defaultRatio, divBubble);
207
+ this._hoverBubbleColor(particle, defaultRatio, divBubble);
207
208
  }
208
209
  });
209
210
  };
@@ -250,10 +251,11 @@ export class Bubbler extends ExternalInteractorBase {
250
251
  else {
251
252
  divModeExecute(bubbleMode, divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
252
253
  }
254
+ await Promise.resolve();
253
255
  }
254
256
  isEnabled(particle) {
255
257
  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
- if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
258
+ if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
257
259
  return false;
258
260
  }
259
261
  return isInArray(bubbleMode, onHover.mode) || isInArray(bubbleMode, onClick.mode) || divBubble;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/interaction-external-bubble",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "tsParticles bubble external interaction",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -87,7 +87,7 @@
87
87
  "./package.json": "./package.json"
88
88
  },
89
89
  "dependencies": {
90
- "@tsparticles/engine": "^3.0.2"
90
+ "@tsparticles/engine": "^3.1.0"
91
91
  },
92
92
  "publishConfig": {
93
93
  "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 [6 Dec 2023 at 17:39]</title>
6
+ <title>@tsparticles/interaction-external-bubble [13 Jan 2024 at 22:59]</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>
@@ -31,7 +31,7 @@
31
31
  <body>
32
32
  <div id="app"></div>
33
33
  <script>
34
- window.chartData = [{"label":"tsparticles.interaction.external.bubble.js","isAsset":true,"statSize":14238,"parsedSize":18134,"gzipSize":4062,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":14196,"groups":[{"id":403,"label":"index.js + 5 modules (concatenated)","path":"./dist/browser/index.js + 5 modules (concatenated)","statSize":14196,"parsedSize":18134,"gzipSize":4062,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser","statSize":14196,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/index.js","statSize":509,"parsedSize":650,"gzipSize":145,"inaccurateSizes":true},{"id":null,"label":"Bubbler.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Bubbler.js","statSize":11607,"parsedSize":14826,"gzipSize":3321,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes","statSize":1626,"groups":[{"id":null,"label":"Bubble.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes/Bubble.js","statSize":419,"parsedSize":535,"gzipSize":119,"inaccurateSizes":true},{"id":null,"label":"BubbleBase.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes/BubbleBase.js","statSize":893,"parsedSize":1140,"gzipSize":255,"inaccurateSizes":true},{"id":null,"label":"BubbleDiv.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes/BubbleDiv.js","statSize":314,"parsedSize":401,"gzipSize":89,"inaccurateSizes":true}],"parsedSize":2077,"gzipSize":465,"inaccurateSizes":true},{"id":null,"label":"Utils.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Utils.js","statSize":454,"parsedSize":579,"gzipSize":129,"inaccurateSizes":true}],"parsedSize":18134,"gzipSize":4062,"inaccurateSizes":true}]}],"parsedSize":18134,"gzipSize":4062},{"label":"engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":533,"label":"engine\",\"root\":\"window\"}","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles/engine\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.interaction.external.bubble":true}}];
34
+ window.chartData = [{"label":"tsparticles.interaction.external.bubble.js","isAsset":true,"statSize":14632,"parsedSize":18541,"gzipSize":4168,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":14590,"groups":[{"id":322,"label":"index.js + 5 modules (concatenated)","path":"./dist/browser/index.js + 5 modules (concatenated)","statSize":14590,"parsedSize":18541,"gzipSize":4168,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser","statSize":14590,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/index.js","statSize":509,"parsedSize":646,"gzipSize":145,"inaccurateSizes":true},{"id":null,"label":"Bubbler.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Bubbler.js","statSize":12001,"parsedSize":15250,"gzipSize":3428,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes","statSize":1626,"groups":[{"id":null,"label":"Bubble.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes/Bubble.js","statSize":419,"parsedSize":532,"gzipSize":119,"inaccurateSizes":true},{"id":null,"label":"BubbleBase.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes/BubbleBase.js","statSize":893,"parsedSize":1134,"gzipSize":255,"inaccurateSizes":true},{"id":null,"label":"BubbleDiv.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Options/Classes/BubbleDiv.js","statSize":314,"parsedSize":399,"gzipSize":89,"inaccurateSizes":true}],"parsedSize":2066,"gzipSize":464,"inaccurateSizes":true},{"id":null,"label":"Utils.js","path":"./dist/browser/index.js + 5 modules (concatenated)/dist/browser/Utils.js","statSize":454,"parsedSize":576,"gzipSize":129,"inaccurateSizes":true}],"parsedSize":18541,"gzipSize":4168,"inaccurateSizes":true}]}],"parsedSize":18541,"gzipSize":4168},{"label":"engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":533,"label":"engine\",\"root\":\"window\"}","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles/engine\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.interaction.external.bubble":true}}];
35
35
  window.entrypoints = ["tsparticles.interaction.external.bubble","tsparticles.interaction.external.bubble.min"];
36
36
  window.defaultSizes = "parsed";
37
37
  </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
- * v3.0.2
7
+ * v3.1.0
8
8
  */
9
9
  (function webpackUniversalModuleDefinition(root, factory) {
10
10
  if(typeof exports === 'object' && typeof module === 'object')
@@ -183,7 +183,16 @@ function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
183
183
 
184
184
 
185
185
 
186
- const bubbleMode = "bubble";
186
+ const bubbleMode = "bubble",
187
+ minDistance = 0,
188
+ defaultClickTime = 0,
189
+ Bubbler_double = 2,
190
+ defaultOpacity = 1,
191
+ ratioOffset = 1,
192
+ defaultBubbleValue = 0,
193
+ minRatio = 0,
194
+ half = 0.5,
195
+ defaultRatio = 1;
187
196
  class Bubbler extends engine_root_window_.ExternalInteractorBase {
188
197
  constructor(container) {
189
198
  super(container);
@@ -199,7 +208,7 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
199
208
  container.bubble = {};
200
209
  }
201
210
  const distance = container.retina.bubbleModeDistance;
202
- if (!distance || distance < 0) {
211
+ if (!distance || distance < minDistance) {
203
212
  return;
204
213
  }
205
214
  const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p)),
@@ -213,11 +222,11 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
213
222
  particle.bubble.inRange = !bubble.durationEnd;
214
223
  const pos = particle.getPosition(),
215
224
  distMouse = (0,engine_root_window_.getDistance)(pos, mouseClickPos),
216
- timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
225
+ timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) / engine_root_window_.millisecondsToSeconds;
217
226
  if (timeSpent > bubbleOptions.duration) {
218
227
  bubble.durationEnd = true;
219
228
  }
220
- if (timeSpent > bubbleOptions.duration * 2) {
229
+ if (timeSpent > bubbleOptions.duration * Bubbler_double) {
221
230
  bubble.clicking = false;
222
231
  bubble.durationEnd = false;
223
232
  }
@@ -240,7 +249,7 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
240
249
  },
241
250
  particlesObj: {
242
251
  optValue: (0,engine_root_window_.getRangeMax)(particle.options.opacity.value),
243
- value: particle.opacity?.value ?? 1
252
+ value: particle.opacity?.value ?? defaultOpacity
244
253
  },
245
254
  type: "opacity"
246
255
  };
@@ -256,7 +265,7 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
256
265
  const container = this.container,
257
266
  mousePos = container.interactivity.mouse.position,
258
267
  distance = container.retina.bubbleModeDistance;
259
- if (!distance || distance < 0 || mousePos === undefined) {
268
+ if (!distance || distance < minDistance || !mousePos) {
260
269
  return;
261
270
  }
262
271
  const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
@@ -264,9 +273,9 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
264
273
  particle.bubble.inRange = true;
265
274
  const pos = particle.getPosition(),
266
275
  pointDistance = (0,engine_root_window_.getDistance)(pos, mousePos),
267
- ratio = 1 - pointDistance / distance;
276
+ ratio = ratioOffset - pointDistance / distance;
268
277
  if (pointDistance <= distance) {
269
- if (ratio >= 0 && container.interactivity.status === engine_root_window_.mouseMoveEvent) {
278
+ if (ratio >= minRatio && container.interactivity.status === engine_root_window_.mouseMoveEvent) {
270
279
  this._hoverBubbleSize(particle, ratio);
271
280
  this._hoverBubbleOpacity(particle, ratio);
272
281
  this._hoverBubbleColor(particle, ratio);
@@ -299,7 +308,7 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
299
308
  if (bubbleOptions.mix) {
300
309
  particle.bubble.color = undefined;
301
310
  const pColor = particle.getFillColor();
302
- particle.bubble.color = pColor ? (0,engine_root_window_.rgbToHsl)((0,engine_root_window_.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio)) : particle.bubble.finalColor;
311
+ particle.bubble.color = pColor ? (0,engine_root_window_.rgbToHsl)((0,engine_root_window_.colorMix)(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio)) : particle.bubble.finalColor;
303
312
  } else {
304
313
  particle.bubble.color = particle.bubble.finalColor;
305
314
  }
@@ -312,7 +321,7 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
312
321
  return;
313
322
  }
314
323
  const optOpacity = particle.options.opacity.value,
315
- pOpacity = particle.opacity?.value ?? 1,
324
+ pOpacity = particle.opacity?.value ?? defaultOpacity,
316
325
  opacity = calculateBubbleValue(pOpacity, modeOpacity, (0,engine_root_window_.getRangeMax)(optOpacity), ratio);
317
326
  if (opacity !== undefined) {
318
327
  particle.bubble.opacity = opacity;
@@ -343,9 +352,9 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
343
352
  bubbleDistance = container.retina.bubbleModeDistance,
344
353
  particlesParam = data.particlesObj.optValue,
345
354
  pObjBubble = data.bubbleObj.value,
346
- pObj = data.particlesObj.value || 0,
355
+ pObj = data.particlesObj.value ?? defaultBubbleValue,
347
356
  type = data.type;
348
- if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
357
+ if (!bubbleDistance || bubbleDistance < minDistance || bubbleParam === particlesParam) {
349
358
  return;
350
359
  }
351
360
  if (!container.bubble) {
@@ -393,10 +402,10 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
393
402
  const elem = item,
394
403
  pxRatio = container.retina.pixelRatio,
395
404
  pos = {
396
- x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
397
- y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio
405
+ x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
406
+ y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio
398
407
  },
399
- repulseRadius = elem.offsetWidth / 2 * pxRatio,
408
+ repulseRadius = elem.offsetWidth * half * pxRatio,
400
409
  area = div.type === "circle" ? new engine_root_window_.Circle(pos.x, pos.y, repulseRadius) : new engine_root_window_.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio),
401
410
  query = container.particles.quadTree.query(area, p => this.isEnabled(p));
402
411
  for (const particle of query) {
@@ -410,9 +419,9 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
410
419
  this.clear(particle, delta, true);
411
420
  particle.bubble.div = elem;
412
421
  }
413
- this._hoverBubbleSize(particle, 1, divBubble);
414
- this._hoverBubbleOpacity(particle, 1, divBubble);
415
- this._hoverBubbleColor(particle, 1, divBubble);
422
+ this._hoverBubbleSize(particle, defaultRatio, divBubble);
423
+ this._hoverBubbleOpacity(particle, defaultRatio, divBubble);
424
+ this._hoverBubbleColor(particle, defaultRatio, divBubble);
416
425
  }
417
426
  });
418
427
  };
@@ -466,6 +475,7 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
466
475
  } else {
467
476
  (0,engine_root_window_.divModeExecute)(bubbleMode, divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
468
477
  }
478
+ await Promise.resolve();
469
479
  }
470
480
  isEnabled(particle) {
471
481
  const container = this.container,
@@ -478,7 +488,7 @@ class Bubbler extends engine_root_window_.ExternalInteractorBase {
478
488
  onHover
479
489
  } = events,
480
490
  divBubble = (0,engine_root_window_.isDivModeEnabled)(bubbleMode, onDiv);
481
- if (!(divBubble || onHover.enable && mouse.position || onClick.enable && mouse.clickPosition)) {
491
+ if (!(divBubble || onHover.enable && !!mouse.position || onClick.enable && mouse.clickPosition)) {
482
492
  return false;
483
493
  }
484
494
  return (0,engine_root_window_.isInArray)(bubbleMode, onHover.mode) || (0,engine_root_window_.isInArray)(bubbleMode, onClick.mode) || divBubble;
@@ -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 i="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in i)("object"==typeof exports?exports:e)[o]=i[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},i={};function o(e){var n=i[e];if(void 0!==n)return n.exports;var b=i[e]={exports:{}};return t[e](b,b.exports,o),b.exports}o.d=(e,t)=>{for(var i in t)o.o(t,i)&&!o.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};return(()=>{o.r(n),o.d(n,{Bubble:()=>b,BubbleBase:()=>t,BubbleDiv:()=>i,loadExternalBubbleInteraction:()=>a});var e=o(533);class t{constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(t){if(t){if(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.mix&&(this.mix=t.mix),void 0!==t.opacity&&(this.opacity=t.opacity),void 0!==t.color){const i=(0,e.isArray)(this.color)?void 0:this.color;this.color=(0,e.executeOnSingleOrMultiple)(t.color,(t=>e.OptionsColor.create(i,t)))}void 0!==t.size&&(this.size=t.size)}}}class i extends t{constructor(){super(),this.selectors=[]}load(e){super.load(e),e&&void 0!==e.selectors&&(this.selectors=e.selectors)}}class b extends t{load(t){super.load(t),t&&(this.divs=(0,e.executeOnSingleOrMultiple)(t.divs,(e=>{const t=new i;return t.load(e),t})))}}function l(t,i,o,n){if(i>=o){const b=t+(i-o)*n;return(0,e.clamp)(b,t,i)}if(i<o){const b=t-(o-i)*n;return(0,e.clamp)(b,i,t)}}const s="bubble";class r extends e.ExternalInteractorBase{constructor(t){super(t),this._clickBubble=()=>{const t=this.container,i=t.actualOptions,o=t.interactivity.mouse.clickPosition,n=i.interactivity.modes.bubble;if(!n||!o)return;t.bubble||(t.bubble={});const b=t.retina.bubbleModeDistance;if(!b||b<0)return;const l=t.particles.quadTree.queryCircle(o,b,(e=>this.isEnabled(e))),{bubble:s}=t;for(const i of l){if(!s.clicking)continue;i.bubble.inRange=!s.durationEnd;const l=i.getPosition(),r=(0,e.getDistance)(l,o),a=((new Date).getTime()-(t.interactivity.mouse.clickTime||0))/1e3;a>n.duration&&(s.durationEnd=!0),a>2*n.duration&&(s.clicking=!1,s.durationEnd=!1);const c={bubbleObj:{optValue:t.retina.bubbleModeSize,value:i.bubble.radius},particlesObj:{optValue:(0,e.getRangeMax)(i.options.size.value)*t.retina.pixelRatio,value:i.size.value},type:"size"};this._process(i,r,a,c);const u={bubbleObj:{optValue:n.opacity,value:i.bubble.opacity},particlesObj:{optValue:(0,e.getRangeMax)(i.options.opacity.value),value:i.opacity?.value??1},type:"opacity"};this._process(i,r,a,u),!s.durationEnd&&r<=b?this._hoverBubbleColor(i,r):delete i.bubble.color}},this._hoverBubble=()=>{const t=this.container,i=t.interactivity.mouse.position,o=t.retina.bubbleModeDistance;if(!o||o<0||void 0===i)return;const n=t.particles.quadTree.queryCircle(i,o,(e=>this.isEnabled(e)));for(const b of n){b.bubble.inRange=!0;const n=b.getPosition(),l=(0,e.getDistance)(n,i),s=1-l/o;l<=o?s>=0&&t.interactivity.status===e.mouseMoveEvent&&(this._hoverBubbleSize(b,s),this._hoverBubbleOpacity(b,s),this._hoverBubbleColor(b,s)):this.reset(b),t.interactivity.status===e.mouseLeaveEvent&&this.reset(b)}},this._hoverBubbleColor=(t,i,o)=>{const n=this.container.actualOptions,b=o??n.interactivity.modes.bubble;if(b){if(!t.bubble.finalColor){const i=b.color;if(!i)return;const o=(0,e.itemFromSingleOrMultiple)(i);t.bubble.finalColor=(0,e.rangeColorToHsl)(o)}if(t.bubble.finalColor)if(b.mix){t.bubble.color=void 0;const o=t.getFillColor();t.bubble.color=o?(0,e.rgbToHsl)((0,e.colorMix)(o,t.bubble.finalColor,1-i,i)):t.bubble.finalColor}else t.bubble.color=t.bubble.finalColor}},this._hoverBubbleOpacity=(t,i,o)=>{const n=this.container.actualOptions,b=o?.opacity??n.interactivity.modes.bubble?.opacity;if(!b)return;const s=t.options.opacity.value,r=l(t.opacity?.value??1,b,(0,e.getRangeMax)(s),i);void 0!==r&&(t.bubble.opacity=r)},this._hoverBubbleSize=(t,i,o)=>{const n=this.container,b=o?.size?o.size*n.retina.pixelRatio:n.retina.bubbleModeSize;if(void 0===b)return;const s=(0,e.getRangeMax)(t.options.size.value)*n.retina.pixelRatio,r=l(t.size.value,b,s,i);void 0!==r&&(t.bubble.radius=r)},this._process=(e,t,i,o)=>{const n=this.container,b=o.bubbleObj.optValue,l=n.actualOptions.interactivity.modes.bubble;if(!l||void 0===b)return;const s=l.duration,r=n.retina.bubbleModeDistance,a=o.particlesObj.optValue,c=o.bubbleObj.value,u=o.particlesObj.value||0,d=o.type;if(r&&!(r<0)&&b!==a)if(n.bubble||(n.bubble={}),n.bubble.durationEnd)c&&("size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity);else if(t<=r){if((c??u)!==b){const t=u-i*(u-b)/s;"size"===d&&(e.bubble.radius=t),"opacity"===d&&(e.bubble.opacity=t)}}else"size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity},this._singleSelectorHover=(t,i,o)=>{const n=this.container,b=document.querySelectorAll(i),l=n.actualOptions.interactivity.modes.bubble;l&&b.length&&b.forEach((i=>{const b=i,s=n.retina.pixelRatio,r={x:(b.offsetLeft+b.offsetWidth/2)*s,y:(b.offsetTop+b.offsetHeight/2)*s},a=b.offsetWidth/2*s,c="circle"===o.type?new e.Circle(r.x,r.y,a):new e.Rectangle(b.offsetLeft*s,b.offsetTop*s,b.offsetWidth*s,b.offsetHeight*s),u=n.particles.quadTree.query(c,(e=>this.isEnabled(e)));for(const i of u){if(!c.contains(i.getPosition()))continue;i.bubble.inRange=!0;const o=l.divs,n=(0,e.divMode)(o,b);i.bubble.div&&i.bubble.div===b||(this.clear(i,t,!0),i.bubble.div=b),this._hoverBubbleSize(i,1,n),this._hoverBubbleOpacity(i,1,n),this._hoverBubbleColor(i,1,n)}}))},t.bubble||(t.bubble={}),this.handleClickMode=e=>{e===s&&(t.bubble||(t.bubble={}),t.bubble.clicking=!0)}}clear(e,t,i){e.bubble.inRange&&!i||(delete e.bubble.div,delete e.bubble.opacity,delete e.bubble.radius,delete e.bubble.color)}init(){const e=this.container,t=e.actualOptions.interactivity.modes.bubble;t&&(e.retina.bubbleModeDistance=t.distance*e.retina.pixelRatio,void 0!==t.size&&(e.retina.bubbleModeSize=t.size*e.retina.pixelRatio))}async interact(t){const i=this.container.actualOptions.interactivity.events,o=i.onHover,n=i.onClick,b=o.enable,l=o.mode,r=n.enable,a=n.mode,c=i.onDiv;b&&(0,e.isInArray)(s,l)?this._hoverBubble():r&&(0,e.isInArray)(s,a)?this._clickBubble():(0,e.divModeExecute)(s,c,((e,i)=>this._singleSelectorHover(t,e,i)))}isEnabled(t){const i=this.container,o=i.actualOptions,n=i.interactivity.mouse,b=(t?.interactivity??o.interactivity).events,{onClick:l,onDiv:r,onHover:a}=b,c=(0,e.isDivModeEnabled)(s,r);return!!(c||a.enable&&n.position||l.enable&&n.clickPosition)&&((0,e.isInArray)(s,a.mode)||(0,e.isInArray)(s,l.mode)||c)}loadModeOptions(e,...t){e.bubble||(e.bubble=new b);for(const i of t)e.bubble.load(i?.bubble)}reset(e){e.bubble.inRange=!1}}async function a(e,t=!0){await e.addInteractor("externalBubble",(e=>new r(e)),t)}})(),n})()));
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 i="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in i)("object"==typeof exports?exports:e)[o]=i[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},i={};function o(e){var n=i[e];if(void 0!==n)return n.exports;var b=i[e]={exports:{}};return t[e](b,b.exports,o),b.exports}o.d=(e,t)=>{for(var i in t)o.o(t,i)&&!o.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};return(()=>{o.r(n),o.d(n,{Bubble:()=>b,BubbleBase:()=>t,BubbleDiv:()=>i,loadExternalBubbleInteraction:()=>a});var e=o(533);class t{constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(t){if(t){if(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.mix&&(this.mix=t.mix),void 0!==t.opacity&&(this.opacity=t.opacity),void 0!==t.color){const i=(0,e.isArray)(this.color)?void 0:this.color;this.color=(0,e.executeOnSingleOrMultiple)(t.color,(t=>e.OptionsColor.create(i,t)))}void 0!==t.size&&(this.size=t.size)}}}class i extends t{constructor(){super(),this.selectors=[]}load(e){super.load(e),e&&void 0!==e.selectors&&(this.selectors=e.selectors)}}class b extends t{load(t){super.load(t),t&&(this.divs=(0,e.executeOnSingleOrMultiple)(t.divs,(e=>{const t=new i;return t.load(e),t})))}}function s(t,i,o,n){if(i>=o){const b=t+(i-o)*n;return(0,e.clamp)(b,t,i)}if(i<o){const b=t-(o-i)*n;return(0,e.clamp)(b,i,t)}}const l="bubble";class r extends e.ExternalInteractorBase{constructor(t){super(t),this._clickBubble=()=>{const t=this.container,i=t.actualOptions,o=t.interactivity.mouse.clickPosition,n=i.interactivity.modes.bubble;if(!n||!o)return;t.bubble||(t.bubble={});const b=t.retina.bubbleModeDistance;if(!b||b<0)return;const s=t.particles.quadTree.queryCircle(o,b,(e=>this.isEnabled(e))),{bubble:l}=t;for(const i of s){if(!l.clicking)continue;i.bubble.inRange=!l.durationEnd;const s=i.getPosition(),r=(0,e.getDistance)(s,o),a=((new Date).getTime()-(t.interactivity.mouse.clickTime??0))/e.millisecondsToSeconds;a>n.duration&&(l.durationEnd=!0),a>2*n.duration&&(l.clicking=!1,l.durationEnd=!1);const c={bubbleObj:{optValue:t.retina.bubbleModeSize,value:i.bubble.radius},particlesObj:{optValue:(0,e.getRangeMax)(i.options.size.value)*t.retina.pixelRatio,value:i.size.value},type:"size"};this._process(i,r,a,c);const u={bubbleObj:{optValue:n.opacity,value:i.bubble.opacity},particlesObj:{optValue:(0,e.getRangeMax)(i.options.opacity.value),value:i.opacity?.value??1},type:"opacity"};this._process(i,r,a,u),!l.durationEnd&&r<=b?this._hoverBubbleColor(i,r):delete i.bubble.color}},this._hoverBubble=()=>{const t=this.container,i=t.interactivity.mouse.position,o=t.retina.bubbleModeDistance;if(!o||o<0||!i)return;const n=t.particles.quadTree.queryCircle(i,o,(e=>this.isEnabled(e)));for(const b of n){b.bubble.inRange=!0;const n=b.getPosition(),s=(0,e.getDistance)(n,i),l=1-s/o;s<=o?l>=0&&t.interactivity.status===e.mouseMoveEvent&&(this._hoverBubbleSize(b,l),this._hoverBubbleOpacity(b,l),this._hoverBubbleColor(b,l)):this.reset(b),t.interactivity.status===e.mouseLeaveEvent&&this.reset(b)}},this._hoverBubbleColor=(t,i,o)=>{const n=this.container.actualOptions,b=o??n.interactivity.modes.bubble;if(b){if(!t.bubble.finalColor){const i=b.color;if(!i)return;const o=(0,e.itemFromSingleOrMultiple)(i);t.bubble.finalColor=(0,e.rangeColorToHsl)(o)}if(t.bubble.finalColor)if(b.mix){t.bubble.color=void 0;const o=t.getFillColor();t.bubble.color=o?(0,e.rgbToHsl)((0,e.colorMix)(o,t.bubble.finalColor,1-i,i)):t.bubble.finalColor}else t.bubble.color=t.bubble.finalColor}},this._hoverBubbleOpacity=(t,i,o)=>{const n=this.container.actualOptions,b=o?.opacity??n.interactivity.modes.bubble?.opacity;if(!b)return;const l=t.options.opacity.value,r=s(t.opacity?.value??1,b,(0,e.getRangeMax)(l),i);void 0!==r&&(t.bubble.opacity=r)},this._hoverBubbleSize=(t,i,o)=>{const n=this.container,b=o?.size?o.size*n.retina.pixelRatio:n.retina.bubbleModeSize;if(void 0===b)return;const l=(0,e.getRangeMax)(t.options.size.value)*n.retina.pixelRatio,r=s(t.size.value,b,l,i);void 0!==r&&(t.bubble.radius=r)},this._process=(e,t,i,o)=>{const n=this.container,b=o.bubbleObj.optValue,s=n.actualOptions.interactivity.modes.bubble;if(!s||void 0===b)return;const l=s.duration,r=n.retina.bubbleModeDistance,a=o.particlesObj.optValue,c=o.bubbleObj.value,u=o.particlesObj.value??0,d=o.type;if(r&&!(r<0)&&b!==a)if(n.bubble||(n.bubble={}),n.bubble.durationEnd)c&&("size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity);else if(t<=r){if((c??u)!==b){const t=u-i*(u-b)/l;"size"===d&&(e.bubble.radius=t),"opacity"===d&&(e.bubble.opacity=t)}}else"size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity},this._singleSelectorHover=(t,i,o)=>{const n=this.container,b=document.querySelectorAll(i),s=n.actualOptions.interactivity.modes.bubble;s&&b.length&&b.forEach((i=>{const b=i,l=n.retina.pixelRatio,r={x:(b.offsetLeft+.5*b.offsetWidth)*l,y:(b.offsetTop+.5*b.offsetHeight)*l},a=.5*b.offsetWidth*l,c="circle"===o.type?new e.Circle(r.x,r.y,a):new e.Rectangle(b.offsetLeft*l,b.offsetTop*l,b.offsetWidth*l,b.offsetHeight*l),u=n.particles.quadTree.query(c,(e=>this.isEnabled(e)));for(const i of u){if(!c.contains(i.getPosition()))continue;i.bubble.inRange=!0;const o=s.divs,n=(0,e.divMode)(o,b);i.bubble.div&&i.bubble.div===b||(this.clear(i,t,!0),i.bubble.div=b),this._hoverBubbleSize(i,1,n),this._hoverBubbleOpacity(i,1,n),this._hoverBubbleColor(i,1,n)}}))},t.bubble||(t.bubble={}),this.handleClickMode=e=>{e===l&&(t.bubble||(t.bubble={}),t.bubble.clicking=!0)}}clear(e,t,i){e.bubble.inRange&&!i||(delete e.bubble.div,delete e.bubble.opacity,delete e.bubble.radius,delete e.bubble.color)}init(){const e=this.container,t=e.actualOptions.interactivity.modes.bubble;t&&(e.retina.bubbleModeDistance=t.distance*e.retina.pixelRatio,void 0!==t.size&&(e.retina.bubbleModeSize=t.size*e.retina.pixelRatio))}async interact(t){const i=this.container.actualOptions.interactivity.events,o=i.onHover,n=i.onClick,b=o.enable,s=o.mode,r=n.enable,a=n.mode,c=i.onDiv;b&&(0,e.isInArray)(l,s)?this._hoverBubble():r&&(0,e.isInArray)(l,a)?this._clickBubble():(0,e.divModeExecute)(l,c,((e,i)=>this._singleSelectorHover(t,e,i))),await Promise.resolve()}isEnabled(t){const i=this.container,o=i.actualOptions,n=i.interactivity.mouse,b=(t?.interactivity??o.interactivity).events,{onClick:s,onDiv:r,onHover:a}=b,c=(0,e.isDivModeEnabled)(l,r);return!!(c||a.enable&&n.position||s.enable&&n.clickPosition)&&((0,e.isInArray)(l,a.mode)||(0,e.isInArray)(l,s.mode)||c)}loadModeOptions(e,...t){e.bubble||(e.bubble=new b);for(const i of t)e.bubble.load(i?.bubble)}reset(e){e.bubble.inRange=!1}}async function a(e,t=!0){await e.addInteractor("externalBubble",(e=>new r(e)),t)}})(),n})()));
@@ -1 +1 @@
1
- /*! tsParticles Bubble External Interaction v3.0.2 by Matteo Bruni */
1
+ /*! tsParticles Bubble External Interaction v3.1.0 by Matteo Bruni */
package/types/Types.d.ts CHANGED
@@ -2,12 +2,12 @@ import type { Bubble } from "./Options/Classes/Bubble.js";
2
2
  import type { BubbleOptions } from "./Options/Classes/BubbleOptions.js";
3
3
  import type { Container } from "@tsparticles/engine";
4
4
  import type { IBubble } from "./Options/Interfaces/IBubble.js";
5
- export type IBubbleMode = {
5
+ export interface IBubbleMode {
6
6
  bubble: IBubble;
7
- };
8
- export type BubbleMode = {
7
+ }
8
+ export interface BubbleMode {
9
9
  bubble?: Bubble;
10
- };
10
+ }
11
11
  interface IContainerBubble {
12
12
  clicking?: boolean;
13
13
  durationEnd?: boolean;
package/umd/Bubbler.js CHANGED
@@ -13,7 +13,7 @@
13
13
  const engine_1 = require("@tsparticles/engine");
14
14
  const Bubble_js_1 = require("./Options/Classes/Bubble.js");
15
15
  const Utils_js_1 = require("./Utils.js");
16
- const bubbleMode = "bubble";
16
+ const bubbleMode = "bubble", minDistance = 0, defaultClickTime = 0, double = 2, defaultOpacity = 1, ratioOffset = 1, defaultBubbleValue = 0, minRatio = 0, half = 0.5, defaultRatio = 1;
17
17
  class Bubbler extends engine_1.ExternalInteractorBase {
18
18
  constructor(container) {
19
19
  super(container);
@@ -26,7 +26,7 @@
26
26
  container.bubble = {};
27
27
  }
28
28
  const distance = container.retina.bubbleModeDistance;
29
- if (!distance || distance < 0) {
29
+ if (!distance || distance < minDistance) {
30
30
  return;
31
31
  }
32
32
  const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
@@ -35,11 +35,12 @@
35
35
  continue;
36
36
  }
37
37
  particle.bubble.inRange = !bubble.durationEnd;
38
- const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
38
+ const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime ?? defaultClickTime)) /
39
+ engine_1.millisecondsToSeconds;
39
40
  if (timeSpent > bubbleOptions.duration) {
40
41
  bubble.durationEnd = true;
41
42
  }
42
- if (timeSpent > bubbleOptions.duration * 2) {
43
+ if (timeSpent > bubbleOptions.duration * double) {
43
44
  bubble.clicking = false;
44
45
  bubble.durationEnd = false;
45
46
  }
@@ -62,7 +63,7 @@
62
63
  },
63
64
  particlesObj: {
64
65
  optValue: (0, engine_1.getRangeMax)(particle.options.opacity.value),
65
- value: particle.opacity?.value ?? 1,
66
+ value: particle.opacity?.value ?? defaultOpacity,
66
67
  },
67
68
  type: "opacity",
68
69
  };
@@ -77,15 +78,15 @@
77
78
  };
78
79
  this._hoverBubble = () => {
79
80
  const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
80
- if (!distance || distance < 0 || mousePos === undefined) {
81
+ if (!distance || distance < minDistance || !mousePos) {
81
82
  return;
82
83
  }
83
84
  const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
84
85
  for (const particle of query) {
85
86
  particle.bubble.inRange = true;
86
- const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = 1 - pointDistance / distance;
87
+ const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
87
88
  if (pointDistance <= distance) {
88
- if (ratio >= 0 && container.interactivity.status === engine_1.mouseMoveEvent) {
89
+ if (ratio >= minRatio && container.interactivity.status === engine_1.mouseMoveEvent) {
89
90
  this._hoverBubbleSize(particle, ratio);
90
91
  this._hoverBubbleOpacity(particle, ratio);
91
92
  this._hoverBubbleColor(particle, ratio);
@@ -119,7 +120,7 @@
119
120
  particle.bubble.color = undefined;
120
121
  const pColor = particle.getFillColor();
121
122
  particle.bubble.color = pColor
122
- ? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
123
+ ? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, ratioOffset - ratio, ratio))
123
124
  : particle.bubble.finalColor;
124
125
  }
125
126
  else {
@@ -131,7 +132,7 @@
131
132
  if (!modeOpacity) {
132
133
  return;
133
134
  }
134
- const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = (0, Utils_js_1.calculateBubbleValue)(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
135
+ const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? defaultOpacity, opacity = (0, Utils_js_1.calculateBubbleValue)(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
135
136
  if (opacity !== undefined) {
136
137
  particle.bubble.opacity = opacity;
137
138
  }
@@ -151,8 +152,8 @@
151
152
  if (!bubbleOptions || bubbleParam === undefined) {
152
153
  return;
153
154
  }
154
- const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
155
- if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
155
+ const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value ?? defaultBubbleValue, type = data.type;
156
+ if (!bubbleDistance || bubbleDistance < minDistance || bubbleParam === particlesParam) {
156
157
  return;
157
158
  }
158
159
  if (!container.bubble) {
@@ -198,9 +199,9 @@
198
199
  }
199
200
  selectors.forEach((item) => {
200
201
  const elem = item, pxRatio = container.retina.pixelRatio, pos = {
201
- x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
202
- y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
203
- }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
202
+ x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
203
+ y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
204
+ }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === "circle"
204
205
  ? new engine_1.Circle(pos.x, pos.y, repulseRadius)
205
206
  : 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));
206
207
  for (const particle of query) {
@@ -213,9 +214,9 @@
213
214
  this.clear(particle, delta, true);
214
215
  particle.bubble.div = elem;
215
216
  }
216
- this._hoverBubbleSize(particle, 1, divBubble);
217
- this._hoverBubbleOpacity(particle, 1, divBubble);
218
- this._hoverBubbleColor(particle, 1, divBubble);
217
+ this._hoverBubbleSize(particle, defaultRatio, divBubble);
218
+ this._hoverBubbleOpacity(particle, defaultRatio, divBubble);
219
+ this._hoverBubbleColor(particle, defaultRatio, divBubble);
219
220
  }
220
221
  });
221
222
  };
@@ -262,10 +263,11 @@
262
263
  else {
263
264
  (0, engine_1.divModeExecute)(bubbleMode, divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
264
265
  }
266
+ await Promise.resolve();
265
267
  }
266
268
  isEnabled(particle) {
267
269
  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
- if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
270
+ if (!(divBubble || (onHover.enable && !!mouse.position) || (onClick.enable && mouse.clickPosition))) {
269
271
  return false;
270
272
  }
271
273
  return (0, engine_1.isInArray)(bubbleMode, onHover.mode) || (0, engine_1.isInArray)(bubbleMode, onClick.mode) || divBubble;