@tsparticles/interaction-external-repulse 4.0.4 → 4.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.
- package/browser/Repulser.js +45 -45
- package/browser/index.js +1 -1
- package/browser/index.lazy.js +1 -1
- package/cjs/Repulser.js +45 -45
- package/cjs/index.js +1 -1
- package/cjs/index.lazy.js +1 -1
- package/esm/Repulser.js +45 -45
- package/esm/index.js +1 -1
- package/esm/index.lazy.js +1 -1
- package/package.json +3 -3
- package/tsparticles.interaction.external.repulse.js +47 -47
- package/tsparticles.interaction.external.repulse.min.js +1 -1
- package/types/Repulser.d.ts +1 -12
package/browser/Repulser.js
CHANGED
|
@@ -4,20 +4,20 @@ import { Repulse } from "./Options/Classes/Repulse.js";
|
|
|
4
4
|
const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, minRestoreSpeed = 0.001, maxRestoreSpeed = 1, restoreEpsilon = 0.5;
|
|
5
5
|
export class Repulser extends ExternalInteractorBase {
|
|
6
6
|
handleClickMode;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
#clickVec;
|
|
8
|
+
#interactedThisFrame;
|
|
9
|
+
#maxDistance;
|
|
10
|
+
#normVec;
|
|
11
|
+
#pluginManager;
|
|
12
|
+
#restoreData;
|
|
13
13
|
constructor(pluginManager, container) {
|
|
14
14
|
super(container);
|
|
15
|
-
this
|
|
16
|
-
this
|
|
17
|
-
this
|
|
18
|
-
this
|
|
19
|
-
this
|
|
20
|
-
this
|
|
15
|
+
this.#pluginManager = pluginManager;
|
|
16
|
+
this.#maxDistance = 0;
|
|
17
|
+
this.#normVec = Vector.origin;
|
|
18
|
+
this.#interactedThisFrame = new Set();
|
|
19
|
+
this.#clickVec = Vector.origin;
|
|
20
|
+
this.#restoreData = new Map();
|
|
21
21
|
container.repulse ??= { particles: [] };
|
|
22
22
|
this.handleClickMode = (mode, interactivityData) => {
|
|
23
23
|
const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
|
|
@@ -45,7 +45,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
get maxDistance() {
|
|
48
|
-
return this
|
|
48
|
+
return this.#maxDistance;
|
|
49
49
|
}
|
|
50
50
|
clear() {
|
|
51
51
|
}
|
|
@@ -54,28 +54,28 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
54
54
|
if (!repulse) {
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
this
|
|
57
|
+
this.#maxDistance = repulse.distance;
|
|
58
58
|
container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
|
|
59
59
|
}
|
|
60
60
|
interact(interactivityData) {
|
|
61
|
-
this.
|
|
61
|
+
this.#interactedThisFrame.clear();
|
|
62
62
|
const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
|
|
63
63
|
if (!events) {
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
|
|
67
67
|
if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
|
|
68
|
-
this
|
|
68
|
+
this.#hoverRepulse(interactivityData);
|
|
69
69
|
}
|
|
70
70
|
else if (clickEnabled && isInArray(repulseMode, clickMode)) {
|
|
71
|
-
this
|
|
71
|
+
this.#clickRepulse(interactivityData);
|
|
72
72
|
}
|
|
73
73
|
else {
|
|
74
74
|
divModeExecute(repulseMode, divs, (selector, div) => {
|
|
75
|
-
this
|
|
75
|
+
this.#singleSelectorRepulse(interactivityData, selector, div);
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
this
|
|
78
|
+
this.#restoreParticles();
|
|
79
79
|
}
|
|
80
80
|
isEnabled(interactivityData, particle) {
|
|
81
81
|
const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
|
|
@@ -97,7 +97,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
97
97
|
}
|
|
98
98
|
reset() {
|
|
99
99
|
}
|
|
100
|
-
|
|
100
|
+
#clickRepulse = interactivityData => {
|
|
101
101
|
const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
102
102
|
if (!repulseOptions) {
|
|
103
103
|
return;
|
|
@@ -123,12 +123,12 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
123
123
|
for (const particle of query) {
|
|
124
124
|
const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
|
|
125
125
|
if (d <= repulseRadius) {
|
|
126
|
-
this
|
|
126
|
+
this.#trackInteractedParticle(particle);
|
|
127
127
|
repulse.particles.push(particle);
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
130
|
-
this.
|
|
131
|
-
particle.velocity.setTo(this
|
|
128
|
+
this.#clickVec.x = dx;
|
|
129
|
+
this.#clickVec.y = dy;
|
|
130
|
+
this.#clickVec.length = force;
|
|
131
|
+
particle.velocity.setTo(this.#clickVec);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -139,39 +139,39 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
139
139
|
repulse.particles = [];
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
|
-
|
|
142
|
+
#hoverRepulse = interactivityData => {
|
|
143
143
|
const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
|
|
144
144
|
if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
this
|
|
147
|
+
this.#processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
|
|
148
148
|
};
|
|
149
|
-
|
|
149
|
+
#processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
|
|
150
150
|
const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
151
151
|
if (!repulseOptions) {
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
|
-
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.
|
|
154
|
+
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.#pluginManager.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
|
|
155
155
|
for (const particle of query) {
|
|
156
156
|
const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
|
|
157
|
-
this.
|
|
158
|
-
this.
|
|
159
|
-
this
|
|
160
|
-
particle.position.addTo(this
|
|
157
|
+
this.#normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
|
|
158
|
+
this.#normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
|
|
159
|
+
this.#trackInteractedParticle(particle);
|
|
160
|
+
particle.position.addTo(this.#normVec);
|
|
161
161
|
}
|
|
162
162
|
};
|
|
163
|
-
|
|
163
|
+
#restoreParticles() {
|
|
164
164
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
165
|
-
if (!restore?.enable || !this.
|
|
165
|
+
if (!restore?.enable || !this.#restoreData.size) {
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
const now = Date.now(), restoreDelay = restore.delay * millisecondsToSeconds, restoreSpeed = Math.max(minRestoreSpeed, Math.min(maxRestoreSpeed, restore.speed));
|
|
169
|
-
for (const [particle, restoreData] of this
|
|
170
|
-
if (this.
|
|
169
|
+
for (const [particle, restoreData] of this.#restoreData) {
|
|
170
|
+
if (this.#interactedThisFrame.has(particle)) {
|
|
171
171
|
continue;
|
|
172
172
|
}
|
|
173
173
|
if (particle.destroyed) {
|
|
174
|
-
this.
|
|
174
|
+
this.#restoreData.delete(particle);
|
|
175
175
|
continue;
|
|
176
176
|
}
|
|
177
177
|
const target = restoreData.target;
|
|
@@ -191,12 +191,12 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
191
191
|
particle.position.x = target.x;
|
|
192
192
|
particle.position.y = target.y;
|
|
193
193
|
particle.position.z = target.z;
|
|
194
|
-
this.
|
|
194
|
+
this.#restoreData.delete(particle);
|
|
195
195
|
continue;
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
-
|
|
199
|
+
#singleSelectorRepulse = (interactivityData, selector, div) => {
|
|
200
200
|
const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
|
|
201
201
|
if (!repulse) {
|
|
202
202
|
return;
|
|
@@ -212,23 +212,23 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
212
212
|
}, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
|
|
213
213
|
? new Circle(pos.x, pos.y, repulseRadius)
|
|
214
214
|
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
|
|
215
|
-
this
|
|
215
|
+
this.#processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
|
|
216
216
|
});
|
|
217
217
|
};
|
|
218
|
-
|
|
219
|
-
this.
|
|
218
|
+
#trackInteractedParticle(particle) {
|
|
219
|
+
this.#interactedThisFrame.add(particle);
|
|
220
220
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
221
221
|
if (!restore?.enable) {
|
|
222
222
|
return;
|
|
223
223
|
}
|
|
224
224
|
const now = Date.now();
|
|
225
|
-
let restoreData = this.
|
|
225
|
+
let restoreData = this.#restoreData.get(particle);
|
|
226
226
|
if (!restoreData) {
|
|
227
227
|
restoreData = {
|
|
228
228
|
target: particle.position.copy(),
|
|
229
229
|
lastInteractionTime: now,
|
|
230
230
|
};
|
|
231
|
-
this.
|
|
231
|
+
this.#restoreData.set(particle, restoreData);
|
|
232
232
|
}
|
|
233
233
|
restoreData.lastInteractionTime = now;
|
|
234
234
|
if (restore.follow && particle.options.move.enable) {
|
package/browser/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ensureInteractivityPluginLoaded } from "@tsparticles/plugin-interactivity";
|
|
2
2
|
import { Repulser } from "./Repulser.js";
|
|
3
3
|
export async function loadExternalRepulseInteraction(engine) {
|
|
4
|
-
engine.checkVersion("4.0
|
|
4
|
+
engine.checkVersion("4.1.0");
|
|
5
5
|
await engine.pluginManager.register((e) => {
|
|
6
6
|
ensureInteractivityPluginLoaded(e);
|
|
7
7
|
const pluginManager = e.pluginManager;
|
package/browser/index.lazy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export async function loadExternalRepulseInteraction(engine) {
|
|
2
|
-
engine.checkVersion("4.0
|
|
2
|
+
engine.checkVersion("4.1.0");
|
|
3
3
|
await engine.pluginManager.register(async (e) => {
|
|
4
4
|
const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity/lazy");
|
|
5
5
|
ensureInteractivityPluginLoaded(e);
|
package/cjs/Repulser.js
CHANGED
|
@@ -4,20 +4,20 @@ import { Repulse } from "./Options/Classes/Repulse.js";
|
|
|
4
4
|
const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, minRestoreSpeed = 0.001, maxRestoreSpeed = 1, restoreEpsilon = 0.5;
|
|
5
5
|
export class Repulser extends ExternalInteractorBase {
|
|
6
6
|
handleClickMode;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
#clickVec;
|
|
8
|
+
#interactedThisFrame;
|
|
9
|
+
#maxDistance;
|
|
10
|
+
#normVec;
|
|
11
|
+
#pluginManager;
|
|
12
|
+
#restoreData;
|
|
13
13
|
constructor(pluginManager, container) {
|
|
14
14
|
super(container);
|
|
15
|
-
this
|
|
16
|
-
this
|
|
17
|
-
this
|
|
18
|
-
this
|
|
19
|
-
this
|
|
20
|
-
this
|
|
15
|
+
this.#pluginManager = pluginManager;
|
|
16
|
+
this.#maxDistance = 0;
|
|
17
|
+
this.#normVec = Vector.origin;
|
|
18
|
+
this.#interactedThisFrame = new Set();
|
|
19
|
+
this.#clickVec = Vector.origin;
|
|
20
|
+
this.#restoreData = new Map();
|
|
21
21
|
container.repulse ??= { particles: [] };
|
|
22
22
|
this.handleClickMode = (mode, interactivityData) => {
|
|
23
23
|
const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
|
|
@@ -45,7 +45,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
get maxDistance() {
|
|
48
|
-
return this
|
|
48
|
+
return this.#maxDistance;
|
|
49
49
|
}
|
|
50
50
|
clear() {
|
|
51
51
|
}
|
|
@@ -54,28 +54,28 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
54
54
|
if (!repulse) {
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
this
|
|
57
|
+
this.#maxDistance = repulse.distance;
|
|
58
58
|
container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
|
|
59
59
|
}
|
|
60
60
|
interact(interactivityData) {
|
|
61
|
-
this.
|
|
61
|
+
this.#interactedThisFrame.clear();
|
|
62
62
|
const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
|
|
63
63
|
if (!events) {
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
|
|
67
67
|
if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
|
|
68
|
-
this
|
|
68
|
+
this.#hoverRepulse(interactivityData);
|
|
69
69
|
}
|
|
70
70
|
else if (clickEnabled && isInArray(repulseMode, clickMode)) {
|
|
71
|
-
this
|
|
71
|
+
this.#clickRepulse(interactivityData);
|
|
72
72
|
}
|
|
73
73
|
else {
|
|
74
74
|
divModeExecute(repulseMode, divs, (selector, div) => {
|
|
75
|
-
this
|
|
75
|
+
this.#singleSelectorRepulse(interactivityData, selector, div);
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
this
|
|
78
|
+
this.#restoreParticles();
|
|
79
79
|
}
|
|
80
80
|
isEnabled(interactivityData, particle) {
|
|
81
81
|
const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
|
|
@@ -97,7 +97,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
97
97
|
}
|
|
98
98
|
reset() {
|
|
99
99
|
}
|
|
100
|
-
|
|
100
|
+
#clickRepulse = interactivityData => {
|
|
101
101
|
const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
102
102
|
if (!repulseOptions) {
|
|
103
103
|
return;
|
|
@@ -123,12 +123,12 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
123
123
|
for (const particle of query) {
|
|
124
124
|
const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
|
|
125
125
|
if (d <= repulseRadius) {
|
|
126
|
-
this
|
|
126
|
+
this.#trackInteractedParticle(particle);
|
|
127
127
|
repulse.particles.push(particle);
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
130
|
-
this.
|
|
131
|
-
particle.velocity.setTo(this
|
|
128
|
+
this.#clickVec.x = dx;
|
|
129
|
+
this.#clickVec.y = dy;
|
|
130
|
+
this.#clickVec.length = force;
|
|
131
|
+
particle.velocity.setTo(this.#clickVec);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -139,39 +139,39 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
139
139
|
repulse.particles = [];
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
|
-
|
|
142
|
+
#hoverRepulse = interactivityData => {
|
|
143
143
|
const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
|
|
144
144
|
if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
this
|
|
147
|
+
this.#processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
|
|
148
148
|
};
|
|
149
|
-
|
|
149
|
+
#processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
|
|
150
150
|
const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
151
151
|
if (!repulseOptions) {
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
|
-
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.
|
|
154
|
+
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.#pluginManager.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
|
|
155
155
|
for (const particle of query) {
|
|
156
156
|
const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
|
|
157
|
-
this.
|
|
158
|
-
this.
|
|
159
|
-
this
|
|
160
|
-
particle.position.addTo(this
|
|
157
|
+
this.#normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
|
|
158
|
+
this.#normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
|
|
159
|
+
this.#trackInteractedParticle(particle);
|
|
160
|
+
particle.position.addTo(this.#normVec);
|
|
161
161
|
}
|
|
162
162
|
};
|
|
163
|
-
|
|
163
|
+
#restoreParticles() {
|
|
164
164
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
165
|
-
if (!restore?.enable || !this.
|
|
165
|
+
if (!restore?.enable || !this.#restoreData.size) {
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
const now = Date.now(), restoreDelay = restore.delay * millisecondsToSeconds, restoreSpeed = Math.max(minRestoreSpeed, Math.min(maxRestoreSpeed, restore.speed));
|
|
169
|
-
for (const [particle, restoreData] of this
|
|
170
|
-
if (this.
|
|
169
|
+
for (const [particle, restoreData] of this.#restoreData) {
|
|
170
|
+
if (this.#interactedThisFrame.has(particle)) {
|
|
171
171
|
continue;
|
|
172
172
|
}
|
|
173
173
|
if (particle.destroyed) {
|
|
174
|
-
this.
|
|
174
|
+
this.#restoreData.delete(particle);
|
|
175
175
|
continue;
|
|
176
176
|
}
|
|
177
177
|
const target = restoreData.target;
|
|
@@ -191,12 +191,12 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
191
191
|
particle.position.x = target.x;
|
|
192
192
|
particle.position.y = target.y;
|
|
193
193
|
particle.position.z = target.z;
|
|
194
|
-
this.
|
|
194
|
+
this.#restoreData.delete(particle);
|
|
195
195
|
continue;
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
-
|
|
199
|
+
#singleSelectorRepulse = (interactivityData, selector, div) => {
|
|
200
200
|
const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
|
|
201
201
|
if (!repulse) {
|
|
202
202
|
return;
|
|
@@ -212,23 +212,23 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
212
212
|
}, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
|
|
213
213
|
? new Circle(pos.x, pos.y, repulseRadius)
|
|
214
214
|
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
|
|
215
|
-
this
|
|
215
|
+
this.#processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
|
|
216
216
|
});
|
|
217
217
|
};
|
|
218
|
-
|
|
219
|
-
this.
|
|
218
|
+
#trackInteractedParticle(particle) {
|
|
219
|
+
this.#interactedThisFrame.add(particle);
|
|
220
220
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
221
221
|
if (!restore?.enable) {
|
|
222
222
|
return;
|
|
223
223
|
}
|
|
224
224
|
const now = Date.now();
|
|
225
|
-
let restoreData = this.
|
|
225
|
+
let restoreData = this.#restoreData.get(particle);
|
|
226
226
|
if (!restoreData) {
|
|
227
227
|
restoreData = {
|
|
228
228
|
target: particle.position.copy(),
|
|
229
229
|
lastInteractionTime: now,
|
|
230
230
|
};
|
|
231
|
-
this.
|
|
231
|
+
this.#restoreData.set(particle, restoreData);
|
|
232
232
|
}
|
|
233
233
|
restoreData.lastInteractionTime = now;
|
|
234
234
|
if (restore.follow && particle.options.move.enable) {
|
package/cjs/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ensureInteractivityPluginLoaded } from "@tsparticles/plugin-interactivity";
|
|
2
2
|
import { Repulser } from "./Repulser.js";
|
|
3
3
|
export async function loadExternalRepulseInteraction(engine) {
|
|
4
|
-
engine.checkVersion("4.0
|
|
4
|
+
engine.checkVersion("4.1.0");
|
|
5
5
|
await engine.pluginManager.register((e) => {
|
|
6
6
|
ensureInteractivityPluginLoaded(e);
|
|
7
7
|
const pluginManager = e.pluginManager;
|
package/cjs/index.lazy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export async function loadExternalRepulseInteraction(engine) {
|
|
2
|
-
engine.checkVersion("4.0
|
|
2
|
+
engine.checkVersion("4.1.0");
|
|
3
3
|
await engine.pluginManager.register(async (e) => {
|
|
4
4
|
const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity/lazy");
|
|
5
5
|
ensureInteractivityPluginLoaded(e);
|
package/esm/Repulser.js
CHANGED
|
@@ -4,20 +4,20 @@ import { Repulse } from "./Options/Classes/Repulse.js";
|
|
|
4
4
|
const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, minRestoreSpeed = 0.001, maxRestoreSpeed = 1, restoreEpsilon = 0.5;
|
|
5
5
|
export class Repulser extends ExternalInteractorBase {
|
|
6
6
|
handleClickMode;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
#clickVec;
|
|
8
|
+
#interactedThisFrame;
|
|
9
|
+
#maxDistance;
|
|
10
|
+
#normVec;
|
|
11
|
+
#pluginManager;
|
|
12
|
+
#restoreData;
|
|
13
13
|
constructor(pluginManager, container) {
|
|
14
14
|
super(container);
|
|
15
|
-
this
|
|
16
|
-
this
|
|
17
|
-
this
|
|
18
|
-
this
|
|
19
|
-
this
|
|
20
|
-
this
|
|
15
|
+
this.#pluginManager = pluginManager;
|
|
16
|
+
this.#maxDistance = 0;
|
|
17
|
+
this.#normVec = Vector.origin;
|
|
18
|
+
this.#interactedThisFrame = new Set();
|
|
19
|
+
this.#clickVec = Vector.origin;
|
|
20
|
+
this.#restoreData = new Map();
|
|
21
21
|
container.repulse ??= { particles: [] };
|
|
22
22
|
this.handleClickMode = (mode, interactivityData) => {
|
|
23
23
|
const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
|
|
@@ -45,7 +45,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
get maxDistance() {
|
|
48
|
-
return this
|
|
48
|
+
return this.#maxDistance;
|
|
49
49
|
}
|
|
50
50
|
clear() {
|
|
51
51
|
}
|
|
@@ -54,28 +54,28 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
54
54
|
if (!repulse) {
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
this
|
|
57
|
+
this.#maxDistance = repulse.distance;
|
|
58
58
|
container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
|
|
59
59
|
}
|
|
60
60
|
interact(interactivityData) {
|
|
61
|
-
this.
|
|
61
|
+
this.#interactedThisFrame.clear();
|
|
62
62
|
const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
|
|
63
63
|
if (!events) {
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
|
|
67
67
|
if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
|
|
68
|
-
this
|
|
68
|
+
this.#hoverRepulse(interactivityData);
|
|
69
69
|
}
|
|
70
70
|
else if (clickEnabled && isInArray(repulseMode, clickMode)) {
|
|
71
|
-
this
|
|
71
|
+
this.#clickRepulse(interactivityData);
|
|
72
72
|
}
|
|
73
73
|
else {
|
|
74
74
|
divModeExecute(repulseMode, divs, (selector, div) => {
|
|
75
|
-
this
|
|
75
|
+
this.#singleSelectorRepulse(interactivityData, selector, div);
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
this
|
|
78
|
+
this.#restoreParticles();
|
|
79
79
|
}
|
|
80
80
|
isEnabled(interactivityData, particle) {
|
|
81
81
|
const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
|
|
@@ -97,7 +97,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
97
97
|
}
|
|
98
98
|
reset() {
|
|
99
99
|
}
|
|
100
|
-
|
|
100
|
+
#clickRepulse = interactivityData => {
|
|
101
101
|
const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
102
102
|
if (!repulseOptions) {
|
|
103
103
|
return;
|
|
@@ -123,12 +123,12 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
123
123
|
for (const particle of query) {
|
|
124
124
|
const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
|
|
125
125
|
if (d <= repulseRadius) {
|
|
126
|
-
this
|
|
126
|
+
this.#trackInteractedParticle(particle);
|
|
127
127
|
repulse.particles.push(particle);
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
130
|
-
this.
|
|
131
|
-
particle.velocity.setTo(this
|
|
128
|
+
this.#clickVec.x = dx;
|
|
129
|
+
this.#clickVec.y = dy;
|
|
130
|
+
this.#clickVec.length = force;
|
|
131
|
+
particle.velocity.setTo(this.#clickVec);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -139,39 +139,39 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
139
139
|
repulse.particles = [];
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
|
-
|
|
142
|
+
#hoverRepulse = interactivityData => {
|
|
143
143
|
const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
|
|
144
144
|
if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
this
|
|
147
|
+
this.#processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
|
|
148
148
|
};
|
|
149
|
-
|
|
149
|
+
#processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
|
|
150
150
|
const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
151
151
|
if (!repulseOptions) {
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
|
-
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.
|
|
154
|
+
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.#pluginManager.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
|
|
155
155
|
for (const particle of query) {
|
|
156
156
|
const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
|
|
157
|
-
this.
|
|
158
|
-
this.
|
|
159
|
-
this
|
|
160
|
-
particle.position.addTo(this
|
|
157
|
+
this.#normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
|
|
158
|
+
this.#normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
|
|
159
|
+
this.#trackInteractedParticle(particle);
|
|
160
|
+
particle.position.addTo(this.#normVec);
|
|
161
161
|
}
|
|
162
162
|
};
|
|
163
|
-
|
|
163
|
+
#restoreParticles() {
|
|
164
164
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
165
|
-
if (!restore?.enable || !this.
|
|
165
|
+
if (!restore?.enable || !this.#restoreData.size) {
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
const now = Date.now(), restoreDelay = restore.delay * millisecondsToSeconds, restoreSpeed = Math.max(minRestoreSpeed, Math.min(maxRestoreSpeed, restore.speed));
|
|
169
|
-
for (const [particle, restoreData] of this
|
|
170
|
-
if (this.
|
|
169
|
+
for (const [particle, restoreData] of this.#restoreData) {
|
|
170
|
+
if (this.#interactedThisFrame.has(particle)) {
|
|
171
171
|
continue;
|
|
172
172
|
}
|
|
173
173
|
if (particle.destroyed) {
|
|
174
|
-
this.
|
|
174
|
+
this.#restoreData.delete(particle);
|
|
175
175
|
continue;
|
|
176
176
|
}
|
|
177
177
|
const target = restoreData.target;
|
|
@@ -191,12 +191,12 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
191
191
|
particle.position.x = target.x;
|
|
192
192
|
particle.position.y = target.y;
|
|
193
193
|
particle.position.z = target.z;
|
|
194
|
-
this.
|
|
194
|
+
this.#restoreData.delete(particle);
|
|
195
195
|
continue;
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
-
|
|
199
|
+
#singleSelectorRepulse = (interactivityData, selector, div) => {
|
|
200
200
|
const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
|
|
201
201
|
if (!repulse) {
|
|
202
202
|
return;
|
|
@@ -212,23 +212,23 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
212
212
|
}, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
|
|
213
213
|
? new Circle(pos.x, pos.y, repulseRadius)
|
|
214
214
|
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
|
|
215
|
-
this
|
|
215
|
+
this.#processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
|
|
216
216
|
});
|
|
217
217
|
};
|
|
218
|
-
|
|
219
|
-
this.
|
|
218
|
+
#trackInteractedParticle(particle) {
|
|
219
|
+
this.#interactedThisFrame.add(particle);
|
|
220
220
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
221
221
|
if (!restore?.enable) {
|
|
222
222
|
return;
|
|
223
223
|
}
|
|
224
224
|
const now = Date.now();
|
|
225
|
-
let restoreData = this.
|
|
225
|
+
let restoreData = this.#restoreData.get(particle);
|
|
226
226
|
if (!restoreData) {
|
|
227
227
|
restoreData = {
|
|
228
228
|
target: particle.position.copy(),
|
|
229
229
|
lastInteractionTime: now,
|
|
230
230
|
};
|
|
231
|
-
this.
|
|
231
|
+
this.#restoreData.set(particle, restoreData);
|
|
232
232
|
}
|
|
233
233
|
restoreData.lastInteractionTime = now;
|
|
234
234
|
if (restore.follow && particle.options.move.enable) {
|
package/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ensureInteractivityPluginLoaded } from "@tsparticles/plugin-interactivity";
|
|
2
2
|
import { Repulser } from "./Repulser.js";
|
|
3
3
|
export async function loadExternalRepulseInteraction(engine) {
|
|
4
|
-
engine.checkVersion("4.0
|
|
4
|
+
engine.checkVersion("4.1.0");
|
|
5
5
|
await engine.pluginManager.register((e) => {
|
|
6
6
|
ensureInteractivityPluginLoaded(e);
|
|
7
7
|
const pluginManager = e.pluginManager;
|
package/esm/index.lazy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export async function loadExternalRepulseInteraction(engine) {
|
|
2
|
-
engine.checkVersion("4.0
|
|
2
|
+
engine.checkVersion("4.1.0");
|
|
3
3
|
await engine.pluginManager.register(async (e) => {
|
|
4
4
|
const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity/lazy");
|
|
5
5
|
ensureInteractivityPluginLoaded(e);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsparticles/interaction-external-repulse",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "tsParticles repulse external interaction",
|
|
5
5
|
"homepage": "https://particles.js.org",
|
|
6
6
|
"repository": {
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
},
|
|
98
98
|
"type": "module",
|
|
99
99
|
"peerDependencies": {
|
|
100
|
-
"@tsparticles/engine": "4.0
|
|
101
|
-
"@tsparticles/plugin-interactivity": "4.0
|
|
100
|
+
"@tsparticles/engine": "4.1.0",
|
|
101
|
+
"@tsparticles/plugin-interactivity": "4.1.0"
|
|
102
102
|
}
|
|
103
103
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
|
|
2
|
-
/* External Interaction v4.0
|
|
2
|
+
/* External Interaction v4.1.0 */
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tsparticles/plugin-interactivity'), require('@tsparticles/engine')) :
|
|
5
5
|
typeof define === 'function' && define.amd ? define(['exports', '@tsparticles/plugin-interactivity', '@tsparticles/engine'], factory) :
|
|
@@ -94,20 +94,20 @@
|
|
|
94
94
|
const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, minRestoreSpeed = 0.001, maxRestoreSpeed = 1, restoreEpsilon = 0.5;
|
|
95
95
|
class Repulser extends pluginInteractivity.ExternalInteractorBase {
|
|
96
96
|
handleClickMode;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
#clickVec;
|
|
98
|
+
#interactedThisFrame;
|
|
99
|
+
#maxDistance;
|
|
100
|
+
#normVec;
|
|
101
|
+
#pluginManager;
|
|
102
|
+
#restoreData;
|
|
103
103
|
constructor(pluginManager, container) {
|
|
104
104
|
super(container);
|
|
105
|
-
this
|
|
106
|
-
this
|
|
107
|
-
this
|
|
108
|
-
this
|
|
109
|
-
this
|
|
110
|
-
this
|
|
105
|
+
this.#pluginManager = pluginManager;
|
|
106
|
+
this.#maxDistance = 0;
|
|
107
|
+
this.#normVec = engine.Vector.origin;
|
|
108
|
+
this.#interactedThisFrame = new Set();
|
|
109
|
+
this.#clickVec = engine.Vector.origin;
|
|
110
|
+
this.#restoreData = new Map();
|
|
111
111
|
container.repulse ??= { particles: [] };
|
|
112
112
|
this.handleClickMode = (mode, interactivityData) => {
|
|
113
113
|
const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
get maxDistance() {
|
|
138
|
-
return this
|
|
138
|
+
return this.#maxDistance;
|
|
139
139
|
}
|
|
140
140
|
clear() {
|
|
141
141
|
}
|
|
@@ -144,28 +144,28 @@
|
|
|
144
144
|
if (!repulse) {
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
this
|
|
147
|
+
this.#maxDistance = repulse.distance;
|
|
148
148
|
container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
|
|
149
149
|
}
|
|
150
150
|
interact(interactivityData) {
|
|
151
|
-
this.
|
|
151
|
+
this.#interactedThisFrame.clear();
|
|
152
152
|
const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === pluginInteractivity.mouseMoveEvent, events = options.interactivity?.events;
|
|
153
153
|
if (!events) {
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
156
|
const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
|
|
157
157
|
if (mouseMoveStatus && hoverEnabled && engine.isInArray(repulseMode, hoverMode)) {
|
|
158
|
-
this
|
|
158
|
+
this.#hoverRepulse(interactivityData);
|
|
159
159
|
}
|
|
160
160
|
else if (clickEnabled && engine.isInArray(repulseMode, clickMode)) {
|
|
161
|
-
this
|
|
161
|
+
this.#clickRepulse(interactivityData);
|
|
162
162
|
}
|
|
163
163
|
else {
|
|
164
164
|
pluginInteractivity.divModeExecute(repulseMode, divs, (selector, div) => {
|
|
165
|
-
this
|
|
165
|
+
this.#singleSelectorRepulse(interactivityData, selector, div);
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
|
-
this
|
|
168
|
+
this.#restoreParticles();
|
|
169
169
|
}
|
|
170
170
|
isEnabled(interactivityData, particle) {
|
|
171
171
|
const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
}
|
|
188
188
|
reset() {
|
|
189
189
|
}
|
|
190
|
-
|
|
190
|
+
#clickRepulse = interactivityData => {
|
|
191
191
|
const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
192
192
|
if (!repulseOptions) {
|
|
193
193
|
return;
|
|
@@ -213,12 +213,12 @@
|
|
|
213
213
|
for (const particle of query) {
|
|
214
214
|
const { dx, dy, distance } = engine.getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
|
|
215
215
|
if (d <= repulseRadius) {
|
|
216
|
-
this
|
|
216
|
+
this.#trackInteractedParticle(particle);
|
|
217
217
|
repulse.particles.push(particle);
|
|
218
|
-
this.
|
|
219
|
-
this.
|
|
220
|
-
this.
|
|
221
|
-
particle.velocity.setTo(this
|
|
218
|
+
this.#clickVec.x = dx;
|
|
219
|
+
this.#clickVec.y = dy;
|
|
220
|
+
this.#clickVec.length = force;
|
|
221
|
+
particle.velocity.setTo(this.#clickVec);
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
}
|
|
@@ -229,39 +229,39 @@
|
|
|
229
229
|
repulse.particles = [];
|
|
230
230
|
}
|
|
231
231
|
};
|
|
232
|
-
|
|
232
|
+
#hoverRepulse = interactivityData => {
|
|
233
233
|
const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
|
|
234
234
|
if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
|
|
235
235
|
return;
|
|
236
236
|
}
|
|
237
|
-
this
|
|
237
|
+
this.#processRepulse(interactivityData, mousePos, repulseRadius, new engine.Circle(mousePos.x, mousePos.y, repulseRadius));
|
|
238
238
|
};
|
|
239
|
-
|
|
239
|
+
#processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
|
|
240
240
|
const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
|
|
241
241
|
if (!repulseOptions) {
|
|
242
242
|
return;
|
|
243
243
|
}
|
|
244
|
-
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.
|
|
244
|
+
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this.#pluginManager.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
|
|
245
245
|
for (const particle of query) {
|
|
246
246
|
const { dx, dy, distance } = engine.getDistances(particle.position, position), repulseFactor = engine.clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
|
|
247
|
-
this.
|
|
248
|
-
this.
|
|
249
|
-
this
|
|
250
|
-
particle.position.addTo(this
|
|
247
|
+
this.#normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
|
|
248
|
+
this.#normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
|
|
249
|
+
this.#trackInteractedParticle(particle);
|
|
250
|
+
particle.position.addTo(this.#normVec);
|
|
251
251
|
}
|
|
252
252
|
};
|
|
253
|
-
|
|
253
|
+
#restoreParticles() {
|
|
254
254
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
255
|
-
if (!restore?.enable || !this.
|
|
255
|
+
if (!restore?.enable || !this.#restoreData.size) {
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
258
258
|
const now = Date.now(), restoreDelay = restore.delay * engine.millisecondsToSeconds, restoreSpeed = Math.max(minRestoreSpeed, Math.min(maxRestoreSpeed, restore.speed));
|
|
259
|
-
for (const [particle, restoreData] of this
|
|
260
|
-
if (this.
|
|
259
|
+
for (const [particle, restoreData] of this.#restoreData) {
|
|
260
|
+
if (this.#interactedThisFrame.has(particle)) {
|
|
261
261
|
continue;
|
|
262
262
|
}
|
|
263
263
|
if (particle.destroyed) {
|
|
264
|
-
this.
|
|
264
|
+
this.#restoreData.delete(particle);
|
|
265
265
|
continue;
|
|
266
266
|
}
|
|
267
267
|
const target = restoreData.target;
|
|
@@ -281,12 +281,12 @@
|
|
|
281
281
|
particle.position.x = target.x;
|
|
282
282
|
particle.position.y = target.y;
|
|
283
283
|
particle.position.z = target.z;
|
|
284
|
-
this.
|
|
284
|
+
this.#restoreData.delete(particle);
|
|
285
285
|
continue;
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
|
-
|
|
289
|
+
#singleSelectorRepulse = (interactivityData, selector, div) => {
|
|
290
290
|
const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
|
|
291
291
|
if (!repulse) {
|
|
292
292
|
return;
|
|
@@ -302,23 +302,23 @@
|
|
|
302
302
|
}, repulseRadius = elem.offsetWidth * engine.half * pxRatio, area = div.type === pluginInteractivity.DivType.circle
|
|
303
303
|
? new engine.Circle(pos.x, pos.y, repulseRadius)
|
|
304
304
|
: new engine.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = pluginInteractivity.divMode(divs, elem);
|
|
305
|
-
this
|
|
305
|
+
this.#processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
|
|
306
306
|
});
|
|
307
307
|
};
|
|
308
|
-
|
|
309
|
-
this.
|
|
308
|
+
#trackInteractedParticle(particle) {
|
|
309
|
+
this.#interactedThisFrame.add(particle);
|
|
310
310
|
const restore = this.container.actualOptions.interactivity?.modes.repulse?.restore;
|
|
311
311
|
if (!restore?.enable) {
|
|
312
312
|
return;
|
|
313
313
|
}
|
|
314
314
|
const now = Date.now();
|
|
315
|
-
let restoreData = this.
|
|
315
|
+
let restoreData = this.#restoreData.get(particle);
|
|
316
316
|
if (!restoreData) {
|
|
317
317
|
restoreData = {
|
|
318
318
|
target: particle.position.copy(),
|
|
319
319
|
lastInteractionTime: now,
|
|
320
320
|
};
|
|
321
|
-
this.
|
|
321
|
+
this.#restoreData.set(particle, restoreData);
|
|
322
322
|
}
|
|
323
323
|
restoreData.lastInteractionTime = now;
|
|
324
324
|
if (restore.follow && particle.options.move.enable) {
|
|
@@ -330,7 +330,7 @@
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
async function loadExternalRepulseInteraction(engine) {
|
|
333
|
-
engine.checkVersion("4.0
|
|
333
|
+
engine.checkVersion("4.1.0");
|
|
334
334
|
await engine.pluginManager.register((e) => {
|
|
335
335
|
pluginInteractivity.ensureInteractivityPluginLoaded(e);
|
|
336
336
|
const pluginManager = e.pluginManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e){e.__tsParticlesInternals=e.__tsParticlesInternals||{},e.__tsParticlesInternals.bundles=e.__tsParticlesInternals.bundles||{},e.__tsParticlesInternals.effects=e.__tsParticlesInternals.effects||{},e.__tsParticlesInternals.engine=e.__tsParticlesInternals.engine||{},e.__tsParticlesInternals.interactions=e.__tsParticlesInternals.interactions||{},e.__tsParticlesInternals.palettes=e.__tsParticlesInternals.palettes||{},e.__tsParticlesInternals.paths=e.__tsParticlesInternals.paths||{},e.__tsParticlesInternals.plugins=e.__tsParticlesInternals.plugins||{},e.__tsParticlesInternals.plugins=e.__tsParticlesInternals.plugins||{},e.__tsParticlesInternals.plugins.emittersShapes=e.__tsParticlesInternals.plugins.emittersShapes||{},e.__tsParticlesInternals.presets=e.__tsParticlesInternals.presets||{},e.__tsParticlesInternals.shapes=e.__tsParticlesInternals.shapes||{},e.__tsParticlesInternals.updaters=e.__tsParticlesInternals.updaters||{},e.__tsParticlesInternals.utils=e.__tsParticlesInternals.utils||{},e.__tsParticlesInternals.canvas=e.__tsParticlesInternals.canvas||{},e.__tsParticlesInternals.canvas=e.__tsParticlesInternals.canvas||{},e.__tsParticlesInternals.canvas.utils=e.__tsParticlesInternals.canvas.utils||{},e.__tsParticlesInternals.path=e.__tsParticlesInternals.path||{},e.__tsParticlesInternals.path=e.__tsParticlesInternals.path||{},e.__tsParticlesInternals.path.utils=e.__tsParticlesInternals.path.utils||{};var t="undefined"!=typeof Proxy?function(e){return new Proxy(e,{get:function(e,t){return t in e||(e[t]={}),e[t]}})}:function(e){return e};e.__tsParticlesInternals.bundles=t(e.__tsParticlesInternals.bundles),e.__tsParticlesInternals.effects=t(e.__tsParticlesInternals.effects),e.__tsParticlesInternals.interactions=t(e.__tsParticlesInternals.interactions),e.__tsParticlesInternals.palettes=t(e.__tsParticlesInternals.palettes),e.__tsParticlesInternals.paths=t(e.__tsParticlesInternals.paths),e.__tsParticlesInternals.plugins=t(e.__tsParticlesInternals.plugins),e.__tsParticlesInternals.plugins.emittersShapes=t(e.__tsParticlesInternals.plugins.emittersShapes),e.__tsParticlesInternals.presets=t(e.__tsParticlesInternals.presets),e.__tsParticlesInternals.shapes=t(e.__tsParticlesInternals.shapes),e.__tsParticlesInternals.updaters=t(e.__tsParticlesInternals.updaters),e.__tsParticlesInternals.utils=t(e.__tsParticlesInternals.utils),e.__tsParticlesInternals.canvas=t(e.__tsParticlesInternals.canvas),e.__tsParticlesInternals.path=t(e.__tsParticlesInternals.path),e.tsparticlesInternalExports=e.tsparticlesInternalExports||{}}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:this),function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@tsparticles/plugin-interactivity"),require("@tsparticles/engine")):"function"==typeof define&&define.amd?define(["exports","@tsparticles/plugin-interactivity","@tsparticles/engine"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).__tsParticlesInternals=e.__tsParticlesInternals||{},e.__tsParticlesInternals.interactions=e.__tsParticlesInternals.interactions||{},e.__tsParticlesInternals.interactions.externalRepulse=e.__tsParticlesInternals.interactions.externalRepulse||{}),e.__tsParticlesInternals.plugins.interactivity,e.__tsParticlesInternals.engine)}(this,function(e,t,s){"use strict";class i{distance;duration;easing;factor;maxSpeed;restore;speed;constructor(){this.distance=200,this.duration=.4,this.factor=100,this.speed=1,this.maxSpeed=50,this.easing=s.EasingType.easeOutQuad,this.restore={enable:!1,delay:0,speed:.08,follow:!0}}load(e){s.isNull(e)||(void 0!==e.distance&&(this.distance=e.distance),void 0!==e.duration&&(this.duration=e.duration),void 0!==e.easing&&(this.easing=e.easing),void 0!==e.factor&&(this.factor=e.factor),void 0!==e.speed&&(this.speed=e.speed),void 0!==e.maxSpeed&&(this.maxSpeed=e.maxSpeed),void 0!==e.restore&&(this.restore.enable=e.restore.enable??this.restore.enable,this.restore.delay=e.restore.delay??this.restore.delay,this.restore.speed=e.restore.speed??this.restore.speed,this.restore.follow=e.restore.follow??this.restore.follow))}}class n extends i{selectors;constructor(){super(),this.selectors=[]}load(e){super.load(e),s.isNull(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}class a extends i{divs;load(e){super.load(e),s.isNull(e)||(this.divs=s.executeOnSingleOrMultiple(e.divs,e=>{const t=new n;return t.load(e),t}))}}const r="repulse";class l extends t.ExternalInteractorBase{handleClickMode;
|
|
1
|
+
!function(e){e.__tsParticlesInternals=e.__tsParticlesInternals||{},e.__tsParticlesInternals.bundles=e.__tsParticlesInternals.bundles||{},e.__tsParticlesInternals.effects=e.__tsParticlesInternals.effects||{},e.__tsParticlesInternals.engine=e.__tsParticlesInternals.engine||{},e.__tsParticlesInternals.interactions=e.__tsParticlesInternals.interactions||{},e.__tsParticlesInternals.palettes=e.__tsParticlesInternals.palettes||{},e.__tsParticlesInternals.paths=e.__tsParticlesInternals.paths||{},e.__tsParticlesInternals.plugins=e.__tsParticlesInternals.plugins||{},e.__tsParticlesInternals.plugins=e.__tsParticlesInternals.plugins||{},e.__tsParticlesInternals.plugins.emittersShapes=e.__tsParticlesInternals.plugins.emittersShapes||{},e.__tsParticlesInternals.presets=e.__tsParticlesInternals.presets||{},e.__tsParticlesInternals.shapes=e.__tsParticlesInternals.shapes||{},e.__tsParticlesInternals.updaters=e.__tsParticlesInternals.updaters||{},e.__tsParticlesInternals.utils=e.__tsParticlesInternals.utils||{},e.__tsParticlesInternals.canvas=e.__tsParticlesInternals.canvas||{},e.__tsParticlesInternals.canvas=e.__tsParticlesInternals.canvas||{},e.__tsParticlesInternals.canvas.utils=e.__tsParticlesInternals.canvas.utils||{},e.__tsParticlesInternals.path=e.__tsParticlesInternals.path||{},e.__tsParticlesInternals.path=e.__tsParticlesInternals.path||{},e.__tsParticlesInternals.path.utils=e.__tsParticlesInternals.path.utils||{};var t="undefined"!=typeof Proxy?function(e){return new Proxy(e,{get:function(e,t){return t in e||(e[t]={}),e[t]}})}:function(e){return e};e.__tsParticlesInternals.bundles=t(e.__tsParticlesInternals.bundles),e.__tsParticlesInternals.effects=t(e.__tsParticlesInternals.effects),e.__tsParticlesInternals.interactions=t(e.__tsParticlesInternals.interactions),e.__tsParticlesInternals.palettes=t(e.__tsParticlesInternals.palettes),e.__tsParticlesInternals.paths=t(e.__tsParticlesInternals.paths),e.__tsParticlesInternals.plugins=t(e.__tsParticlesInternals.plugins),e.__tsParticlesInternals.plugins.emittersShapes=t(e.__tsParticlesInternals.plugins.emittersShapes),e.__tsParticlesInternals.presets=t(e.__tsParticlesInternals.presets),e.__tsParticlesInternals.shapes=t(e.__tsParticlesInternals.shapes),e.__tsParticlesInternals.updaters=t(e.__tsParticlesInternals.updaters),e.__tsParticlesInternals.utils=t(e.__tsParticlesInternals.utils),e.__tsParticlesInternals.canvas=t(e.__tsParticlesInternals.canvas),e.__tsParticlesInternals.path=t(e.__tsParticlesInternals.path),e.tsparticlesInternalExports=e.tsparticlesInternalExports||{}}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:this),function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@tsparticles/plugin-interactivity"),require("@tsparticles/engine")):"function"==typeof define&&define.amd?define(["exports","@tsparticles/plugin-interactivity","@tsparticles/engine"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).__tsParticlesInternals=e.__tsParticlesInternals||{},e.__tsParticlesInternals.interactions=e.__tsParticlesInternals.interactions||{},e.__tsParticlesInternals.interactions.externalRepulse=e.__tsParticlesInternals.interactions.externalRepulse||{}),e.__tsParticlesInternals.plugins.interactivity,e.__tsParticlesInternals.engine)}(this,function(e,t,s){"use strict";class i{distance;duration;easing;factor;maxSpeed;restore;speed;constructor(){this.distance=200,this.duration=.4,this.factor=100,this.speed=1,this.maxSpeed=50,this.easing=s.EasingType.easeOutQuad,this.restore={enable:!1,delay:0,speed:.08,follow:!0}}load(e){s.isNull(e)||(void 0!==e.distance&&(this.distance=e.distance),void 0!==e.duration&&(this.duration=e.duration),void 0!==e.easing&&(this.easing=e.easing),void 0!==e.factor&&(this.factor=e.factor),void 0!==e.speed&&(this.speed=e.speed),void 0!==e.maxSpeed&&(this.maxSpeed=e.maxSpeed),void 0!==e.restore&&(this.restore.enable=e.restore.enable??this.restore.enable,this.restore.delay=e.restore.delay??this.restore.delay,this.restore.speed=e.restore.speed??this.restore.speed,this.restore.follow=e.restore.follow??this.restore.follow))}}class n extends i{selectors;constructor(){super(),this.selectors=[]}load(e){super.load(e),s.isNull(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}class a extends i{divs;load(e){super.load(e),s.isNull(e)||(this.divs=s.executeOnSingleOrMultiple(e.divs,e=>{const t=new n;return t.load(e),t}))}}const r="repulse";class l extends t.ExternalInteractorBase{handleClickMode;#e;#t;#s;#i;#n;#a;constructor(e,t){super(t),this.#n=e,this.#s=0,this.#i=s.Vector.origin,this.#t=new Set,this.#e=s.Vector.origin,this.#a=new Map,t.repulse??={particles:[]},this.handleClickMode=(e,i)=>{const n=this.container.actualOptions,a=n.interactivity?.modes.repulse;if(!a||e!==r)return;t.repulse??={particles:[]};const l=t.repulse;l.clicking=!0,l.count=0;for(const e of t.repulse.particles)this.isEnabled(i,e)&&e.velocity.setTo(e.initialVelocity);l.particles=[],l.finish=!1,setTimeout(()=>{t.destroyed||(l.clicking=!1)},a.duration*s.millisecondsToSeconds)}}get maxDistance(){return this.#s}clear(){}init(){const e=this.container,t=e.actualOptions.interactivity?.modes.repulse;t&&(this.#s=t.distance,e.retina.repulseModeDistance=t.distance*e.retina.pixelRatio)}interact(e){this.#t.clear();const i=this.container.actualOptions,n=e.status===t.mouseMoveEvent,a=i.interactivity?.events;if(!a)return;const l=a.onHover,c=l.enable,o=l.mode,p=a.onClick,d=p.enable,u=p.mode,_=a.onDiv;n&&c&&s.isInArray(r,o)?this.#r(e):d&&s.isInArray(r,u)?this.#l(e):t.divModeExecute(r,_,(t,s)=>{this.#c(e,t,s)}),this.#o()}isEnabled(e,i){const n=this.container.actualOptions,a=e.mouse,l=(i?.interactivity??n.interactivity)?.events;if(!l)return!1;const c=l.onDiv,o=l.onHover,p=l.onClick,d=t.isDivModeEnabled(r,c);if(!(d||o.enable&&a.position||p.enable&&a.clickPosition))return!1;const u=o.mode,_=p.mode;return s.isInArray(r,u)||s.isInArray(r,_)||d}loadModeOptions(e,...t){e.repulse??=new a;for(const s of t)e.repulse.load(s?.repulse)}reset(){}#l=e=>{const t=this.container,i=t.actualOptions.interactivity?.modes.repulse;if(!i)return;const n=t.repulse??{particles:[]};if(n.finish||(n.count??=0,n.count++,n.count===t.particles.count&&(n.finish=!0)),n.clicking){const a=t.retina.repulseModeDistance;if(!a||a<0)return;const r=Math.pow(a/6,3),l=e.mouse.clickPosition;if(void 0===l)return;const c=new s.Circle(l.x,l.y,r),o=t.particles.grid.query(c,t=>this.isEnabled(e,t));for(const e of o){const{dx:t,dy:a,distance:c}=s.getDistances(l,e.position),o=c**2,p=-r*i.speed/o;o<=r&&(this.#p(e),n.particles.push(e),this.#e.x=t,this.#e.y=a,this.#e.length=p,e.velocity.setTo(this.#e))}}else if(!1===n.clicking){for(const e of n.particles)e.velocity.setTo(e.initialVelocity);n.particles=[]}};#r=e=>{const t=this.container,i=e.mouse.position,n=t.retina.repulseModeDistance;!n||n<0||!i||this.#d(e,i,n,new s.Circle(i.x,i.y,n))};#d=(e,t,i,n,a)=>{const r=this.container,l=r.particles.grid.query(n,t=>this.isEnabled(e,t)),c=r.actualOptions.interactivity?.modes.repulse;if(!c)return;const{easing:o,speed:p,factor:d,maxSpeed:u}=c,_=this.#n.getEasing(o),h=(a?.speed??p)*d;for(const e of l){const{dx:n,dy:a,distance:r}=s.getDistances(e.position,t),l=s.clamp(_(1-r/i)*h,0,u);this.#i.x=r?n/r*l:h,this.#i.y=r?a/r*l:h,this.#p(e),e.position.addTo(this.#i)}};#o(){const e=this.container.actualOptions.interactivity?.modes.repulse?.restore;if(!e?.enable||!this.#a.size)return;const t=Date.now(),i=e.delay*s.millisecondsToSeconds,n=Math.max(.001,Math.min(1,e.speed));for(const[s,a]of this.#a){if(this.#t.has(s))continue;if(s.destroyed){this.#a.delete(s);continue}const r=a.target;if(t-a.lastInteractionTime<i)continue;e.follow&&s.options.move.enable&&(r.x+=s.velocity.x,r.y+=s.velocity.y,r.z+=s.velocity.z);const l=r.x-s.position.x,c=r.y-s.position.y,o=r.z-s.position.z;s.position.x+=l*n,s.position.y+=c*n,s.position.z+=o*n,Math.abs(l)<=.5&&Math.abs(c)<=.5&&(s.position.x=r.x,s.position.y=r.y,s.position.z=r.z,this.#a.delete(s))}}#c=(e,i,n)=>{const a=this.container,r=a.actualOptions.interactivity?.modes.repulse;if(!r)return;const l=s.safeDocument().querySelectorAll(i);l.length&&l.forEach(i=>{const l=i,c=a.retina.pixelRatio,o={x:(l.offsetLeft+l.offsetWidth*s.half)*c,y:(l.offsetTop+l.offsetHeight*s.half)*c},p=l.offsetWidth*s.half*c,d=n.type===t.DivType.circle?new s.Circle(o.x,o.y,p):new s.Rectangle(l.offsetLeft*c,l.offsetTop*c,l.offsetWidth*c,l.offsetHeight*c),u=r.divs,_=t.divMode(u,l);this.#d(e,o,p,d,_)})};#p(e){this.#t.add(e);const t=this.container.actualOptions.interactivity?.modes.repulse?.restore;if(!t?.enable)return;const s=Date.now();let i=this.#a.get(e);i||(i={target:e.position.copy(),lastInteractionTime:s},this.#a.set(e,i)),i.lastInteractionTime=s,t.follow&&e.options.move.enable&&(i.target.x+=e.velocity.x,i.target.y+=e.velocity.y,i.target.z+=e.velocity.z)}}async function c(e){e.checkVersion("4.1.0"),await e.pluginManager.register(e=>{t.ensureInteractivityPluginLoaded(e);const s=e.pluginManager;s.addInteractor?.("externalRepulse",e=>Promise.resolve(new l(s,e)))})}const o=globalThis;o.__tsParticlesInternals=o.__tsParticlesInternals??{},o.loadExternalRepulseInteraction=c,e.Repulse=a,e.RepulseBase=i,e.RepulseDiv=n,e.loadExternalRepulseInteraction=c}),Object.assign(globalThis.window||globalThis,{loadExternalRepulseInteraction:(globalThis.__tsParticlesInternals.interactions.externalRepulse||{}).loadExternalRepulseInteraction}),delete(globalThis.window||globalThis).tsparticlesInternalExports;
|
package/types/Repulser.d.ts
CHANGED
|
@@ -2,13 +2,8 @@ import { type PluginManager, type RecursivePartial } from "@tsparticles/engine";
|
|
|
2
2
|
import { ExternalInteractorBase, type IInteractivityData, type IModes, type InteractivityParticle, type Modes } from "@tsparticles/plugin-interactivity";
|
|
3
3
|
import type { IRepulseMode, RepulseContainer, RepulseMode } from "./Types.js";
|
|
4
4
|
export declare class Repulser extends ExternalInteractorBase<RepulseContainer> {
|
|
5
|
+
#private;
|
|
5
6
|
handleClickMode: (mode: string, interactivityData: IInteractivityData) => void;
|
|
6
|
-
private readonly _clickVec;
|
|
7
|
-
private readonly _interactedThisFrame;
|
|
8
|
-
private _maxDistance;
|
|
9
|
-
private readonly _normVec;
|
|
10
|
-
private readonly _pluginManager;
|
|
11
|
-
private readonly _restoreData;
|
|
12
7
|
constructor(pluginManager: PluginManager, container: RepulseContainer);
|
|
13
8
|
get maxDistance(): number;
|
|
14
9
|
clear(): void;
|
|
@@ -17,10 +12,4 @@ export declare class Repulser extends ExternalInteractorBase<RepulseContainer> {
|
|
|
17
12
|
isEnabled(interactivityData: IInteractivityData, particle?: InteractivityParticle): boolean;
|
|
18
13
|
loadModeOptions(options: Modes & RepulseMode, ...sources: RecursivePartial<(IModes & IRepulseMode) | undefined>[]): void;
|
|
19
14
|
reset(): void;
|
|
20
|
-
private readonly _clickRepulse;
|
|
21
|
-
private readonly _hoverRepulse;
|
|
22
|
-
private readonly _processRepulse;
|
|
23
|
-
private _restoreParticles;
|
|
24
|
-
private readonly _singleSelectorRepulse;
|
|
25
|
-
private _trackInteractedParticle;
|
|
26
15
|
}
|