@tsparticles/interaction-external-bubble 3.0.0-alpha.0 → 3.0.0-beta.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.
Files changed (46) hide show
  1. package/README.md +25 -19
  2. package/browser/Bubbler.js +211 -234
  3. package/browser/Options/Classes/Bubble.js +1 -1
  4. package/browser/Options/Classes/BubbleBase.js +2 -2
  5. package/browser/Options/Classes/BubbleDiv.js +0 -10
  6. package/browser/Utils.js +11 -0
  7. package/browser/index.js +2 -2
  8. package/cjs/Bubbler.js +218 -252
  9. package/cjs/Options/Classes/Bubble.js +1 -1
  10. package/cjs/Options/Classes/BubbleBase.js +1 -1
  11. package/cjs/Options/Classes/BubbleDiv.js +0 -10
  12. package/cjs/Utils.js +15 -0
  13. package/cjs/index.js +2 -13
  14. package/esm/Bubbler.js +211 -234
  15. package/esm/Options/Classes/Bubble.js +1 -1
  16. package/esm/Options/Classes/BubbleBase.js +2 -2
  17. package/esm/Options/Classes/BubbleDiv.js +0 -10
  18. package/esm/Utils.js +11 -0
  19. package/esm/index.js +2 -2
  20. package/package.json +6 -5
  21. package/report.html +4 -4
  22. package/tsparticles.interaction.external.bubble.js +255 -262
  23. package/tsparticles.interaction.external.bubble.min.js +1 -1
  24. package/tsparticles.interaction.external.bubble.min.js.LICENSE.txt +1 -8
  25. package/types/Bubbler.d.ts +8 -9
  26. package/types/{IBubblerProcessParam.d.ts → Interfaces.d.ts} +2 -2
  27. package/types/Options/Classes/Bubble.d.ts +1 -1
  28. package/types/Options/Classes/BubbleBase.d.ts +1 -2
  29. package/types/Options/Classes/BubbleDiv.d.ts +1 -3
  30. package/types/Utils.d.ts +1 -0
  31. package/types/index.d.ts +1 -1
  32. package/umd/Bubbler.js +211 -234
  33. package/umd/Options/Classes/Bubble.js +2 -2
  34. package/umd/Options/Classes/BubbleBase.js +1 -1
  35. package/umd/Options/Classes/BubbleDiv.js +1 -11
  36. package/umd/Utils.js +25 -0
  37. package/umd/index.js +2 -2
  38. /package/browser/{IBubblerProcessParam.js → Enums.js} +0 -0
  39. /package/browser/{ProcessBubbleType.js → Interfaces.js} +0 -0
  40. /package/cjs/{IBubblerProcessParam.js → Enums.js} +0 -0
  41. /package/cjs/{ProcessBubbleType.js → Interfaces.js} +0 -0
  42. /package/esm/{IBubblerProcessParam.js → Enums.js} +0 -0
  43. /package/esm/{ProcessBubbleType.js → Interfaces.js} +0 -0
  44. /package/types/{ProcessBubbleType.d.ts → Enums.d.ts} +0 -0
  45. /package/umd/{IBubblerProcessParam.js → Enums.js} +0 -0
  46. /package/umd/{ProcessBubbleType.js → Interfaces.js} +0 -0
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # tsParticles External Bubble Interaction
4
4
 
5
- [![jsDelivr](https://data.jsdelivr.com/v1/package/npm/tsparticles-interaction-external-bubble/badge)](https://www.jsdelivr.com/package/npm/tsparticles-interaction-external-bubble)
6
- [![npmjs](https://badge.fury.io/js/tsparticles-interaction-external-bubble.svg)](https://www.npmjs.com/package/tsparticles-interaction-external-bubble)
7
- [![npmjs](https://img.shields.io/npm/dt/tsparticles-interaction-external-bubble)](https://www.npmjs.com/package/tsparticles-interaction-external-bubble) [![GitHub Sponsors](https://img.shields.io/github/sponsors/matteobruni)](https://github.com/sponsors/matteobruni)
5
+ [![jsDelivr](https://data.jsdelivr.com/v1/package/npm/@tsparticles/interaction-external-bubble/badge)](https://www.jsdelivr.com/package/npm/@tsparticles/interaction-external-bubble)
6
+ [![npmjs](https://badge.fury.io/js/@tsparticles/interaction-external-bubble.svg)](https://www.npmjs.com/package/@tsparticles/interaction-external-bubble)
7
+ [![npmjs](https://img.shields.io/npm/dt/@tsparticles/interaction-external-bubble)](https://www.npmjs.com/package/@tsparticles/interaction-external-bubble) [![GitHub Sponsors](https://img.shields.io/github/sponsors/matteobruni)](https://github.com/sponsors/matteobruni)
8
8
 
9
9
  [tsParticles](https://github.com/matteobruni/tsparticles) interaction plugin for bubble effect around mouse or HTML
10
10
  elements.
@@ -27,14 +27,16 @@ loadExternalBubbleInteraction;
27
27
  Once the scripts are loaded you can set up `tsParticles` and the interaction plugin like this:
28
28
 
29
29
  ```javascript
30
- loadExternalBubbleInteraction(tsParticles);
31
-
32
- tsParticles.load({
33
- id: "tsparticles",
34
- options: {
35
- /* options */
36
- },
37
- });
30
+ (async () => {
31
+ await loadExternalBubbleInteraction(tsParticles);
32
+
33
+ await tsParticles.load({
34
+ id: "tsparticles",
35
+ options: {
36
+ /* options */
37
+ },
38
+ });
39
+ })();
38
40
  ```
39
41
 
40
42
  ### ESM / CommonJS
@@ -42,29 +44,33 @@ tsParticles.load({
42
44
  This package is compatible also with ES or CommonJS modules, firstly this needs to be installed, like this:
43
45
 
44
46
  ```shell
45
- $ npm install tsparticles-interaction-external-bubble
47
+ $ npm install @tsparticles/interaction-external-bubble
46
48
  ```
47
49
 
48
50
  or
49
51
 
50
52
  ```shell
51
- $ yarn add tsparticles-interaction-external-bubble
53
+ $ yarn add @tsparticles/interaction-external-bubble
52
54
  ```
53
55
 
54
56
  Then you need to import it in the app, like this:
55
57
 
56
58
  ```javascript
57
- const { tsParticles } = require("tsparticles-engine");
58
- const { loadExternalBubbleInteraction } = require("tsparticles-interaction-external-bubble");
59
+ const { tsParticles } = require("@tsparticles/engine");
60
+ const { loadExternalBubbleInteraction } = require("@tsparticles/interaction-external-bubble");
59
61
 
60
- loadExternalBubbleInteraction(tsParticles);
62
+ (async () => {
63
+ await loadExternalBubbleInteraction(tsParticles);
64
+ })();
61
65
  ```
62
66
 
63
67
  or
64
68
 
65
69
  ```javascript
66
- import { tsParticles } from "tsparticles-engine";
67
- import { loadExternalBubbleInteraction } from "tsparticles-interaction-external-bubble";
70
+ import { tsParticles } from "@tsparticles/engine";
71
+ import { loadExternalBubbleInteraction } from "@tsparticles/interaction-external-bubble";
68
72
 
69
- loadExternalBubbleInteraction(tsParticles);
73
+ (async () => {
74
+ await loadExternalBubbleInteraction(tsParticles);
75
+ })();
70
76
  ```
@@ -1,18 +1,211 @@
1
- import { Circle, ExternalInteractorBase, Rectangle, clamp, 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, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
2
2
  import { Bubble } from "./Options/Classes/Bubble";
3
- function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
4
- if (modeValue >= optionsValue) {
5
- const value = particleValue + (modeValue - optionsValue) * ratio;
6
- return clamp(value, particleValue, modeValue);
7
- }
8
- else if (modeValue < optionsValue) {
9
- const value = particleValue - (optionsValue - modeValue) * ratio;
10
- return clamp(value, modeValue, particleValue);
11
- }
12
- }
3
+ import { calculateBubbleValue } from "./Utils";
13
4
  export class Bubbler extends ExternalInteractorBase {
14
5
  constructor(container) {
15
6
  super(container);
7
+ this._clickBubble = () => {
8
+ const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
9
+ if (!bubbleOptions || !mouseClickPos) {
10
+ return;
11
+ }
12
+ if (!container.bubble) {
13
+ container.bubble = {};
14
+ }
15
+ const distance = container.retina.bubbleModeDistance;
16
+ if (!distance || distance < 0) {
17
+ return;
18
+ }
19
+ const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
20
+ for (const particle of query) {
21
+ if (!bubble.clicking) {
22
+ continue;
23
+ }
24
+ particle.bubble.inRange = !bubble.durationEnd;
25
+ const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
26
+ if (timeSpent > bubbleOptions.duration) {
27
+ bubble.durationEnd = true;
28
+ }
29
+ if (timeSpent > bubbleOptions.duration * 2) {
30
+ bubble.clicking = false;
31
+ bubble.durationEnd = false;
32
+ }
33
+ const sizeData = {
34
+ bubbleObj: {
35
+ optValue: container.retina.bubbleModeSize,
36
+ value: particle.bubble.radius,
37
+ },
38
+ particlesObj: {
39
+ optValue: getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
40
+ value: particle.size.value,
41
+ },
42
+ type: "size",
43
+ };
44
+ this._process(particle, distMouse, timeSpent, sizeData);
45
+ const opacityData = {
46
+ bubbleObj: {
47
+ optValue: bubbleOptions.opacity,
48
+ value: particle.bubble.opacity,
49
+ },
50
+ particlesObj: {
51
+ optValue: getRangeMax(particle.options.opacity.value),
52
+ value: particle.opacity?.value ?? 1,
53
+ },
54
+ type: "opacity",
55
+ };
56
+ this._process(particle, distMouse, timeSpent, opacityData);
57
+ if (!bubble.durationEnd && distMouse <= distance) {
58
+ this._hoverBubbleColor(particle, distMouse);
59
+ }
60
+ else {
61
+ delete particle.bubble.color;
62
+ }
63
+ }
64
+ };
65
+ this._hoverBubble = () => {
66
+ const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
67
+ if (!distance || distance < 0 || mousePos === undefined) {
68
+ return;
69
+ }
70
+ const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
71
+ for (const particle of query) {
72
+ particle.bubble.inRange = true;
73
+ const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
74
+ if (pointDistance <= distance) {
75
+ if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
76
+ this._hoverBubbleSize(particle, ratio);
77
+ this._hoverBubbleOpacity(particle, ratio);
78
+ this._hoverBubbleColor(particle, ratio);
79
+ }
80
+ }
81
+ else {
82
+ this.reset(particle);
83
+ }
84
+ if (container.interactivity.status === mouseLeaveEvent) {
85
+ this.reset(particle);
86
+ }
87
+ }
88
+ };
89
+ this._hoverBubbleColor = (particle, ratio, divBubble) => {
90
+ const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
91
+ if (!bubbleOptions) {
92
+ return;
93
+ }
94
+ if (!particle.bubble.finalColor) {
95
+ const modeColor = bubbleOptions.color;
96
+ if (!modeColor) {
97
+ return;
98
+ }
99
+ const bubbleColor = itemFromSingleOrMultiple(modeColor);
100
+ particle.bubble.finalColor = rangeColorToHsl(bubbleColor);
101
+ }
102
+ if (!particle.bubble.finalColor) {
103
+ return;
104
+ }
105
+ if (bubbleOptions.mix) {
106
+ particle.bubble.color = undefined;
107
+ const pColor = particle.getFillColor();
108
+ particle.bubble.color = pColor
109
+ ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
110
+ : particle.bubble.finalColor;
111
+ }
112
+ else {
113
+ particle.bubble.color = particle.bubble.finalColor;
114
+ }
115
+ };
116
+ this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
117
+ const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
118
+ if (!modeOpacity) {
119
+ return;
120
+ }
121
+ const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
122
+ if (opacity !== undefined) {
123
+ particle.bubble.opacity = opacity;
124
+ }
125
+ };
126
+ this._hoverBubbleSize = (particle, ratio, divBubble) => {
127
+ const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
128
+ if (modeSize === undefined) {
129
+ return;
130
+ }
131
+ const optSize = getRangeMax(particle.options.size.value) * container.retina.pixelRatio, pSize = particle.size.value, size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
132
+ if (size !== undefined) {
133
+ particle.bubble.radius = size;
134
+ }
135
+ };
136
+ this._process = (particle, distMouse, timeSpent, data) => {
137
+ const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
138
+ if (!bubbleOptions || bubbleParam === undefined) {
139
+ return;
140
+ }
141
+ const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
142
+ if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
143
+ return;
144
+ }
145
+ if (!container.bubble) {
146
+ container.bubble = {};
147
+ }
148
+ if (container.bubble.durationEnd) {
149
+ if (pObjBubble) {
150
+ if (type === "size") {
151
+ delete particle.bubble.radius;
152
+ }
153
+ if (type === "opacity") {
154
+ delete particle.bubble.opacity;
155
+ }
156
+ }
157
+ }
158
+ else {
159
+ if (distMouse <= bubbleDistance) {
160
+ const obj = pObjBubble ?? pObj;
161
+ if (obj !== bubbleParam) {
162
+ const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
163
+ if (type === "size") {
164
+ particle.bubble.radius = value;
165
+ }
166
+ if (type === "opacity") {
167
+ particle.bubble.opacity = value;
168
+ }
169
+ }
170
+ }
171
+ else {
172
+ if (type === "size") {
173
+ delete particle.bubble.radius;
174
+ }
175
+ if (type === "opacity") {
176
+ delete particle.bubble.opacity;
177
+ }
178
+ }
179
+ }
180
+ };
181
+ this._singleSelectorHover = (delta, selector, div) => {
182
+ const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
183
+ if (!bubble || !selectors.length) {
184
+ return;
185
+ }
186
+ selectors.forEach((item) => {
187
+ const elem = item, pxRatio = container.retina.pixelRatio, pos = {
188
+ x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
189
+ y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
190
+ }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
191
+ ? new Circle(pos.x, pos.y, repulseRadius)
192
+ : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
193
+ for (const particle of query) {
194
+ if (!area.contains(particle.getPosition())) {
195
+ continue;
196
+ }
197
+ particle.bubble.inRange = true;
198
+ const divs = bubble.divs, divBubble = divMode(divs, elem);
199
+ if (!particle.bubble.div || particle.bubble.div !== elem) {
200
+ this.clear(particle, delta, true);
201
+ particle.bubble.div = elem;
202
+ }
203
+ this._hoverBubbleSize(particle, 1, divBubble);
204
+ this._hoverBubbleOpacity(particle, 1, divBubble);
205
+ this._hoverBubbleColor(particle, 1, divBubble);
206
+ }
207
+ });
208
+ };
16
209
  if (!container.bubble) {
17
210
  container.bubble = {};
18
211
  }
@@ -48,247 +241,31 @@ export class Bubbler extends ExternalInteractorBase {
48
241
  async interact(delta) {
49
242
  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;
50
243
  if (hoverEnabled && isInArray("bubble", hoverMode)) {
51
- this.hoverBubble(delta);
244
+ this._hoverBubble();
52
245
  }
53
246
  else if (clickEnabled && isInArray("bubble", clickMode)) {
54
- this.clickBubble(delta);
247
+ this._clickBubble();
55
248
  }
56
249
  else {
57
- divModeExecute("bubble", divs, (selector, div) => this.singleSelectorHover(delta, selector, div));
250
+ divModeExecute("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
58
251
  }
59
252
  }
60
253
  isEnabled(particle) {
61
- var _a;
62
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events, divs = events.onDiv, divBubble = isDivModeEnabled("bubble", divs);
63
- if (!(divBubble || (events.onHover.enable && mouse.position) || (events.onClick.enable && mouse.clickPosition))) {
254
+ const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled("bubble", onDiv);
255
+ if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
64
256
  return false;
65
257
  }
66
- const hoverMode = events.onHover.mode;
67
- const clickMode = events.onClick.mode;
68
- return isInArray("bubble", hoverMode) || isInArray("bubble", clickMode) || divBubble;
258
+ return isInArray("bubble", onHover.mode) || isInArray("bubble", onClick.mode) || divBubble;
69
259
  }
70
260
  loadModeOptions(options, ...sources) {
71
261
  if (!options.bubble) {
72
262
  options.bubble = new Bubble();
73
263
  }
74
264
  for (const source of sources) {
75
- options.bubble.load(source === null || source === void 0 ? void 0 : source.bubble);
265
+ options.bubble.load(source?.bubble);
76
266
  }
77
267
  }
78
268
  reset(particle) {
79
269
  particle.bubble.inRange = false;
80
270
  }
81
- clickBubble(delta) {
82
- var _a, _b;
83
- const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubble = options.interactivity.modes.bubble;
84
- if (!bubble || !mouseClickPos) {
85
- return;
86
- }
87
- if (!container.bubble) {
88
- container.bubble = {};
89
- }
90
- const distance = container.retina.bubbleModeDistance;
91
- if (!distance || distance < 0) {
92
- return;
93
- }
94
- const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p));
95
- for (const particle of query) {
96
- if (!container.bubble.clicking) {
97
- continue;
98
- }
99
- particle.bubble.inRange = !container.bubble.durationEnd;
100
- const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
101
- if (timeSpent > bubble.duration) {
102
- container.bubble.durationEnd = true;
103
- }
104
- if (timeSpent > bubble.duration * 2) {
105
- container.bubble.clicking = false;
106
- container.bubble.durationEnd = false;
107
- }
108
- const sizeData = {
109
- bubbleObj: {
110
- optValue: container.retina.bubbleModeSize,
111
- value: particle.bubble.radius,
112
- },
113
- particlesObj: {
114
- optValue: getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
115
- value: particle.size.value,
116
- },
117
- type: "size",
118
- };
119
- this.process(particle, distMouse, timeSpent, sizeData);
120
- const opacityData = {
121
- bubbleObj: {
122
- optValue: bubble.opacity,
123
- value: particle.bubble.opacity,
124
- },
125
- particlesObj: {
126
- optValue: getRangeMax(particle.options.opacity.value),
127
- value: (_b = (_a = particle.opacity) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 1,
128
- },
129
- type: "opacity",
130
- };
131
- this.process(particle, distMouse, timeSpent, opacityData);
132
- if (!container.bubble.durationEnd) {
133
- if (distMouse <= distance) {
134
- this.hoverBubbleColor(particle, distMouse);
135
- }
136
- else {
137
- delete particle.bubble.color;
138
- }
139
- }
140
- else {
141
- delete particle.bubble.color;
142
- }
143
- }
144
- }
145
- hoverBubble(delta) {
146
- const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
147
- if (!distance || distance < 0 || mousePos === undefined) {
148
- return;
149
- }
150
- const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
151
- for (const particle of query) {
152
- particle.bubble.inRange = true;
153
- const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
154
- if (pointDistance <= distance) {
155
- if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
156
- this.hoverBubbleSize(particle, ratio);
157
- this.hoverBubbleOpacity(particle, ratio);
158
- this.hoverBubbleColor(particle, ratio);
159
- }
160
- }
161
- else {
162
- this.reset(particle);
163
- }
164
- if (container.interactivity.status === mouseLeaveEvent) {
165
- this.reset(particle);
166
- }
167
- }
168
- }
169
- hoverBubbleColor(particle, ratio, divBubble) {
170
- const options = this.container.actualOptions;
171
- const bubbleOptions = divBubble !== null && divBubble !== void 0 ? divBubble : options.interactivity.modes.bubble;
172
- if (!bubbleOptions) {
173
- return;
174
- }
175
- if (!particle.bubble.finalColor) {
176
- const modeColor = bubbleOptions.color;
177
- if (!modeColor) {
178
- return;
179
- }
180
- const bubbleColor = itemFromSingleOrMultiple(modeColor);
181
- particle.bubble.finalColor = rangeColorToHsl(bubbleColor);
182
- }
183
- if (!particle.bubble.finalColor) {
184
- return;
185
- }
186
- if (bubbleOptions.mix) {
187
- particle.bubble.color = undefined;
188
- const pColor = particle.getFillColor();
189
- particle.bubble.color = pColor
190
- ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
191
- : particle.bubble.finalColor;
192
- }
193
- else {
194
- particle.bubble.color = particle.bubble.finalColor;
195
- }
196
- }
197
- hoverBubbleOpacity(particle, ratio, divBubble) {
198
- var _a, _b, _c, _d;
199
- const container = this.container, options = container.actualOptions, modeOpacity = (_a = divBubble === null || divBubble === void 0 ? void 0 : divBubble.opacity) !== null && _a !== void 0 ? _a : (_b = options.interactivity.modes.bubble) === null || _b === void 0 ? void 0 : _b.opacity;
200
- if (!modeOpacity) {
201
- return;
202
- }
203
- const optOpacity = particle.options.opacity.value;
204
- const pOpacity = (_d = (_c = particle.opacity) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : 1;
205
- const opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
206
- if (opacity !== undefined) {
207
- particle.bubble.opacity = opacity;
208
- }
209
- }
210
- hoverBubbleSize(particle, ratio, divBubble) {
211
- const container = this.container, modeSize = (divBubble === null || divBubble === void 0 ? void 0 : divBubble.size) ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
212
- if (modeSize === undefined) {
213
- return;
214
- }
215
- const optSize = getRangeMax(particle.options.size.value) * container.retina.pixelRatio;
216
- const pSize = particle.size.value;
217
- const size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
218
- if (size !== undefined) {
219
- particle.bubble.radius = size;
220
- }
221
- }
222
- process(particle, distMouse, timeSpent, data) {
223
- const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubble = options.interactivity.modes.bubble;
224
- if (!bubble || bubbleParam === undefined) {
225
- return;
226
- }
227
- const bubbleDuration = bubble.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
228
- if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
229
- return;
230
- }
231
- if (!container.bubble) {
232
- container.bubble = {};
233
- }
234
- if (!container.bubble.durationEnd) {
235
- if (distMouse <= bubbleDistance) {
236
- const obj = pObjBubble !== null && pObjBubble !== void 0 ? pObjBubble : pObj;
237
- if (obj !== bubbleParam) {
238
- const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
239
- if (type === "size") {
240
- particle.bubble.radius = value;
241
- }
242
- if (type === "opacity") {
243
- particle.bubble.opacity = value;
244
- }
245
- }
246
- }
247
- else {
248
- if (type === "size") {
249
- delete particle.bubble.radius;
250
- }
251
- if (type === "opacity") {
252
- delete particle.bubble.opacity;
253
- }
254
- }
255
- }
256
- else if (pObjBubble) {
257
- if (type === "size") {
258
- delete particle.bubble.radius;
259
- }
260
- if (type === "opacity") {
261
- delete particle.bubble.opacity;
262
- }
263
- }
264
- }
265
- singleSelectorHover(delta, selector, div) {
266
- const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
267
- if (!bubble || !selectors.length) {
268
- return;
269
- }
270
- selectors.forEach((item) => {
271
- const elem = item, pxRatio = container.retina.pixelRatio, pos = {
272
- x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
273
- y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
274
- }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
275
- ? new Circle(pos.x, pos.y, repulseRadius)
276
- : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
277
- for (const particle of query) {
278
- if (!area.contains(particle.getPosition())) {
279
- continue;
280
- }
281
- particle.bubble.inRange = true;
282
- const divs = bubble.divs;
283
- const divBubble = divMode(divs, elem);
284
- if (!particle.bubble.div || particle.bubble.div !== elem) {
285
- this.clear(particle, delta, true);
286
- particle.bubble.div = elem;
287
- }
288
- this.hoverBubbleSize(particle, 1, divBubble);
289
- this.hoverBubbleOpacity(particle, 1, divBubble);
290
- this.hoverBubbleColor(particle, 1, divBubble);
291
- }
292
- });
293
- }
294
271
  }
@@ -1,6 +1,6 @@
1
+ import { executeOnSingleOrMultiple, } from "@tsparticles/engine";
1
2
  import { BubbleBase } from "./BubbleBase";
2
3
  import { BubbleDiv } from "./BubbleDiv";
3
- import { executeOnSingleOrMultiple } from "@tsparticles/engine";
4
4
  export class Bubble extends BubbleBase {
5
5
  load(data) {
6
6
  super.load(data);
@@ -1,4 +1,4 @@
1
- import { OptionsColor, executeOnSingleOrMultiple } from "@tsparticles/engine";
1
+ import { OptionsColor, executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
2
2
  export class BubbleBase {
3
3
  constructor() {
4
4
  this.distance = 200;
@@ -22,7 +22,7 @@ export class BubbleBase {
22
22
  this.opacity = data.opacity;
23
23
  }
24
24
  if (data.color !== undefined) {
25
- const sourceColor = this.color instanceof Array ? undefined : this.color;
25
+ const sourceColor = isArray(this.color) ? undefined : this.color;
26
26
  this.color = executeOnSingleOrMultiple(data.color, (color) => {
27
27
  return OptionsColor.create(sourceColor, color);
28
28
  });
@@ -1,24 +1,14 @@
1
1
  import { BubbleBase } from "./BubbleBase";
2
- import { executeOnSingleOrMultiple } from "@tsparticles/engine";
3
2
  export class BubbleDiv extends BubbleBase {
4
3
  constructor() {
5
4
  super();
6
5
  this.selectors = [];
7
6
  }
8
- get ids() {
9
- return executeOnSingleOrMultiple(this.selectors, (t) => t.replace("#", ""));
10
- }
11
- set ids(value) {
12
- this.selectors = executeOnSingleOrMultiple(value, (t) => `#${t}`);
13
- }
14
7
  load(data) {
15
8
  super.load(data);
16
9
  if (!data) {
17
10
  return;
18
11
  }
19
- if (data.ids !== undefined) {
20
- this.ids = data.ids;
21
- }
22
12
  if (data.selectors !== undefined) {
23
13
  this.selectors = data.selectors;
24
14
  }
@@ -0,0 +1,11 @@
1
+ import { clamp } from "@tsparticles/engine";
2
+ export function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
3
+ if (modeValue >= optionsValue) {
4
+ const value = particleValue + (modeValue - optionsValue) * ratio;
5
+ return clamp(value, particleValue, modeValue);
6
+ }
7
+ else if (modeValue < optionsValue) {
8
+ const value = particleValue - (optionsValue - modeValue) * ratio;
9
+ return clamp(value, modeValue, particleValue);
10
+ }
11
+ }
package/browser/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Bubbler } from "./Bubbler";
2
- export async function loadExternalBubbleInteraction(engine) {
3
- await engine.addInteractor("externalBubble", (container) => new Bubbler(container));
2
+ export async function loadExternalBubbleInteraction(engine, refresh = true) {
3
+ await engine.addInteractor("externalBubble", (container) => new Bubbler(container), refresh);
4
4
  }
5
5
  export * from "./Options/Classes/BubbleBase";
6
6
  export * from "./Options/Classes/BubbleDiv";