@tsparticles/interaction-external-attract 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { Circle, ExternalInteractorBase, Vector, clamp, getDistances, getEasing, isInArray, mouseMoveEvent, } from "@tsparticles/engine";
1
+ import { Circle, ExternalInteractorBase, Vector, clamp, getDistances, getEasing, isInArray, millisecondsToSeconds, mouseMoveEvent, } from "@tsparticles/engine";
2
2
  import { Attract } from "./Options/Classes/Attract.js";
3
- const attractMode = "attract";
3
+ const attractMode = "attract", minRadius = 0, minFactor = 1, identity = 1;
4
4
  export class Attractor extends ExternalInteractorBase {
5
5
  constructor(engine, container) {
6
6
  super(container);
@@ -21,7 +21,7 @@ export class Attractor extends ExternalInteractorBase {
21
21
  }
22
22
  if (attract.clicking) {
23
23
  const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
24
- if (!attractRadius || attractRadius < 0 || !mousePos) {
24
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
25
25
  return;
26
26
  }
27
27
  this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
@@ -29,11 +29,10 @@ export class Attractor extends ExternalInteractorBase {
29
29
  else if (attract.clicking === false) {
30
30
  attract.particles = [];
31
31
  }
32
- return;
33
32
  };
34
33
  this._hoverAttract = () => {
35
34
  const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
36
- if (!attractRadius || attractRadius < 0 || !mousePos) {
35
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
37
36
  return;
38
37
  }
39
38
  this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
@@ -45,10 +44,7 @@ export class Attractor extends ExternalInteractorBase {
45
44
  }
46
45
  const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
47
46
  for (const particle of query) {
48
- const { dx, dy, distance } = getDistances(particle.position, position);
49
- const velocity = attractOptions.speed * attractOptions.factor;
50
- const attractFactor = clamp(getEasing(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
51
- const normVec = Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
47
+ const { dx, dy, distance } = getDistances(particle.position, position), velocity = attractOptions.speed * attractOptions.factor, attractFactor = clamp(getEasing(attractOptions.easing)(identity - distance / attractRadius) * velocity, minFactor, attractOptions.maxSpeed), normVec = Vector.create(!distance ? velocity : (dx / distance) * attractFactor, !distance ? velocity : (dy / distance) * attractFactor);
52
48
  particle.position.subFrom(normVec);
53
49
  }
54
50
  };
@@ -82,7 +78,7 @@ export class Attractor extends ExternalInteractorBase {
82
78
  container.attract = { particles: [] };
83
79
  }
84
80
  container.attract.clicking = false;
85
- }, attract.duration * 1000);
81
+ }, attract.duration * millisecondsToSeconds);
86
82
  };
87
83
  }
88
84
  clear() {
@@ -102,6 +98,7 @@ export class Attractor extends ExternalInteractorBase {
102
98
  else if (clickEnabled && isInArray(attractMode, clickMode)) {
103
99
  this._clickAttract();
104
100
  }
101
+ await Promise.resolve();
105
102
  }
106
103
  isEnabled(particle) {
107
104
  const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events;
package/cjs/Attractor.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Attractor = void 0;
4
4
  const engine_1 = require("@tsparticles/engine");
5
5
  const Attract_js_1 = require("./Options/Classes/Attract.js");
6
- const attractMode = "attract";
6
+ const attractMode = "attract", minRadius = 0, minFactor = 1, identity = 1;
7
7
  class Attractor extends engine_1.ExternalInteractorBase {
8
8
  constructor(engine, container) {
9
9
  super(container);
@@ -24,7 +24,7 @@ class Attractor extends engine_1.ExternalInteractorBase {
24
24
  }
25
25
  if (attract.clicking) {
26
26
  const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
27
- if (!attractRadius || attractRadius < 0 || !mousePos) {
27
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
28
28
  return;
29
29
  }
30
30
  this._processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
@@ -32,11 +32,10 @@ class Attractor extends engine_1.ExternalInteractorBase {
32
32
  else if (attract.clicking === false) {
33
33
  attract.particles = [];
34
34
  }
35
- return;
36
35
  };
37
36
  this._hoverAttract = () => {
38
37
  const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
39
- if (!attractRadius || attractRadius < 0 || !mousePos) {
38
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
40
39
  return;
41
40
  }
42
41
  this._processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
@@ -48,10 +47,7 @@ class Attractor extends engine_1.ExternalInteractorBase {
48
47
  }
49
48
  const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
50
49
  for (const particle of query) {
51
- const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position);
52
- const velocity = attractOptions.speed * attractOptions.factor;
53
- const attractFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
54
- const normVec = engine_1.Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
50
+ const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position), velocity = attractOptions.speed * attractOptions.factor, attractFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(attractOptions.easing)(identity - distance / attractRadius) * velocity, minFactor, attractOptions.maxSpeed), normVec = engine_1.Vector.create(!distance ? velocity : (dx / distance) * attractFactor, !distance ? velocity : (dy / distance) * attractFactor);
55
51
  particle.position.subFrom(normVec);
56
52
  }
57
53
  };
@@ -85,7 +81,7 @@ class Attractor extends engine_1.ExternalInteractorBase {
85
81
  container.attract = { particles: [] };
86
82
  }
87
83
  container.attract.clicking = false;
88
- }, attract.duration * 1000);
84
+ }, attract.duration * engine_1.millisecondsToSeconds);
89
85
  };
90
86
  }
91
87
  clear() {
@@ -105,6 +101,7 @@ class Attractor extends engine_1.ExternalInteractorBase {
105
101
  else if (clickEnabled && (0, engine_1.isInArray)(attractMode, clickMode)) {
106
102
  this._clickAttract();
107
103
  }
104
+ await Promise.resolve();
108
105
  }
109
106
  isEnabled(particle) {
110
107
  const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events;
package/esm/Attractor.js CHANGED
@@ -1,6 +1,6 @@
1
- import { Circle, ExternalInteractorBase, Vector, clamp, getDistances, getEasing, isInArray, mouseMoveEvent, } from "@tsparticles/engine";
1
+ import { Circle, ExternalInteractorBase, Vector, clamp, getDistances, getEasing, isInArray, millisecondsToSeconds, mouseMoveEvent, } from "@tsparticles/engine";
2
2
  import { Attract } from "./Options/Classes/Attract.js";
3
- const attractMode = "attract";
3
+ const attractMode = "attract", minRadius = 0, minFactor = 1, identity = 1;
4
4
  export class Attractor extends ExternalInteractorBase {
5
5
  constructor(engine, container) {
6
6
  super(container);
@@ -21,7 +21,7 @@ export class Attractor extends ExternalInteractorBase {
21
21
  }
22
22
  if (attract.clicking) {
23
23
  const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
24
- if (!attractRadius || attractRadius < 0 || !mousePos) {
24
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
25
25
  return;
26
26
  }
27
27
  this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
@@ -29,11 +29,10 @@ export class Attractor extends ExternalInteractorBase {
29
29
  else if (attract.clicking === false) {
30
30
  attract.particles = [];
31
31
  }
32
- return;
33
32
  };
34
33
  this._hoverAttract = () => {
35
34
  const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
36
- if (!attractRadius || attractRadius < 0 || !mousePos) {
35
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
37
36
  return;
38
37
  }
39
38
  this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
@@ -45,10 +44,7 @@ export class Attractor extends ExternalInteractorBase {
45
44
  }
46
45
  const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
47
46
  for (const particle of query) {
48
- const { dx, dy, distance } = getDistances(particle.position, position);
49
- const velocity = attractOptions.speed * attractOptions.factor;
50
- const attractFactor = clamp(getEasing(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
51
- const normVec = Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
47
+ const { dx, dy, distance } = getDistances(particle.position, position), velocity = attractOptions.speed * attractOptions.factor, attractFactor = clamp(getEasing(attractOptions.easing)(identity - distance / attractRadius) * velocity, minFactor, attractOptions.maxSpeed), normVec = Vector.create(!distance ? velocity : (dx / distance) * attractFactor, !distance ? velocity : (dy / distance) * attractFactor);
52
48
  particle.position.subFrom(normVec);
53
49
  }
54
50
  };
@@ -82,7 +78,7 @@ export class Attractor extends ExternalInteractorBase {
82
78
  container.attract = { particles: [] };
83
79
  }
84
80
  container.attract.clicking = false;
85
- }, attract.duration * 1000);
81
+ }, attract.duration * millisecondsToSeconds);
86
82
  };
87
83
  }
88
84
  clear() {
@@ -102,6 +98,7 @@ export class Attractor extends ExternalInteractorBase {
102
98
  else if (clickEnabled && isInArray(attractMode, clickMode)) {
103
99
  this._clickAttract();
104
100
  }
101
+ await Promise.resolve();
105
102
  }
106
103
  isEnabled(particle) {
107
104
  const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/interaction-external-attract",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "tsParticles attract external interaction",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -87,7 +87,7 @@
87
87
  "./package.json": "./package.json"
88
88
  },
89
89
  "dependencies": {
90
- "@tsparticles/engine": "^3.0.2"
90
+ "@tsparticles/engine": "^3.1.0"
91
91
  },
92
92
  "publishConfig": {
93
93
  "access": "public"
package/report.html CHANGED
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8"/>
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
6
- <title>@tsparticles/interaction-external-attract [6 Dec 2023 at 17:39]</title>
6
+ <title>@tsparticles/interaction-external-attract [13 Jan 2024 at 22:59]</title>
7
7
  <link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" />
8
8
 
9
9
  <script>
@@ -31,7 +31,7 @@
31
31
  <body>
32
32
  <div id="app"></div>
33
33
  <script>
34
- window.chartData = [{"label":"tsparticles.interaction.external.attract.js","isAsset":true,"statSize":6351,"parsedSize":10296,"gzipSize":2710,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":6309,"groups":[{"id":559,"label":"index.js + 2 modules (concatenated)","path":"./dist/browser/index.js + 2 modules (concatenated)","statSize":6309,"parsedSize":10296,"gzipSize":2710,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser","statSize":6309,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/index.js","statSize":325,"parsedSize":530,"gzipSize":139,"inaccurateSizes":true},{"id":null,"label":"Attractor.js","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/Attractor.js","statSize":5261,"parsedSize":8585,"gzipSize":2259,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/Options/Classes","statSize":723,"groups":[{"id":null,"label":"Attract.js","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/Options/Classes/Attract.js","statSize":723,"parsedSize":1179,"gzipSize":310,"inaccurateSizes":true}],"parsedSize":1179,"gzipSize":310,"inaccurateSizes":true}],"parsedSize":10296,"gzipSize":2710,"inaccurateSizes":true}]}],"parsedSize":10296,"gzipSize":2710},{"label":"engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":533,"label":"engine\",\"root\":\"window\"}","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles/engine\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.interaction.external.attract":true}}];
34
+ window.chartData = [{"label":"tsparticles.interaction.external.attract.js","isAsset":true,"statSize":6473,"parsedSize":10415,"gzipSize":2756,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":6431,"groups":[{"id":212,"label":"index.js + 2 modules (concatenated)","path":"./dist/browser/index.js + 2 modules (concatenated)","statSize":6431,"parsedSize":10415,"gzipSize":2756,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser","statSize":6431,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/index.js","statSize":325,"parsedSize":526,"gzipSize":139,"inaccurateSizes":true},{"id":null,"label":"Attractor.js","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/Attractor.js","statSize":5383,"parsedSize":8717,"gzipSize":2306,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/Options/Classes","statSize":723,"groups":[{"id":null,"label":"Attract.js","path":"./dist/browser/index.js + 2 modules (concatenated)/dist/browser/Options/Classes/Attract.js","statSize":723,"parsedSize":1170,"gzipSize":309,"inaccurateSizes":true}],"parsedSize":1170,"gzipSize":309,"inaccurateSizes":true}],"parsedSize":10415,"gzipSize":2756,"inaccurateSizes":true}]}],"parsedSize":10415,"gzipSize":2756},{"label":"engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":533,"label":"engine\",\"root\":\"window\"}","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles/engine\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.interaction.external.attract":true}}];
35
35
  window.entrypoints = ["tsparticles.interaction.external.attract","tsparticles.interaction.external.attract.min"];
36
36
  window.defaultSizes = "parsed";
37
37
  </script>
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v3.0.2
7
+ * v3.1.0
8
8
  */
9
9
  (function webpackUniversalModuleDefinition(root, factory) {
10
10
  if(typeof exports === 'object' && typeof module === 'object')
@@ -134,7 +134,10 @@ class Attract {
134
134
  ;// CONCATENATED MODULE: ./dist/browser/Attractor.js
135
135
 
136
136
 
137
- const attractMode = "attract";
137
+ const attractMode = "attract",
138
+ minRadius = 0,
139
+ minFactor = 1,
140
+ identity = 1;
138
141
  class Attractor extends engine_root_window_.ExternalInteractorBase {
139
142
  constructor(engine, container) {
140
143
  super(container);
@@ -160,20 +163,19 @@ class Attractor extends engine_root_window_.ExternalInteractorBase {
160
163
  if (attract.clicking) {
161
164
  const mousePos = container.interactivity.mouse.clickPosition,
162
165
  attractRadius = container.retina.attractModeDistance;
163
- if (!attractRadius || attractRadius < 0 || !mousePos) {
166
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
164
167
  return;
165
168
  }
166
169
  this._processAttract(mousePos, attractRadius, new engine_root_window_.Circle(mousePos.x, mousePos.y, attractRadius));
167
170
  } else if (attract.clicking === false) {
168
171
  attract.particles = [];
169
172
  }
170
- return;
171
173
  };
172
174
  this._hoverAttract = () => {
173
175
  const container = this.container,
174
176
  mousePos = container.interactivity.mouse.position,
175
177
  attractRadius = container.retina.attractModeDistance;
176
- if (!attractRadius || attractRadius < 0 || !mousePos) {
178
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
177
179
  return;
178
180
  }
179
181
  this._processAttract(mousePos, attractRadius, new engine_root_window_.Circle(mousePos.x, mousePos.y, attractRadius));
@@ -187,13 +189,13 @@ class Attractor extends engine_root_window_.ExternalInteractorBase {
187
189
  const query = container.particles.quadTree.query(area, p => this.isEnabled(p));
188
190
  for (const particle of query) {
189
191
  const {
190
- dx,
191
- dy,
192
- distance
193
- } = (0,engine_root_window_.getDistances)(particle.position, position);
194
- const velocity = attractOptions.speed * attractOptions.factor;
195
- const attractFactor = (0,engine_root_window_.clamp)((0,engine_root_window_.getEasing)(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
196
- const normVec = engine_root_window_.Vector.create(distance === 0 ? velocity : dx / distance * attractFactor, distance === 0 ? velocity : dy / distance * attractFactor);
192
+ dx,
193
+ dy,
194
+ distance
195
+ } = (0,engine_root_window_.getDistances)(particle.position, position),
196
+ velocity = attractOptions.speed * attractOptions.factor,
197
+ attractFactor = (0,engine_root_window_.clamp)((0,engine_root_window_.getEasing)(attractOptions.easing)(identity - distance / attractRadius) * velocity, minFactor, attractOptions.maxSpeed),
198
+ normVec = engine_root_window_.Vector.create(!distance ? velocity : dx / distance * attractFactor, !distance ? velocity : dy / distance * attractFactor);
197
199
  particle.position.subFrom(normVec);
198
200
  }
199
201
  };
@@ -234,7 +236,7 @@ class Attractor extends engine_root_window_.ExternalInteractorBase {
234
236
  };
235
237
  }
236
238
  container.attract.clicking = false;
237
- }, attract.duration * 1000);
239
+ }, attract.duration * engine_root_window_.millisecondsToSeconds);
238
240
  };
239
241
  }
240
242
  clear() {}
@@ -260,6 +262,7 @@ class Attractor extends engine_root_window_.ExternalInteractorBase {
260
262
  } else if (clickEnabled && (0,engine_root_window_.isInArray)(attractMode, clickMode)) {
261
263
  this._clickAttract();
262
264
  }
265
+ await Promise.resolve();
263
266
  }
264
267
  isEnabled(particle) {
265
268
  const container = this.container,
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see tsparticles.interaction.external.attract.min.js.LICENSE.txt */
2
- !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/engine")):e(t.window);for(var a in i)("object"==typeof exports?exports:t)[a]=i[a]}}(this,(t=>(()=>{"use strict";var e={533:e=>{e.exports=t}},i={};function a(t){var r=i[t];if(void 0!==r)return r.exports;var n=i[t]={exports:{}};return e[t](n,n.exports,a),n.exports}a.d=(t,e)=>{for(var i in e)a.o(e,i)&&!a.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},a.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),a.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var r={};return(()=>{a.r(r),a.d(r,{Attract:()=>e,loadExternalAttractInteraction:()=>o});var t=a(533);class e{constructor(){this.distance=200,this.duration=.4,this.easing="ease-out-quad",this.factor=1,this.maxSpeed=50,this.speed=1}load(t){t&&(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.easing&&(this.easing=t.easing),void 0!==t.factor&&(this.factor=t.factor),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed),void 0!==t.speed&&(this.speed=t.speed))}}const i="attract";class n extends t.ExternalInteractorBase{constructor(e,a){super(a),this._clickAttract=()=>{const e=this.container;e.attract||(e.attract={particles:[]});const{attract:i}=e;if(i.finish||(i.count||(i.count=0),i.count++,i.count===e.particles.count&&(i.finish=!0)),i.clicking){const i=e.interactivity.mouse.clickPosition,a=e.retina.attractModeDistance;if(!a||a<0||!i)return;this._processAttract(i,a,new t.Circle(i.x,i.y,a))}else!1===i.clicking&&(i.particles=[])},this._hoverAttract=()=>{const e=this.container,i=e.interactivity.mouse.position,a=e.retina.attractModeDistance;!a||a<0||!i||this._processAttract(i,a,new t.Circle(i.x,i.y,a))},this._processAttract=(e,i,a)=>{const r=this.container,n=r.actualOptions.interactivity.modes.attract;if(!n)return;const o=r.particles.quadTree.query(a,(t=>this.isEnabled(t)));for(const a of o){const{dx:r,dy:o,distance:c}=(0,t.getDistances)(a.position,e),s=n.speed*n.factor,d=(0,t.clamp)((0,t.getEasing)(n.easing)(1-c/i)*s,0,n.maxSpeed),l=t.Vector.create(0===c?s:r/c*d,0===c?s:o/c*d);a.position.subFrom(l)}},this._engine=e,a.attract||(a.attract={particles:[]}),this.handleClickMode=t=>{const e=this.container.actualOptions.interactivity.modes.attract;if(e&&t===i){a.attract||(a.attract={particles:[]}),a.attract.clicking=!0,a.attract.count=0;for(const t of a.attract.particles)this.isEnabled(t)&&t.velocity.setTo(t.initialVelocity);a.attract.particles=[],a.attract.finish=!1,setTimeout((()=>{a.destroyed||(a.attract||(a.attract={particles:[]}),a.attract.clicking=!1)}),1e3*e.duration)}}}clear(){}init(){const t=this.container,e=t.actualOptions.interactivity.modes.attract;e&&(t.retina.attractModeDistance=e.distance*t.retina.pixelRatio)}async interact(){const e=this.container,a=e.actualOptions,r=e.interactivity.status===t.mouseMoveEvent,n=a.interactivity.events,o=n.onHover.enable,c=n.onHover.mode,s=n.onClick.enable,d=n.onClick.mode;r&&o&&(0,t.isInArray)(i,c)?this._hoverAttract():s&&(0,t.isInArray)(i,d)&&this._clickAttract()}isEnabled(e){const a=this.container,r=a.actualOptions,n=a.interactivity.mouse,o=(e?.interactivity??r.interactivity).events;if(!(n.position&&o.onHover.enable||n.clickPosition&&o.onClick.enable))return!1;const c=o.onHover.mode,s=o.onClick.mode;return(0,t.isInArray)(i,c)||(0,t.isInArray)(i,s)}loadModeOptions(t,...i){t.attract||(t.attract=new e);for(const e of i)t.attract.load(e?.attract)}reset(){}}async function o(t,e=!0){await t.addInteractor("externalAttract",(e=>new n(t,e)),e)}})(),r})()));
2
+ !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/engine")):e(t.window);for(var a in i)("object"==typeof exports?exports:t)[a]=i[a]}}(this,(t=>(()=>{"use strict";var e={533:e=>{e.exports=t}},i={};function a(t){var r=i[t];if(void 0!==r)return r.exports;var o=i[t]={exports:{}};return e[t](o,o.exports,a),o.exports}a.d=(t,e)=>{for(var i in e)a.o(e,i)&&!a.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},a.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),a.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var r={};return(()=>{a.r(r),a.d(r,{Attract:()=>e,loadExternalAttractInteraction:()=>n});var t=a(533);class e{constructor(){this.distance=200,this.duration=.4,this.easing="ease-out-quad",this.factor=1,this.maxSpeed=50,this.speed=1}load(t){t&&(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.easing&&(this.easing=t.easing),void 0!==t.factor&&(this.factor=t.factor),void 0!==t.maxSpeed&&(this.maxSpeed=t.maxSpeed),void 0!==t.speed&&(this.speed=t.speed))}}const i="attract";class o extends t.ExternalInteractorBase{constructor(e,a){super(a),this._clickAttract=()=>{const e=this.container;e.attract||(e.attract={particles:[]});const{attract:i}=e;if(i.finish||(i.count||(i.count=0),i.count++,i.count===e.particles.count&&(i.finish=!0)),i.clicking){const i=e.interactivity.mouse.clickPosition,a=e.retina.attractModeDistance;if(!a||a<0||!i)return;this._processAttract(i,a,new t.Circle(i.x,i.y,a))}else!1===i.clicking&&(i.particles=[])},this._hoverAttract=()=>{const e=this.container,i=e.interactivity.mouse.position,a=e.retina.attractModeDistance;!a||a<0||!i||this._processAttract(i,a,new t.Circle(i.x,i.y,a))},this._processAttract=(e,i,a)=>{const r=this.container,o=r.actualOptions.interactivity.modes.attract;if(!o)return;const n=r.particles.quadTree.query(a,(t=>this.isEnabled(t)));for(const a of n){const{dx:r,dy:n,distance:c}=(0,t.getDistances)(a.position,e),s=o.speed*o.factor,d=(0,t.clamp)((0,t.getEasing)(o.easing)(1-c/i)*s,1,o.maxSpeed),l=t.Vector.create(c?r/c*d:s,c?n/c*d:s);a.position.subFrom(l)}},this._engine=e,a.attract||(a.attract={particles:[]}),this.handleClickMode=e=>{const r=this.container.actualOptions.interactivity.modes.attract;if(r&&e===i){a.attract||(a.attract={particles:[]}),a.attract.clicking=!0,a.attract.count=0;for(const t of a.attract.particles)this.isEnabled(t)&&t.velocity.setTo(t.initialVelocity);a.attract.particles=[],a.attract.finish=!1,setTimeout((()=>{a.destroyed||(a.attract||(a.attract={particles:[]}),a.attract.clicking=!1)}),r.duration*t.millisecondsToSeconds)}}}clear(){}init(){const t=this.container,e=t.actualOptions.interactivity.modes.attract;e&&(t.retina.attractModeDistance=e.distance*t.retina.pixelRatio)}async interact(){const e=this.container,a=e.actualOptions,r=e.interactivity.status===t.mouseMoveEvent,o=a.interactivity.events,n=o.onHover.enable,c=o.onHover.mode,s=o.onClick.enable,d=o.onClick.mode;r&&n&&(0,t.isInArray)(i,c)?this._hoverAttract():s&&(0,t.isInArray)(i,d)&&this._clickAttract(),await Promise.resolve()}isEnabled(e){const a=this.container,r=a.actualOptions,o=a.interactivity.mouse,n=(e?.interactivity??r.interactivity).events;if(!(o.position&&n.onHover.enable||o.clickPosition&&n.onClick.enable))return!1;const c=n.onHover.mode,s=n.onClick.mode;return(0,t.isInArray)(i,c)||(0,t.isInArray)(i,s)}loadModeOptions(t,...i){t.attract||(t.attract=new e);for(const e of i)t.attract.load(e?.attract)}reset(){}}async function n(t,e=!0){await t.addInteractor("externalAttract",(e=>new o(t,e)),e)}})(),r})()));
@@ -1 +1 @@
1
- /*! tsParticles Attract External Interaction v3.0.2 by Matteo Bruni */
1
+ /*! tsParticles Attract External Interaction v3.1.0 by Matteo Bruni */
package/types/Types.d.ts CHANGED
@@ -2,12 +2,12 @@ import type { Container, Particle } from "@tsparticles/engine";
2
2
  import type { Attract } from "./Options/Classes/Attract.js";
3
3
  import type { AttractOptions } from "./Options/Classes/AttractOptions.js";
4
4
  import type { IAttract } from "./Options/Interfaces/IAttract.js";
5
- export type IAttractMode = {
5
+ export interface IAttractMode {
6
6
  attract: IAttract;
7
- };
8
- export type AttractMode = {
7
+ }
8
+ export interface AttractMode {
9
9
  attract?: Attract;
10
- };
10
+ }
11
11
  interface IContainerAttract {
12
12
  clicking?: boolean;
13
13
  count?: number;
package/umd/Attractor.js CHANGED
@@ -12,7 +12,7 @@
12
12
  exports.Attractor = void 0;
13
13
  const engine_1 = require("@tsparticles/engine");
14
14
  const Attract_js_1 = require("./Options/Classes/Attract.js");
15
- const attractMode = "attract";
15
+ const attractMode = "attract", minRadius = 0, minFactor = 1, identity = 1;
16
16
  class Attractor extends engine_1.ExternalInteractorBase {
17
17
  constructor(engine, container) {
18
18
  super(container);
@@ -33,7 +33,7 @@
33
33
  }
34
34
  if (attract.clicking) {
35
35
  const mousePos = container.interactivity.mouse.clickPosition, attractRadius = container.retina.attractModeDistance;
36
- if (!attractRadius || attractRadius < 0 || !mousePos) {
36
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
37
37
  return;
38
38
  }
39
39
  this._processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
@@ -41,11 +41,10 @@
41
41
  else if (attract.clicking === false) {
42
42
  attract.particles = [];
43
43
  }
44
- return;
45
44
  };
46
45
  this._hoverAttract = () => {
47
46
  const container = this.container, mousePos = container.interactivity.mouse.position, attractRadius = container.retina.attractModeDistance;
48
- if (!attractRadius || attractRadius < 0 || !mousePos) {
47
+ if (!attractRadius || attractRadius < minRadius || !mousePos) {
49
48
  return;
50
49
  }
51
50
  this._processAttract(mousePos, attractRadius, new engine_1.Circle(mousePos.x, mousePos.y, attractRadius));
@@ -57,10 +56,7 @@
57
56
  }
58
57
  const query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
59
58
  for (const particle of query) {
60
- const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position);
61
- const velocity = attractOptions.speed * attractOptions.factor;
62
- const attractFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
63
- const normVec = engine_1.Vector.create(distance === 0 ? velocity : (dx / distance) * attractFactor, distance === 0 ? velocity : (dy / distance) * attractFactor);
59
+ const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position), velocity = attractOptions.speed * attractOptions.factor, attractFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(attractOptions.easing)(identity - distance / attractRadius) * velocity, minFactor, attractOptions.maxSpeed), normVec = engine_1.Vector.create(!distance ? velocity : (dx / distance) * attractFactor, !distance ? velocity : (dy / distance) * attractFactor);
64
60
  particle.position.subFrom(normVec);
65
61
  }
66
62
  };
@@ -94,7 +90,7 @@
94
90
  container.attract = { particles: [] };
95
91
  }
96
92
  container.attract.clicking = false;
97
- }, attract.duration * 1000);
93
+ }, attract.duration * engine_1.millisecondsToSeconds);
98
94
  };
99
95
  }
100
96
  clear() {
@@ -114,6 +110,7 @@
114
110
  else if (clickEnabled && (0, engine_1.isInArray)(attractMode, clickMode)) {
115
111
  this._clickAttract();
116
112
  }
113
+ await Promise.resolve();
117
114
  }
118
115
  isEnabled(particle) {
119
116
  const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events;