@tsparticles/interaction-external-repulse 3.9.1 → 4.0.0-alpha.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/176.min.js +2 -0
- package/176.min.js.LICENSE.txt +1 -0
- package/browser/Repulser.js +9 -15
- package/browser/index.js +8 -9
- package/cjs/Options/Classes/Repulse.js +7 -11
- package/cjs/Options/Classes/RepulseBase.js +4 -8
- package/cjs/Options/Classes/RepulseDiv.js +4 -8
- package/cjs/Options/Classes/RepulseOptions.js +1 -2
- package/cjs/Options/Interfaces/IRepulse.js +1 -2
- package/cjs/Options/Interfaces/IRepulseBase.js +1 -2
- package/cjs/Options/Interfaces/IRepulseDiv.js +1 -2
- package/cjs/Repulser.js +25 -35
- package/cjs/Types.js +1 -2
- package/cjs/index.js +11 -29
- package/dist_browser_Repulser_js.js +30 -0
- package/esm/Repulser.js +9 -15
- package/esm/index.js +8 -9
- package/package.json +4 -3
- package/report.html +5 -4
- package/tsparticles.interaction.external.repulse.js +221 -42
- package/tsparticles.interaction.external.repulse.min.js +1 -1
- package/tsparticles.interaction.external.repulse.min.js.LICENSE.txt +1 -1
- package/types/index.d.ts +4 -4
- package/umd/Repulser.js +8 -14
- package/umd/index.js +32 -10
package/176.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 176.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[]).push([[176],{176(e,t,i){i.d(t,{Repulser:()=>c});var s=i(303),n=i(246);const o="repulse";class c extends s.ExternalInteractorBase{constructor(e,t){super(t),this._clickRepulse=()=>{const e=this.container,t=e.actualOptions.interactivity.modes.repulse;if(!t)return;const i=e.repulse??{particles:[]};if(i.finish||(i.count??=0,i.count++,i.count===e.particles.count&&(i.finish=!0)),i.clicking){const n=e.retina.repulseModeDistance;if(!n||n<0)return;const o=Math.pow(n/6,3),c=e.interactivity.mouse.clickPosition;if(void 0===c)return;const r=new s.Circle(c.x,c.y,o),a=e.particles.quadTree.query(r,(e=>this.isEnabled(e)));for(const e of a){const{dx:n,dy:r,distance:a}=(0,s.getDistances)(c,e.position),l=a**2,p=-o*t.speed/l;if(l<=o){i.particles.push(e);const t=s.Vector.create(n,r);t.length=p,e.velocity.setTo(t)}}}else if(!1===i.clicking){for(const e of i.particles)e.velocity.setTo(e.initialVelocity);i.particles=[]}},this._hoverRepulse=()=>{const e=this.container,t=e.interactivity.mouse.position,i=e.retina.repulseModeDistance;!i||i<0||!t||this._processRepulse(t,i,new s.Circle(t.x,t.y,i))},this._processRepulse=(e,t,i,n)=>{const o=this.container,c=o.particles.quadTree.query(i,(e=>this.isEnabled(e))),r=o.actualOptions.interactivity.modes.repulse;if(!r)return;const{easing:a,speed:l,factor:p,maxSpeed:u}=r,d=this._engine.getEasing(a),f=(n?.speed??l)*p;for(const i of c){const{dx:n,dy:o,distance:c}=(0,s.getDistances)(i.position,e),r=(0,s.clamp)(d(1-c/t)*f,0,u),a=s.Vector.create(c?n/c*r:f,c?o/c*r:f);i.position.addTo(a)}},this._singleSelectorRepulse=(e,t)=>{const i=this.container,n=i.actualOptions.interactivity.modes.repulse;if(!n)return;const o=(0,s.safeDocument)().querySelectorAll(e);o.length&&o.forEach((e=>{const o=e,c=i.retina.pixelRatio,r={x:(o.offsetLeft+.5*o.offsetWidth)*c,y:(o.offsetTop+.5*o.offsetHeight)*c},a=.5*o.offsetWidth*c,l=t.type===s.DivType.circle?new s.Circle(r.x,r.y,a):new s.Rectangle(o.offsetLeft*c,o.offsetTop*c,o.offsetWidth*c,o.offsetHeight*c),p=n.divs,u=(0,s.divMode)(p,o);this._processRepulse(r,a,l,u)}))},this._engine=e,t.repulse??={particles:[]},this.handleClickMode=e=>{const i=this.container.actualOptions.interactivity.modes.repulse;if(!i||e!==o)return;t.repulse??={particles:[]};const n=t.repulse;n.clicking=!0,n.count=0;for(const e of t.repulse.particles)this.isEnabled(e)&&e.velocity.setTo(e.initialVelocity);n.particles=[],n.finish=!1,setTimeout((()=>{t.destroyed||(n.clicking=!1)}),i.duration*s.millisecondsToSeconds)}}clear(){}init(){const e=this.container,t=e.actualOptions.interactivity.modes.repulse;t&&(e.retina.repulseModeDistance=t.distance*e.retina.pixelRatio)}interact(){const e=this.container,t=e.actualOptions,i=e.interactivity.status===s.mouseMoveEvent,n=t.interactivity.events,c=n.onHover,r=c.enable,a=c.mode,l=n.onClick,p=l.enable,u=l.mode,d=n.onDiv;i&&r&&(0,s.isInArray)(o,a)?this._hoverRepulse():p&&(0,s.isInArray)(o,u)?this._clickRepulse():(0,s.divModeExecute)(o,d,((e,t)=>{this._singleSelectorRepulse(e,t)}))}isEnabled(e){const t=this.container,i=t.actualOptions,n=t.interactivity.mouse,c=(e?.interactivity??i.interactivity).events,r=c.onDiv,a=c.onHover,l=c.onClick,p=(0,s.isDivModeEnabled)(o,r);if(!(p||a.enable&&n.position||l.enable&&n.clickPosition))return!1;const u=a.mode,d=l.mode;return(0,s.isInArray)(o,u)||(0,s.isInArray)(o,d)||p}loadModeOptions(e,...t){e.repulse??=new n.Z;for(const i of t)e.repulse.load(i?.repulse)}reset(){}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Repulse External Interaction v4.0.0-alpha.0 by Matteo Bruni */
|
package/browser/Repulser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, } from "@tsparticles/engine";
|
|
1
|
+
import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, safeDocument, } from "@tsparticles/engine";
|
|
2
2
|
import { Repulse } from "./Options/Classes/Repulse.js";
|
|
3
3
|
const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, half = 0.5;
|
|
4
4
|
export class Repulser extends ExternalInteractorBase {
|
|
@@ -11,9 +11,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
11
11
|
}
|
|
12
12
|
const repulse = container.repulse ?? { particles: [] };
|
|
13
13
|
if (!repulse.finish) {
|
|
14
|
-
|
|
15
|
-
repulse.count = 0;
|
|
16
|
-
}
|
|
14
|
+
repulse.count ??= 0;
|
|
17
15
|
repulse.count++;
|
|
18
16
|
if (repulse.count === container.particles.count) {
|
|
19
17
|
repulse.finish = true;
|
|
@@ -69,7 +67,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
69
67
|
if (!repulse) {
|
|
70
68
|
return;
|
|
71
69
|
}
|
|
72
|
-
const query =
|
|
70
|
+
const query = safeDocument().querySelectorAll(selector);
|
|
73
71
|
if (!query.length) {
|
|
74
72
|
return;
|
|
75
73
|
}
|
|
@@ -84,17 +82,13 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
84
82
|
});
|
|
85
83
|
};
|
|
86
84
|
this._engine = engine;
|
|
87
|
-
|
|
88
|
-
container.repulse = { particles: [] };
|
|
89
|
-
}
|
|
85
|
+
container.repulse ??= { particles: [] };
|
|
90
86
|
this.handleClickMode = (mode) => {
|
|
91
87
|
const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
|
|
92
88
|
if (!repulseOpts || mode !== repulseMode) {
|
|
93
89
|
return;
|
|
94
90
|
}
|
|
95
|
-
|
|
96
|
-
container.repulse = { particles: [] };
|
|
97
|
-
}
|
|
91
|
+
container.repulse ??= { particles: [] };
|
|
98
92
|
const repulse = container.repulse;
|
|
99
93
|
repulse.clicking = true;
|
|
100
94
|
repulse.count = 0;
|
|
@@ -132,7 +126,9 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
132
126
|
this._clickRepulse();
|
|
133
127
|
}
|
|
134
128
|
else {
|
|
135
|
-
divModeExecute(repulseMode, divs, (selector, div) =>
|
|
129
|
+
divModeExecute(repulseMode, divs, (selector, div) => {
|
|
130
|
+
this._singleSelectorRepulse(selector, div);
|
|
131
|
+
});
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
134
|
isEnabled(particle) {
|
|
@@ -144,9 +140,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
144
140
|
return isInArray(repulseMode, hoverMode) || isInArray(repulseMode, clickMode) || divRepulse;
|
|
145
141
|
}
|
|
146
142
|
loadModeOptions(options, ...sources) {
|
|
147
|
-
|
|
148
|
-
options.repulse = new Repulse();
|
|
149
|
-
}
|
|
143
|
+
options.repulse ??= new Repulse();
|
|
150
144
|
for (const source of sources) {
|
|
151
145
|
options.repulse.load(source?.repulse);
|
|
152
146
|
}
|
package/browser/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
engine.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export function loadExternalRepulseInteraction(engine) {
|
|
2
|
+
engine.checkVersion("4.0.0-alpha.0");
|
|
3
|
+
engine.register(e => {
|
|
4
|
+
e.addInteractor("externalRepulse", async (container) => {
|
|
5
|
+
const { Repulser } = await import("./Repulser.js");
|
|
6
|
+
return new Repulser(engine, container);
|
|
7
|
+
});
|
|
8
|
+
});
|
|
7
9
|
}
|
|
8
10
|
export * from "./Options/Classes/RepulseBase.js";
|
|
9
11
|
export * from "./Options/Classes/RepulseDiv.js";
|
|
10
12
|
export * from "./Options/Classes/Repulse.js";
|
|
11
|
-
export * from "./Options/Interfaces/IRepulseBase.js";
|
|
12
|
-
export * from "./Options/Interfaces/IRepulseDiv.js";
|
|
13
|
-
export * from "./Options/Interfaces/IRepulse.js";
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const RepulseBase_js_1 = require("./RepulseBase.js");
|
|
6
|
-
const RepulseDiv_js_1 = require("./RepulseDiv.js");
|
|
7
|
-
class Repulse extends RepulseBase_js_1.RepulseBase {
|
|
1
|
+
import { executeOnSingleOrMultiple, isNull, } from "@tsparticles/engine";
|
|
2
|
+
import { RepulseBase } from "./RepulseBase.js";
|
|
3
|
+
import { RepulseDiv } from "./RepulseDiv.js";
|
|
4
|
+
export class Repulse extends RepulseBase {
|
|
8
5
|
load(data) {
|
|
9
6
|
super.load(data);
|
|
10
|
-
if (
|
|
7
|
+
if (isNull(data)) {
|
|
11
8
|
return;
|
|
12
9
|
}
|
|
13
|
-
this.divs =
|
|
14
|
-
const tmp = new
|
|
10
|
+
this.divs = executeOnSingleOrMultiple(data.divs, div => {
|
|
11
|
+
const tmp = new RepulseDiv();
|
|
15
12
|
tmp.load(div);
|
|
16
13
|
return tmp;
|
|
17
14
|
});
|
|
18
15
|
}
|
|
19
16
|
}
|
|
20
|
-
exports.Repulse = Repulse;
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.RepulseBase = void 0;
|
|
4
|
-
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
class RepulseBase {
|
|
1
|
+
import { EasingType, isNull } from "@tsparticles/engine";
|
|
2
|
+
export class RepulseBase {
|
|
6
3
|
constructor() {
|
|
7
4
|
this.distance = 200;
|
|
8
5
|
this.duration = 0.4;
|
|
9
6
|
this.factor = 100;
|
|
10
7
|
this.speed = 1;
|
|
11
8
|
this.maxSpeed = 50;
|
|
12
|
-
this.easing =
|
|
9
|
+
this.easing = EasingType.easeOutQuad;
|
|
13
10
|
}
|
|
14
11
|
load(data) {
|
|
15
|
-
if (
|
|
12
|
+
if (isNull(data)) {
|
|
16
13
|
return;
|
|
17
14
|
}
|
|
18
15
|
if (data.distance !== undefined) {
|
|
@@ -35,4 +32,3 @@ class RepulseBase {
|
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
}
|
|
38
|
-
exports.RepulseBase = RepulseBase;
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
const RepulseBase_js_1 = require("./RepulseBase.js");
|
|
6
|
-
class RepulseDiv extends RepulseBase_js_1.RepulseBase {
|
|
1
|
+
import { isNull } from "@tsparticles/engine";
|
|
2
|
+
import { RepulseBase } from "./RepulseBase.js";
|
|
3
|
+
export class RepulseDiv extends RepulseBase {
|
|
7
4
|
constructor() {
|
|
8
5
|
super();
|
|
9
6
|
this.selectors = [];
|
|
10
7
|
}
|
|
11
8
|
load(data) {
|
|
12
9
|
super.load(data);
|
|
13
|
-
if (
|
|
10
|
+
if (isNull(data)) {
|
|
14
11
|
return;
|
|
15
12
|
}
|
|
16
13
|
if (data.selectors !== undefined) {
|
|
@@ -18,4 +15,3 @@ class RepulseDiv extends RepulseBase_js_1.RepulseBase {
|
|
|
18
15
|
}
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
|
-
exports.RepulseDiv = RepulseDiv;
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/cjs/Repulser.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.Repulser = void 0;
|
|
4
|
-
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
const Repulse_js_1 = require("./Options/Classes/Repulse.js");
|
|
1
|
+
import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, safeDocument, } from "@tsparticles/engine";
|
|
2
|
+
import { Repulse } from "./Options/Classes/Repulse.js";
|
|
6
3
|
const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, half = 0.5;
|
|
7
|
-
class Repulser extends
|
|
4
|
+
export class Repulser extends ExternalInteractorBase {
|
|
8
5
|
constructor(engine, container) {
|
|
9
6
|
super(container);
|
|
10
7
|
this._clickRepulse = () => {
|
|
@@ -14,9 +11,7 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
14
11
|
}
|
|
15
12
|
const repulse = container.repulse ?? { particles: [] };
|
|
16
13
|
if (!repulse.finish) {
|
|
17
|
-
|
|
18
|
-
repulse.count = 0;
|
|
19
|
-
}
|
|
14
|
+
repulse.count ??= 0;
|
|
20
15
|
repulse.count++;
|
|
21
16
|
if (repulse.count === container.particles.count) {
|
|
22
17
|
repulse.finish = true;
|
|
@@ -31,12 +26,12 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
31
26
|
if (mouseClickPos === undefined) {
|
|
32
27
|
return;
|
|
33
28
|
}
|
|
34
|
-
const range = new
|
|
29
|
+
const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(p));
|
|
35
30
|
for (const particle of query) {
|
|
36
|
-
const { dx, dy, distance } =
|
|
31
|
+
const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
|
|
37
32
|
if (d <= repulseRadius) {
|
|
38
33
|
repulse.particles.push(particle);
|
|
39
|
-
const vect =
|
|
34
|
+
const vect = Vector.create(dx, dy);
|
|
40
35
|
vect.length = force;
|
|
41
36
|
particle.velocity.setTo(vect);
|
|
42
37
|
}
|
|
@@ -54,7 +49,7 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
54
49
|
if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
|
|
55
50
|
return;
|
|
56
51
|
}
|
|
57
|
-
this._processRepulse(mousePos, repulseRadius, new
|
|
52
|
+
this._processRepulse(mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
|
|
58
53
|
};
|
|
59
54
|
this._processRepulse = (position, repulseRadius, area, divRepulse) => {
|
|
60
55
|
const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(p)), repulseOptions = container.actualOptions.interactivity.modes.repulse;
|
|
@@ -63,7 +58,7 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
63
58
|
}
|
|
64
59
|
const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this._engine.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
|
|
65
60
|
for (const particle of query) {
|
|
66
|
-
const { dx, dy, distance } =
|
|
61
|
+
const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed), normVec = Vector.create(!distance ? velocity : (dx / distance) * repulseFactor, !distance ? velocity : (dy / distance) * repulseFactor);
|
|
67
62
|
particle.position.addTo(normVec);
|
|
68
63
|
}
|
|
69
64
|
};
|
|
@@ -72,7 +67,7 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
72
67
|
if (!repulse) {
|
|
73
68
|
return;
|
|
74
69
|
}
|
|
75
|
-
const query =
|
|
70
|
+
const query = safeDocument().querySelectorAll(selector);
|
|
76
71
|
if (!query.length) {
|
|
77
72
|
return;
|
|
78
73
|
}
|
|
@@ -80,24 +75,20 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
80
75
|
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
|
|
81
76
|
x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
|
|
82
77
|
y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
|
|
83
|
-
}, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type ===
|
|
84
|
-
? new
|
|
85
|
-
: new
|
|
78
|
+
}, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
|
|
79
|
+
? new Circle(pos.x, pos.y, repulseRadius)
|
|
80
|
+
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
|
|
86
81
|
this._processRepulse(pos, repulseRadius, area, divRepulse);
|
|
87
82
|
});
|
|
88
83
|
};
|
|
89
84
|
this._engine = engine;
|
|
90
|
-
|
|
91
|
-
container.repulse = { particles: [] };
|
|
92
|
-
}
|
|
85
|
+
container.repulse ??= { particles: [] };
|
|
93
86
|
this.handleClickMode = (mode) => {
|
|
94
87
|
const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
|
|
95
88
|
if (!repulseOpts || mode !== repulseMode) {
|
|
96
89
|
return;
|
|
97
90
|
}
|
|
98
|
-
|
|
99
|
-
container.repulse = { particles: [] };
|
|
100
|
-
}
|
|
91
|
+
container.repulse ??= { particles: [] };
|
|
101
92
|
const repulse = container.repulse;
|
|
102
93
|
repulse.clicking = true;
|
|
103
94
|
repulse.count = 0;
|
|
@@ -114,7 +105,7 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
114
105
|
return;
|
|
115
106
|
}
|
|
116
107
|
repulse.clicking = false;
|
|
117
|
-
}, repulseOpts.duration *
|
|
108
|
+
}, repulseOpts.duration * millisecondsToSeconds);
|
|
118
109
|
};
|
|
119
110
|
}
|
|
120
111
|
clear() {
|
|
@@ -127,29 +118,29 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
127
118
|
container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
|
|
128
119
|
}
|
|
129
120
|
interact() {
|
|
130
|
-
const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status ===
|
|
131
|
-
if (mouseMoveStatus && hoverEnabled &&
|
|
121
|
+
const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === mouseMoveEvent, events = options.interactivity.events, hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
|
|
122
|
+
if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
|
|
132
123
|
this._hoverRepulse();
|
|
133
124
|
}
|
|
134
|
-
else if (clickEnabled &&
|
|
125
|
+
else if (clickEnabled && isInArray(repulseMode, clickMode)) {
|
|
135
126
|
this._clickRepulse();
|
|
136
127
|
}
|
|
137
128
|
else {
|
|
138
|
-
|
|
129
|
+
divModeExecute(repulseMode, divs, (selector, div) => {
|
|
130
|
+
this._singleSelectorRepulse(selector, div);
|
|
131
|
+
});
|
|
139
132
|
}
|
|
140
133
|
}
|
|
141
134
|
isEnabled(particle) {
|
|
142
|
-
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse =
|
|
135
|
+
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
|
|
143
136
|
if (!(divRepulse || (hover.enable && !!mouse.position) || (click.enable && mouse.clickPosition))) {
|
|
144
137
|
return false;
|
|
145
138
|
}
|
|
146
139
|
const hoverMode = hover.mode, clickMode = click.mode;
|
|
147
|
-
return
|
|
140
|
+
return isInArray(repulseMode, hoverMode) || isInArray(repulseMode, clickMode) || divRepulse;
|
|
148
141
|
}
|
|
149
142
|
loadModeOptions(options, ...sources) {
|
|
150
|
-
|
|
151
|
-
options.repulse = new Repulse_js_1.Repulse();
|
|
152
|
-
}
|
|
143
|
+
options.repulse ??= new Repulse();
|
|
153
144
|
for (const source of sources) {
|
|
154
145
|
options.repulse.load(source?.repulse);
|
|
155
146
|
}
|
|
@@ -157,4 +148,3 @@ class Repulser extends engine_1.ExternalInteractorBase {
|
|
|
157
148
|
reset() {
|
|
158
149
|
}
|
|
159
150
|
}
|
|
160
|
-
exports.Repulser = Repulser;
|
package/cjs/Types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/cjs/index.js
CHANGED
|
@@ -1,30 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.loadExternalRepulseInteraction = loadExternalRepulseInteraction;
|
|
18
|
-
const Repulser_js_1 = require("./Repulser.js");
|
|
19
|
-
async function loadExternalRepulseInteraction(engine, refresh = true) {
|
|
20
|
-
engine.checkVersion("3.9.1");
|
|
21
|
-
await engine.addInteractor("externalRepulse", container => {
|
|
22
|
-
return Promise.resolve(new Repulser_js_1.Repulser(engine, container));
|
|
23
|
-
}, refresh);
|
|
1
|
+
export function loadExternalRepulseInteraction(engine) {
|
|
2
|
+
engine.checkVersion("4.0.0-alpha.0");
|
|
3
|
+
engine.register(e => {
|
|
4
|
+
e.addInteractor("externalRepulse", async (container) => {
|
|
5
|
+
const { Repulser } = await import("./Repulser.js");
|
|
6
|
+
return new Repulser(engine, container);
|
|
7
|
+
});
|
|
8
|
+
});
|
|
24
9
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
__exportStar(require("./Options/Interfaces/IRepulseBase.js"), exports);
|
|
29
|
-
__exportStar(require("./Options/Interfaces/IRepulseDiv.js"), exports);
|
|
30
|
-
__exportStar(require("./Options/Interfaces/IRepulse.js"), exports);
|
|
10
|
+
export * from "./Options/Classes/RepulseBase.js";
|
|
11
|
+
export * from "./Options/Classes/RepulseDiv.js";
|
|
12
|
+
export * from "./Options/Classes/Repulse.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Author : Matteo Bruni
|
|
3
|
+
* MIT license: https://opensource.org/licenses/MIT
|
|
4
|
+
* Demo / Generator : https://particles.js.org/
|
|
5
|
+
* GitHub : https://www.github.com/matteobruni/tsparticles
|
|
6
|
+
* How to use? : Check the GitHub README
|
|
7
|
+
* v4.0.0-alpha.0
|
|
8
|
+
*/
|
|
9
|
+
"use strict";
|
|
10
|
+
/*
|
|
11
|
+
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
12
|
+
* This devtool is neither made for production nor for readable output files.
|
|
13
|
+
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
14
|
+
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
15
|
+
* or disable the default devtool with "devtool: false".
|
|
16
|
+
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
17
|
+
*/
|
|
18
|
+
(this["webpackChunk_tsparticles_interaction_external_repulse"] = this["webpackChunk_tsparticles_interaction_external_repulse"] || []).push([["dist_browser_Repulser_js"],{
|
|
19
|
+
|
|
20
|
+
/***/ "./dist/browser/Repulser.js"
|
|
21
|
+
/*!**********************************!*\
|
|
22
|
+
!*** ./dist/browser/Repulser.js ***!
|
|
23
|
+
\**********************************/
|
|
24
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
25
|
+
|
|
26
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Repulser: () => (/* binding */ Repulser)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Options/Classes/Repulse.js */ \"./dist/browser/Options/Classes/Repulse.js\");\n\n\nconst repulseMode = \"repulse\",\n minDistance = 0,\n repulseRadiusFactor = 6,\n repulseRadiusPower = 3,\n squarePower = 2,\n minRadius = 0,\n minSpeed = 0,\n easingOffset = 1,\n half = 0.5;\nclass Repulser extends _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.ExternalInteractorBase {\n constructor(engine, container) {\n super(container);\n this._clickRepulse = () => {\n const container = this.container,\n repulseOptions = container.actualOptions.interactivity.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const repulse = container.repulse ?? {\n particles: []\n };\n if (!repulse.finish) {\n repulse.count ??= 0;\n repulse.count++;\n if (repulse.count === container.particles.count) {\n repulse.finish = true;\n }\n }\n if (repulse.clicking) {\n const repulseDistance = container.retina.repulseModeDistance;\n if (!repulseDistance || repulseDistance < minDistance) {\n return;\n }\n const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower),\n mouseClickPos = container.interactivity.mouse.clickPosition;\n if (mouseClickPos === undefined) {\n return;\n }\n const range = new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius),\n query = container.particles.quadTree.query(range, p => this.isEnabled(p));\n for (const particle of query) {\n const {\n dx,\n dy,\n distance\n } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(mouseClickPos, particle.position),\n d = distance ** squarePower,\n velocity = repulseOptions.speed,\n force = -repulseRadius * velocity / d;\n if (d <= repulseRadius) {\n repulse.particles.push(particle);\n const vect = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.create(dx, dy);\n vect.length = force;\n particle.velocity.setTo(vect);\n }\n }\n } else if (repulse.clicking === false) {\n for (const particle of repulse.particles) {\n particle.velocity.setTo(particle.initialVelocity);\n }\n repulse.particles = [];\n }\n };\n this._hoverRepulse = () => {\n const container = this.container,\n mousePos = container.interactivity.mouse.position,\n repulseRadius = container.retina.repulseModeDistance;\n if (!repulseRadius || repulseRadius < minRadius || !mousePos) {\n return;\n }\n this._processRepulse(mousePos, repulseRadius, new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(mousePos.x, mousePos.y, repulseRadius));\n };\n this._processRepulse = (position, repulseRadius, area, divRepulse) => {\n const container = this.container,\n query = container.particles.quadTree.query(area, p => this.isEnabled(p)),\n repulseOptions = container.actualOptions.interactivity.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const {\n easing,\n speed,\n factor,\n maxSpeed\n } = repulseOptions,\n easingFunc = this._engine.getEasing(easing),\n velocity = (divRepulse?.speed ?? speed) * factor;\n for (const particle of query) {\n const {\n dx,\n dy,\n distance\n } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(particle.position, position),\n repulseFactor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.clamp)(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed),\n normVec = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.create(!distance ? velocity : dx / distance * repulseFactor, !distance ? velocity : dy / distance * repulseFactor);\n particle.position.addTo(normVec);\n }\n };\n this._singleSelectorRepulse = (selector, div) => {\n const container = this.container,\n repulse = container.actualOptions.interactivity.modes.repulse;\n if (!repulse) {\n return;\n }\n const query = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.safeDocument)().querySelectorAll(selector);\n if (!query.length) {\n return;\n }\n query.forEach(item => {\n const elem = item,\n pxRatio = container.retina.pixelRatio,\n pos = {\n x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio\n },\n repulseRadius = elem.offsetWidth * half * pxRatio,\n area = div.type === _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.DivType.circle ? new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(pos.x, pos.y, repulseRadius) : new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio),\n divs = repulse.divs,\n divRepulse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.divMode)(divs, elem);\n this._processRepulse(pos, repulseRadius, area, divRepulse);\n });\n };\n this._engine = engine;\n container.repulse ??= {\n particles: []\n };\n this.handleClickMode = mode => {\n const options = this.container.actualOptions,\n repulseOpts = options.interactivity.modes.repulse;\n if (!repulseOpts || mode !== repulseMode) {\n return;\n }\n container.repulse ??= {\n particles: []\n };\n const repulse = container.repulse;\n repulse.clicking = true;\n repulse.count = 0;\n for (const particle of container.repulse.particles) {\n if (!this.isEnabled(particle)) {\n continue;\n }\n particle.velocity.setTo(particle.initialVelocity);\n }\n repulse.particles = [];\n repulse.finish = false;\n setTimeout(() => {\n if (container.destroyed) {\n return;\n }\n repulse.clicking = false;\n }, repulseOpts.duration * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.millisecondsToSeconds);\n };\n }\n clear() {}\n init() {\n const container = this.container,\n repulse = container.actualOptions.interactivity.modes.repulse;\n if (!repulse) {\n return;\n }\n container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;\n }\n interact() {\n const container = this.container,\n options = container.actualOptions,\n mouseMoveStatus = container.interactivity.status === _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.mouseMoveEvent,\n events = options.interactivity.events,\n hover = events.onHover,\n hoverEnabled = hover.enable,\n hoverMode = hover.mode,\n click = events.onClick,\n clickEnabled = click.enable,\n clickMode = click.mode,\n divs = events.onDiv;\n if (mouseMoveStatus && hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode)) {\n this._hoverRepulse();\n } else if (clickEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, clickMode)) {\n this._clickRepulse();\n } else {\n (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.divModeExecute)(repulseMode, divs, (selector, div) => {\n this._singleSelectorRepulse(selector, div);\n });\n }\n }\n isEnabled(particle) {\n const container = this.container,\n options = container.actualOptions,\n mouse = container.interactivity.mouse,\n events = (particle?.interactivity ?? options.interactivity).events,\n divs = events.onDiv,\n hover = events.onHover,\n click = events.onClick,\n divRepulse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isDivModeEnabled)(repulseMode, divs);\n if (!(divRepulse || hover.enable && !!mouse.position || click.enable && mouse.clickPosition)) {\n return false;\n }\n const hoverMode = hover.mode,\n clickMode = click.mode;\n return (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode) || (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, clickMode) || divRepulse;\n }\n loadModeOptions(options, ...sources) {\n options.repulse ??= new _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_1__.Repulse();\n for (const source of sources) {\n options.repulse.load(source?.repulse);\n }\n }\n reset() {}\n}\n\n//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/Repulser.js?\n}");
|
|
27
|
+
|
|
28
|
+
/***/ }
|
|
29
|
+
|
|
30
|
+
}]);
|
package/esm/Repulser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, } from "@tsparticles/engine";
|
|
1
|
+
import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, safeDocument, } from "@tsparticles/engine";
|
|
2
2
|
import { Repulse } from "./Options/Classes/Repulse.js";
|
|
3
3
|
const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, half = 0.5;
|
|
4
4
|
export class Repulser extends ExternalInteractorBase {
|
|
@@ -11,9 +11,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
11
11
|
}
|
|
12
12
|
const repulse = container.repulse ?? { particles: [] };
|
|
13
13
|
if (!repulse.finish) {
|
|
14
|
-
|
|
15
|
-
repulse.count = 0;
|
|
16
|
-
}
|
|
14
|
+
repulse.count ??= 0;
|
|
17
15
|
repulse.count++;
|
|
18
16
|
if (repulse.count === container.particles.count) {
|
|
19
17
|
repulse.finish = true;
|
|
@@ -69,7 +67,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
69
67
|
if (!repulse) {
|
|
70
68
|
return;
|
|
71
69
|
}
|
|
72
|
-
const query =
|
|
70
|
+
const query = safeDocument().querySelectorAll(selector);
|
|
73
71
|
if (!query.length) {
|
|
74
72
|
return;
|
|
75
73
|
}
|
|
@@ -84,17 +82,13 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
84
82
|
});
|
|
85
83
|
};
|
|
86
84
|
this._engine = engine;
|
|
87
|
-
|
|
88
|
-
container.repulse = { particles: [] };
|
|
89
|
-
}
|
|
85
|
+
container.repulse ??= { particles: [] };
|
|
90
86
|
this.handleClickMode = (mode) => {
|
|
91
87
|
const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
|
|
92
88
|
if (!repulseOpts || mode !== repulseMode) {
|
|
93
89
|
return;
|
|
94
90
|
}
|
|
95
|
-
|
|
96
|
-
container.repulse = { particles: [] };
|
|
97
|
-
}
|
|
91
|
+
container.repulse ??= { particles: [] };
|
|
98
92
|
const repulse = container.repulse;
|
|
99
93
|
repulse.clicking = true;
|
|
100
94
|
repulse.count = 0;
|
|
@@ -132,7 +126,9 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
132
126
|
this._clickRepulse();
|
|
133
127
|
}
|
|
134
128
|
else {
|
|
135
|
-
divModeExecute(repulseMode, divs, (selector, div) =>
|
|
129
|
+
divModeExecute(repulseMode, divs, (selector, div) => {
|
|
130
|
+
this._singleSelectorRepulse(selector, div);
|
|
131
|
+
});
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
134
|
isEnabled(particle) {
|
|
@@ -144,9 +140,7 @@ export class Repulser extends ExternalInteractorBase {
|
|
|
144
140
|
return isInArray(repulseMode, hoverMode) || isInArray(repulseMode, clickMode) || divRepulse;
|
|
145
141
|
}
|
|
146
142
|
loadModeOptions(options, ...sources) {
|
|
147
|
-
|
|
148
|
-
options.repulse = new Repulse();
|
|
149
|
-
}
|
|
143
|
+
options.repulse ??= new Repulse();
|
|
150
144
|
for (const source of sources) {
|
|
151
145
|
options.repulse.load(source?.repulse);
|
|
152
146
|
}
|
package/esm/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
engine.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export function loadExternalRepulseInteraction(engine) {
|
|
2
|
+
engine.checkVersion("4.0.0-alpha.0");
|
|
3
|
+
engine.register(e => {
|
|
4
|
+
e.addInteractor("externalRepulse", async (container) => {
|
|
5
|
+
const { Repulser } = await import("./Repulser.js");
|
|
6
|
+
return new Repulser(engine, container);
|
|
7
|
+
});
|
|
8
|
+
});
|
|
7
9
|
}
|
|
8
10
|
export * from "./Options/Classes/RepulseBase.js";
|
|
9
11
|
export * from "./Options/Classes/RepulseDiv.js";
|
|
10
12
|
export * from "./Options/Classes/Repulse.js";
|
|
11
|
-
export * from "./Options/Interfaces/IRepulseBase.js";
|
|
12
|
-
export * from "./Options/Interfaces/IRepulseDiv.js";
|
|
13
|
-
export * from "./Options/Interfaces/IRepulse.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsparticles/interaction-external-repulse",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-alpha.0",
|
|
4
4
|
"description": "tsParticles repulse external interaction",
|
|
5
5
|
"homepage": "https://particles.js.org",
|
|
6
6
|
"repository": {
|
|
@@ -87,9 +87,10 @@
|
|
|
87
87
|
"./package.json": "./package.json"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"@tsparticles/engine": "
|
|
90
|
+
"@tsparticles/engine": "4.0.0-alpha.0"
|
|
91
91
|
},
|
|
92
92
|
"publishConfig": {
|
|
93
93
|
"access": "public"
|
|
94
|
-
}
|
|
94
|
+
},
|
|
95
|
+
"type": "module"
|
|
95
96
|
}
|