@tsparticles/interaction-external-attract 3.0.0-alpha.1 → 3.0.0-beta.1
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/README.md +25 -19
- package/browser/Attractor.js +59 -58
- package/browser/index.js +5 -5
- package/browser/package.json +1 -0
- package/cjs/Attractor.js +66 -76
- package/cjs/index.js +5 -16
- package/cjs/package.json +1 -0
- package/esm/Attractor.js +59 -58
- package/esm/index.js +5 -5
- package/esm/package.json +1 -0
- package/package.json +19 -6
- package/report.html +4 -4
- package/tsparticles.interaction.external.attract.js +76 -73
- package/tsparticles.interaction.external.attract.min.js +1 -1
- package/tsparticles.interaction.external.attract.min.js.LICENSE.txt +1 -8
- package/types/Attractor.d.ts +5 -6
- package/types/Options/Classes/Attract.d.ts +2 -3
- package/types/Options/Classes/AttractOptions.d.ts +1 -1
- package/types/Types.d.ts +3 -3
- package/types/index.d.ts +3 -3
- package/umd/Attractor.js +61 -60
- package/umd/index.js +6 -6
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
# tsParticles External Attraction Interaction
|
|
4
4
|
|
|
5
|
-
[](https://www.jsdelivr.com/package/npm/@tsparticles/interaction-external-attract)
|
|
6
|
+
[](https://www.npmjs.com/package/@tsparticles/interaction-external-attract)
|
|
7
|
+
[](https://www.npmjs.com/package/@tsparticles/interaction-external-attract) [](https://github.com/sponsors/matteobruni)
|
|
8
8
|
|
|
9
9
|
[tsParticles](https://github.com/matteobruni/tsparticles) interaction plugin for attract effect around mouse or HTML
|
|
10
10
|
elements.
|
|
@@ -27,14 +27,16 @@ loadExternalAttractInteraction;
|
|
|
27
27
|
Once the scripts are loaded you can set up `tsParticles` and the interaction plugin like this:
|
|
28
28
|
|
|
29
29
|
```javascript
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
30
|
+
(async () => {
|
|
31
|
+
await loadExternalAttractInteraction(tsParticles);
|
|
32
|
+
|
|
33
|
+
await tsParticles.load({
|
|
34
|
+
id: "tsparticles",
|
|
35
|
+
options: {
|
|
36
|
+
/* options */
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
})();
|
|
38
40
|
```
|
|
39
41
|
|
|
40
42
|
### ESM / CommonJS
|
|
@@ -42,29 +44,33 @@ tsParticles.load({
|
|
|
42
44
|
This package is compatible also with ES or CommonJS modules, firstly this needs to be installed, like this:
|
|
43
45
|
|
|
44
46
|
```shell
|
|
45
|
-
$ npm install tsparticles
|
|
47
|
+
$ npm install @tsparticles/interaction-external-attract
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
or
|
|
49
51
|
|
|
50
52
|
```shell
|
|
51
|
-
$ yarn add tsparticles
|
|
53
|
+
$ yarn add @tsparticles/interaction-external-attract
|
|
52
54
|
```
|
|
53
55
|
|
|
54
56
|
Then you need to import it in the app, like this:
|
|
55
57
|
|
|
56
58
|
```javascript
|
|
57
|
-
const { tsParticles } = require("tsparticles
|
|
58
|
-
const { loadExternalAttractInteraction } = require("tsparticles
|
|
59
|
+
const { tsParticles } = require("@tsparticles/engine");
|
|
60
|
+
const { loadExternalAttractInteraction } = require("@tsparticles/interaction-external-attract");
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
(async () => {
|
|
63
|
+
await loadExternalAttractInteraction(tsParticles);
|
|
64
|
+
})();
|
|
61
65
|
```
|
|
62
66
|
|
|
63
67
|
or
|
|
64
68
|
|
|
65
69
|
```javascript
|
|
66
|
-
import { tsParticles } from "tsparticles
|
|
67
|
-
import { loadExternalAttractInteraction } from "tsparticles
|
|
70
|
+
import { tsParticles } from "@tsparticles/engine";
|
|
71
|
+
import { loadExternalAttractInteraction } from "@tsparticles/interaction-external-attract";
|
|
68
72
|
|
|
69
|
-
|
|
73
|
+
(async () => {
|
|
74
|
+
await loadExternalAttractInteraction(tsParticles);
|
|
75
|
+
})();
|
|
70
76
|
```
|
package/browser/Attractor.js
CHANGED
|
@@ -1,8 +1,56 @@
|
|
|
1
1
|
import { Circle, ExternalInteractorBase, Vector, clamp, getDistances, getEasing, isInArray, mouseMoveEvent, } from "@tsparticles/engine";
|
|
2
|
-
import { Attract } from "./Options/Classes/Attract";
|
|
2
|
+
import { Attract } from "./Options/Classes/Attract.js";
|
|
3
3
|
export class Attractor extends ExternalInteractorBase {
|
|
4
4
|
constructor(engine, container) {
|
|
5
5
|
super(container);
|
|
6
|
+
this._clickAttract = () => {
|
|
7
|
+
const container = this.container;
|
|
8
|
+
if (!container.attract) {
|
|
9
|
+
container.attract = { particles: [] };
|
|
10
|
+
}
|
|
11
|
+
const { attract } = container;
|
|
12
|
+
if (!attract.finish) {
|
|
13
|
+
if (!attract.count) {
|
|
14
|
+
attract.count = 0;
|
|
15
|
+
}
|
|
16
|
+
attract.count++;
|
|
17
|
+
if (attract.count === container.particles.count) {
|
|
18
|
+
attract.finish = true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (attract.clicking) {
|
|
22
|
+
const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
|
|
23
|
+
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
27
|
+
}
|
|
28
|
+
else if (attract.clicking === false) {
|
|
29
|
+
attract.particles = [];
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
};
|
|
33
|
+
this._hoverAttract = () => {
|
|
34
|
+
const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
|
|
35
|
+
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
39
|
+
};
|
|
40
|
+
this._processAttract = (position, attractRadius, area) => {
|
|
41
|
+
const container = this.container, attractOptions = container.actualOptions.interactivity.modes.attract;
|
|
42
|
+
if (!attractOptions) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
|
|
46
|
+
for (const particle of query) {
|
|
47
|
+
const { dx, dy, distance } = getDistances(particle.position, position);
|
|
48
|
+
const velocity = attractOptions.speed * attractOptions.factor;
|
|
49
|
+
const attractFactor = clamp(getEasing(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
|
|
50
|
+
const normVec = Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
|
|
51
|
+
particle.position.subFrom(normVec);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
6
54
|
this._engine = engine;
|
|
7
55
|
if (!container.attract) {
|
|
8
56
|
container.attract = { particles: [] };
|
|
@@ -26,12 +74,13 @@ export class Attractor extends ExternalInteractorBase {
|
|
|
26
74
|
container.attract.particles = [];
|
|
27
75
|
container.attract.finish = false;
|
|
28
76
|
setTimeout(() => {
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
container.attract
|
|
77
|
+
if (container.destroyed) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (!container.attract) {
|
|
81
|
+
container.attract = { particles: [] };
|
|
34
82
|
}
|
|
83
|
+
container.attract.clicking = false;
|
|
35
84
|
}, attract.duration * 1000);
|
|
36
85
|
};
|
|
37
86
|
}
|
|
@@ -47,15 +96,14 @@ export class Attractor extends ExternalInteractorBase {
|
|
|
47
96
|
async interact() {
|
|
48
97
|
const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === mouseMoveEvent, events = options.interactivity.events, hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, clickEnabled = events.onClick.enable, clickMode = events.onClick.mode;
|
|
49
98
|
if (mouseMoveStatus && hoverEnabled && isInArray("attract", hoverMode)) {
|
|
50
|
-
this.
|
|
99
|
+
this._hoverAttract();
|
|
51
100
|
}
|
|
52
101
|
else if (clickEnabled && isInArray("attract", clickMode)) {
|
|
53
|
-
this.
|
|
102
|
+
this._clickAttract();
|
|
54
103
|
}
|
|
55
104
|
}
|
|
56
105
|
isEnabled(particle) {
|
|
57
|
-
|
|
58
|
-
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events;
|
|
106
|
+
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events;
|
|
59
107
|
if ((!mouse.position || !events.onHover.enable) && (!mouse.clickPosition || !events.onClick.enable)) {
|
|
60
108
|
return false;
|
|
61
109
|
}
|
|
@@ -67,56 +115,9 @@ export class Attractor extends ExternalInteractorBase {
|
|
|
67
115
|
options.attract = new Attract();
|
|
68
116
|
}
|
|
69
117
|
for (const source of sources) {
|
|
70
|
-
options.attract.load(source
|
|
118
|
+
options.attract.load(source?.attract);
|
|
71
119
|
}
|
|
72
120
|
}
|
|
73
121
|
reset() {
|
|
74
122
|
}
|
|
75
|
-
clickAttract() {
|
|
76
|
-
const container = this.container;
|
|
77
|
-
if (!container.attract) {
|
|
78
|
-
container.attract = { particles: [] };
|
|
79
|
-
}
|
|
80
|
-
if (!container.attract.finish) {
|
|
81
|
-
if (!container.attract.count) {
|
|
82
|
-
container.attract.count = 0;
|
|
83
|
-
}
|
|
84
|
-
container.attract.count++;
|
|
85
|
-
if (container.attract.count === container.particles.count) {
|
|
86
|
-
container.attract.finish = true;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (container.attract.clicking) {
|
|
90
|
-
const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
|
|
91
|
-
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
this.processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
95
|
-
}
|
|
96
|
-
else if (container.attract.clicking === false) {
|
|
97
|
-
container.attract.particles = [];
|
|
98
|
-
}
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
hoverAttract() {
|
|
102
|
-
const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
|
|
103
|
-
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
this.processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
107
|
-
}
|
|
108
|
-
processAttract(position, attractRadius, area) {
|
|
109
|
-
const container = this.container, attractOptions = container.actualOptions.interactivity.modes.attract;
|
|
110
|
-
if (!attractOptions) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
|
|
114
|
-
for (const particle of query) {
|
|
115
|
-
const { dx, dy, distance } = getDistances(particle.position, position);
|
|
116
|
-
const velocity = attractOptions.speed * attractOptions.factor;
|
|
117
|
-
const attractFactor = clamp(getEasing(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
|
|
118
|
-
const normVec = Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
|
|
119
|
-
particle.position.subFrom(normVec);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
123
|
}
|
package/browser/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Attractor } from "./Attractor";
|
|
2
|
-
export async function loadExternalAttractInteraction(engine) {
|
|
3
|
-
await engine.addInteractor("externalAttract", (container) => new Attractor(engine, container));
|
|
1
|
+
import { Attractor } from "./Attractor.js";
|
|
2
|
+
export async function loadExternalAttractInteraction(engine, refresh = true) {
|
|
3
|
+
await engine.addInteractor("externalAttract", (container) => new Attractor(engine, container), refresh);
|
|
4
4
|
}
|
|
5
|
-
export * from "./Options/Classes/Attract";
|
|
6
|
-
export * from "./Options/Interfaces/IAttract";
|
|
5
|
+
export * from "./Options/Classes/Attract.js";
|
|
6
|
+
export * from "./Options/Interfaces/IAttract.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "module" }
|
package/cjs/Attractor.js
CHANGED
|
@@ -1,20 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.Attractor = void 0;
|
|
13
4
|
const engine_1 = require("@tsparticles/engine");
|
|
14
|
-
const
|
|
5
|
+
const Attract_js_1 = require("./Options/Classes/Attract.js");
|
|
15
6
|
class Attractor extends engine_1.ExternalInteractorBase {
|
|
16
7
|
constructor(engine, container) {
|
|
17
8
|
super(container);
|
|
9
|
+
this._clickAttract = () => {
|
|
10
|
+
const container = this.container;
|
|
11
|
+
if (!container.attract) {
|
|
12
|
+
container.attract = { particles: [] };
|
|
13
|
+
}
|
|
14
|
+
const { attract } = container;
|
|
15
|
+
if (!attract.finish) {
|
|
16
|
+
if (!attract.count) {
|
|
17
|
+
attract.count = 0;
|
|
18
|
+
}
|
|
19
|
+
attract.count++;
|
|
20
|
+
if (attract.count === container.particles.count) {
|
|
21
|
+
attract.finish = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (attract.clicking) {
|
|
25
|
+
const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
|
|
26
|
+
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this._processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
|
|
30
|
+
}
|
|
31
|
+
else if (attract.clicking === false) {
|
|
32
|
+
attract.particles = [];
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
};
|
|
36
|
+
this._hoverAttract = () => {
|
|
37
|
+
const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
|
|
38
|
+
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this._processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
|
|
42
|
+
};
|
|
43
|
+
this._processAttract = (position, attractRadius, area) => {
|
|
44
|
+
const container = this.container, attractOptions = container.actualOptions.interactivity.modes.attract;
|
|
45
|
+
if (!attractOptions) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
|
|
49
|
+
for (const particle of query) {
|
|
50
|
+
const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position);
|
|
51
|
+
const velocity = attractOptions.speed * attractOptions.factor;
|
|
52
|
+
const attractFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
|
|
53
|
+
const normVec = engine_1.Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
|
|
54
|
+
particle.position.subFrom(normVec);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
18
57
|
this._engine = engine;
|
|
19
58
|
if (!container.attract) {
|
|
20
59
|
container.attract = { particles: [] };
|
|
@@ -38,12 +77,13 @@ class Attractor extends engine_1.ExternalInteractorBase {
|
|
|
38
77
|
container.attract.particles = [];
|
|
39
78
|
container.attract.finish = false;
|
|
40
79
|
setTimeout(() => {
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
container.attract
|
|
80
|
+
if (container.destroyed) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!container.attract) {
|
|
84
|
+
container.attract = { particles: [] };
|
|
46
85
|
}
|
|
86
|
+
container.attract.clicking = false;
|
|
47
87
|
}, attract.duration * 1000);
|
|
48
88
|
};
|
|
49
89
|
}
|
|
@@ -56,20 +96,17 @@ class Attractor extends engine_1.ExternalInteractorBase {
|
|
|
56
96
|
}
|
|
57
97
|
container.retina.attractModeDistance = attract.distance * container.retina.pixelRatio;
|
|
58
98
|
}
|
|
59
|
-
interact() {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
});
|
|
99
|
+
async interact() {
|
|
100
|
+
const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === engine_1.mouseMoveEvent, events = options.interactivity.events, hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, clickEnabled = events.onClick.enable, clickMode = events.onClick.mode;
|
|
101
|
+
if (mouseMoveStatus && hoverEnabled && (0, engine_1.isInArray)("attract", hoverMode)) {
|
|
102
|
+
this._hoverAttract();
|
|
103
|
+
}
|
|
104
|
+
else if (clickEnabled && (0, engine_1.isInArray)("attract", clickMode)) {
|
|
105
|
+
this._clickAttract();
|
|
106
|
+
}
|
|
69
107
|
}
|
|
70
108
|
isEnabled(particle) {
|
|
71
|
-
|
|
72
|
-
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events;
|
|
109
|
+
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events;
|
|
73
110
|
if ((!mouse.position || !events.onHover.enable) && (!mouse.clickPosition || !events.onClick.enable)) {
|
|
74
111
|
return false;
|
|
75
112
|
}
|
|
@@ -78,60 +115,13 @@ class Attractor extends engine_1.ExternalInteractorBase {
|
|
|
78
115
|
}
|
|
79
116
|
loadModeOptions(options, ...sources) {
|
|
80
117
|
if (!options.attract) {
|
|
81
|
-
options.attract = new
|
|
118
|
+
options.attract = new Attract_js_1.Attract();
|
|
82
119
|
}
|
|
83
120
|
for (const source of sources) {
|
|
84
|
-
options.attract.load(source
|
|
121
|
+
options.attract.load(source?.attract);
|
|
85
122
|
}
|
|
86
123
|
}
|
|
87
124
|
reset() {
|
|
88
125
|
}
|
|
89
|
-
clickAttract() {
|
|
90
|
-
const container = this.container;
|
|
91
|
-
if (!container.attract) {
|
|
92
|
-
container.attract = { particles: [] };
|
|
93
|
-
}
|
|
94
|
-
if (!container.attract.finish) {
|
|
95
|
-
if (!container.attract.count) {
|
|
96
|
-
container.attract.count = 0;
|
|
97
|
-
}
|
|
98
|
-
container.attract.count++;
|
|
99
|
-
if (container.attract.count === container.particles.count) {
|
|
100
|
-
container.attract.finish = true;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (container.attract.clicking) {
|
|
104
|
-
const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
|
|
105
|
-
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
this.processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
|
|
109
|
-
}
|
|
110
|
-
else if (container.attract.clicking === false) {
|
|
111
|
-
container.attract.particles = [];
|
|
112
|
-
}
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
hoverAttract() {
|
|
116
|
-
const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
|
|
117
|
-
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
this.processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
|
|
121
|
-
}
|
|
122
|
-
processAttract(position, attractRadius, area) {
|
|
123
|
-
const container = this.container, attractOptions = container.actualOptions.interactivity.modes.attract;
|
|
124
|
-
if (!attractOptions) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
|
|
128
|
-
for (const particle of query) {
|
|
129
|
-
const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position);
|
|
130
|
-
const velocity = attractOptions.speed * attractOptions.factor;
|
|
131
|
-
const attractFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
|
|
132
|
-
const normVec = engine_1.Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
|
|
133
|
-
particle.position.subFrom(normVec);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
126
|
}
|
|
137
127
|
exports.Attractor = Attractor;
|
package/cjs/index.js
CHANGED
|
@@ -13,23 +13,12 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
13
13
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
17
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
18
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
19
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
20
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
21
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
22
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
17
|
exports.loadExternalAttractInteraction = void 0;
|
|
27
|
-
const
|
|
28
|
-
function loadExternalAttractInteraction(engine) {
|
|
29
|
-
|
|
30
|
-
yield engine.addInteractor("externalAttract", (container) => new Attractor_1.Attractor(engine, container));
|
|
31
|
-
});
|
|
18
|
+
const Attractor_js_1 = require("./Attractor.js");
|
|
19
|
+
async function loadExternalAttractInteraction(engine, refresh = true) {
|
|
20
|
+
await engine.addInteractor("externalAttract", (container) => new Attractor_js_1.Attractor(engine, container), refresh);
|
|
32
21
|
}
|
|
33
22
|
exports.loadExternalAttractInteraction = loadExternalAttractInteraction;
|
|
34
|
-
__exportStar(require("./Options/Classes/Attract"), exports);
|
|
35
|
-
__exportStar(require("./Options/Interfaces/IAttract"), exports);
|
|
23
|
+
__exportStar(require("./Options/Classes/Attract.js"), exports);
|
|
24
|
+
__exportStar(require("./Options/Interfaces/IAttract.js"), exports);
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "commonjs" }
|
package/esm/Attractor.js
CHANGED
|
@@ -1,8 +1,56 @@
|
|
|
1
1
|
import { Circle, ExternalInteractorBase, Vector, clamp, getDistances, getEasing, isInArray, mouseMoveEvent, } from "@tsparticles/engine";
|
|
2
|
-
import { Attract } from "./Options/Classes/Attract";
|
|
2
|
+
import { Attract } from "./Options/Classes/Attract.js";
|
|
3
3
|
export class Attractor extends ExternalInteractorBase {
|
|
4
4
|
constructor(engine, container) {
|
|
5
5
|
super(container);
|
|
6
|
+
this._clickAttract = () => {
|
|
7
|
+
const container = this.container;
|
|
8
|
+
if (!container.attract) {
|
|
9
|
+
container.attract = { particles: [] };
|
|
10
|
+
}
|
|
11
|
+
const { attract } = container;
|
|
12
|
+
if (!attract.finish) {
|
|
13
|
+
if (!attract.count) {
|
|
14
|
+
attract.count = 0;
|
|
15
|
+
}
|
|
16
|
+
attract.count++;
|
|
17
|
+
if (attract.count === container.particles.count) {
|
|
18
|
+
attract.finish = true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (attract.clicking) {
|
|
22
|
+
const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
|
|
23
|
+
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
27
|
+
}
|
|
28
|
+
else if (attract.clicking === false) {
|
|
29
|
+
attract.particles = [];
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
};
|
|
33
|
+
this._hoverAttract = () => {
|
|
34
|
+
const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
|
|
35
|
+
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
39
|
+
};
|
|
40
|
+
this._processAttract = (position, attractRadius, area) => {
|
|
41
|
+
const container = this.container, attractOptions = container.actualOptions.interactivity.modes.attract;
|
|
42
|
+
if (!attractOptions) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
|
|
46
|
+
for (const particle of query) {
|
|
47
|
+
const { dx, dy, distance } = getDistances(particle.position, position);
|
|
48
|
+
const velocity = attractOptions.speed * attractOptions.factor;
|
|
49
|
+
const attractFactor = clamp(getEasing(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
|
|
50
|
+
const normVec = Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
|
|
51
|
+
particle.position.subFrom(normVec);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
6
54
|
this._engine = engine;
|
|
7
55
|
if (!container.attract) {
|
|
8
56
|
container.attract = { particles: [] };
|
|
@@ -26,12 +74,13 @@ export class Attractor extends ExternalInteractorBase {
|
|
|
26
74
|
container.attract.particles = [];
|
|
27
75
|
container.attract.finish = false;
|
|
28
76
|
setTimeout(() => {
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
container.attract
|
|
77
|
+
if (container.destroyed) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (!container.attract) {
|
|
81
|
+
container.attract = { particles: [] };
|
|
34
82
|
}
|
|
83
|
+
container.attract.clicking = false;
|
|
35
84
|
}, attract.duration * 1000);
|
|
36
85
|
};
|
|
37
86
|
}
|
|
@@ -47,15 +96,14 @@ export class Attractor extends ExternalInteractorBase {
|
|
|
47
96
|
async interact() {
|
|
48
97
|
const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === mouseMoveEvent, events = options.interactivity.events, hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, clickEnabled = events.onClick.enable, clickMode = events.onClick.mode;
|
|
49
98
|
if (mouseMoveStatus && hoverEnabled && isInArray("attract", hoverMode)) {
|
|
50
|
-
this.
|
|
99
|
+
this._hoverAttract();
|
|
51
100
|
}
|
|
52
101
|
else if (clickEnabled && isInArray("attract", clickMode)) {
|
|
53
|
-
this.
|
|
102
|
+
this._clickAttract();
|
|
54
103
|
}
|
|
55
104
|
}
|
|
56
105
|
isEnabled(particle) {
|
|
57
|
-
|
|
58
|
-
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events;
|
|
106
|
+
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events;
|
|
59
107
|
if ((!mouse.position || !events.onHover.enable) && (!mouse.clickPosition || !events.onClick.enable)) {
|
|
60
108
|
return false;
|
|
61
109
|
}
|
|
@@ -67,56 +115,9 @@ export class Attractor extends ExternalInteractorBase {
|
|
|
67
115
|
options.attract = new Attract();
|
|
68
116
|
}
|
|
69
117
|
for (const source of sources) {
|
|
70
|
-
options.attract.load(source
|
|
118
|
+
options.attract.load(source?.attract);
|
|
71
119
|
}
|
|
72
120
|
}
|
|
73
121
|
reset() {
|
|
74
122
|
}
|
|
75
|
-
clickAttract() {
|
|
76
|
-
const container = this.container;
|
|
77
|
-
if (!container.attract) {
|
|
78
|
-
container.attract = { particles: [] };
|
|
79
|
-
}
|
|
80
|
-
if (!container.attract.finish) {
|
|
81
|
-
if (!container.attract.count) {
|
|
82
|
-
container.attract.count = 0;
|
|
83
|
-
}
|
|
84
|
-
container.attract.count++;
|
|
85
|
-
if (container.attract.count === container.particles.count) {
|
|
86
|
-
container.attract.finish = true;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (container.attract.clicking) {
|
|
90
|
-
const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
|
|
91
|
-
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
this.processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
95
|
-
}
|
|
96
|
-
else if (container.attract.clicking === false) {
|
|
97
|
-
container.attract.particles = [];
|
|
98
|
-
}
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
hoverAttract() {
|
|
102
|
-
const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
|
|
103
|
-
if (!attractRadius || attractRadius < 0 || !mousePos) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
this.processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
|
|
107
|
-
}
|
|
108
|
-
processAttract(position, attractRadius, area) {
|
|
109
|
-
const container = this.container, attractOptions = container.actualOptions.interactivity.modes.attract;
|
|
110
|
-
if (!attractOptions) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
|
|
114
|
-
for (const particle of query) {
|
|
115
|
-
const { dx, dy, distance } = getDistances(particle.position, position);
|
|
116
|
-
const velocity = attractOptions.speed * attractOptions.factor;
|
|
117
|
-
const attractFactor = clamp(getEasing(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
|
|
118
|
-
const normVec = Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
|
|
119
|
-
particle.position.subFrom(normVec);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
123
|
}
|
package/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Attractor } from "./Attractor";
|
|
2
|
-
export async function loadExternalAttractInteraction(engine) {
|
|
3
|
-
await engine.addInteractor("externalAttract", (container) => new Attractor(engine, container));
|
|
1
|
+
import { Attractor } from "./Attractor.js";
|
|
2
|
+
export async function loadExternalAttractInteraction(engine, refresh = true) {
|
|
3
|
+
await engine.addInteractor("externalAttract", (container) => new Attractor(engine, container), refresh);
|
|
4
4
|
}
|
|
5
|
-
export * from "./Options/Classes/Attract";
|
|
6
|
-
export * from "./Options/Interfaces/IAttract";
|
|
5
|
+
export * from "./Options/Classes/Attract.js";
|
|
6
|
+
export * from "./Options/Interfaces/IAttract.js";
|
package/esm/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "module" }
|