@tsparticles/interaction-external-repulse 4.0.0-alpha.24 → 4.0.0-alpha.26

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/504.min.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";(this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[]).push([[504],{504(e,t,i){i.d(t,{Repulser:()=>c});var s=i(303),n=i(702),l=i(686);let r="repulse";class c extends n.ExternalInteractorBase{handleClickMode;_clickVec;_engine;_maxDistance;_normVec;constructor(e,t){super(t),this._engine=e,this._maxDistance=0,this._normVec=s.Vector.origin,this._clickVec=s.Vector.origin,t.repulse??={particles:[]},this.handleClickMode=(e,i)=>{let n=this.container.actualOptions,l=n.interactivity?.modes.repulse;if(!l||e!==r)return;t.repulse??={particles:[]};let c=t.repulse;for(let e of(c.clicking=!0,c.count=0,t.repulse.particles))this.isEnabled(i,e)&&e.velocity.setTo(e.initialVelocity);c.particles=[],c.finish=!1,setTimeout(()=>{t.destroyed||(c.clicking=!1)},l.duration*s.millisecondsToSeconds)}}get maxDistance(){return this._maxDistance}clear(){}init(){let e=this.container,t=e.actualOptions.interactivity?.modes.repulse;t&&(this._maxDistance=t.distance,e.retina.repulseModeDistance=t.distance*e.retina.pixelRatio)}interact(e){let t=this.container.actualOptions,i=e.status===n.mouseMoveEvent,l=t.interactivity?.events;if(!l)return;let c=l.onHover,o=c.enable,a=c.mode,p=l.onClick,u=p.enable,h=p.mode,d=l.onDiv;i&&o&&(0,s.isInArray)(r,a)?this._hoverRepulse(e):u&&(0,s.isInArray)(r,h)?this._clickRepulse(e):(0,n.divModeExecute)(r,d,(t,i)=>{this._singleSelectorRepulse(e,t,i)})}isEnabled(e,t){let i=this.container.actualOptions,l=e.mouse,c=(t?.interactivity??i.interactivity)?.events;if(!c)return!1;let o=c.onDiv,a=c.onHover,p=c.onClick,u=(0,n.isDivModeEnabled)(r,o);if(!(u||a.enable&&l.position||p.enable&&l.clickPosition))return!1;let h=a.mode,d=p.mode;return(0,s.isInArray)(r,h)||(0,s.isInArray)(r,d)||u}loadModeOptions(e,...t){for(let i of(e.repulse??=new l.Z,t))e.repulse.load(i?.repulse)}reset(){}_clickRepulse=e=>{let t=this.container,i=t.actualOptions.interactivity?.modes.repulse;if(!i)return;let n=t.repulse??{particles:[]};if(n.finish||(n.count??=0,n.count++,n.count===t.particles.count&&(n.finish=!0)),n.clicking){let l=t.retina.repulseModeDistance;if(!l||l<0)return;let r=Math.pow(l/6,3),c=e.mouse.clickPosition;if(void 0===c)return;let o=new s.Circle(c.x,c.y,r);for(let l of t.particles.grid.query(o,t=>this.isEnabled(e,t))){let{dx:e,dy:t,distance:o}=(0,s.getDistances)(c,l.position),a=o**2,p=-r*i.speed/a;a<=r&&(n.particles.push(l),this._clickVec.x=e,this._clickVec.y=t,this._clickVec.length=p,l.velocity.setTo(this._clickVec))}}else if(!1===n.clicking){for(let e of n.particles)e.velocity.setTo(e.initialVelocity);n.particles=[]}};_hoverRepulse=e=>{let t=this.container,i=e.mouse.position,n=t.retina.repulseModeDistance;n&&!(n<0)&&i&&this._processRepulse(e,i,n,new s.Circle(i.x,i.y,n))};_processRepulse=(e,t,i,n,l)=>{let r=this.container,c=r.particles.grid.query(n,t=>this.isEnabled(e,t)),o=r.actualOptions.interactivity?.modes.repulse;if(!o)return;let{easing:a,speed:p,factor:u,maxSpeed:h}=o,d=this._engine.getEasing(a),f=(l?.speed??p)*u;for(let e of c){let{dx:n,dy:l,distance:r}=(0,s.getDistances)(e.position,t),c=(0,s.clamp)(d(1-r/i)*f,0,h);this._normVec.x=r?n/r*c:f,this._normVec.y=r?l/r*c:f,e.position.addTo(this._normVec)}};_singleSelectorRepulse=(e,t,i)=>{let l=this.container,r=l.actualOptions.interactivity?.modes.repulse;if(!r)return;let c=(0,s.safeDocument)().querySelectorAll(t);c.length&&c.forEach(t=>{let c=l.retina.pixelRatio,o={x:(t.offsetLeft+t.offsetWidth*s.half)*c,y:(t.offsetTop+t.offsetHeight*s.half)*c},a=t.offsetWidth*s.half*c,p=i.type===n.DivType.circle?new s.Circle(o.x,o.y,a):new s.Rectangle(t.offsetLeft*c,t.offsetTop*c,t.offsetWidth*c,t.offsetHeight*c),u=r.divs,h=(0,n.divMode)(u,t);this._processRepulse(e,o,a,p,h)})}}}}]);
@@ -4,10 +4,16 @@ import { Repulse } from "./Options/Classes/Repulse.js";
4
4
  const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
5
5
  export class Repulser extends ExternalInteractorBase {
6
6
  handleClickMode;
7
+ _clickVec;
7
8
  _engine;
9
+ _maxDistance;
10
+ _normVec;
8
11
  constructor(engine, container) {
9
12
  super(container);
10
13
  this._engine = engine;
14
+ this._maxDistance = 0;
15
+ this._normVec = Vector.origin;
16
+ this._clickVec = Vector.origin;
11
17
  container.repulse ??= { particles: [] };
12
18
  this.handleClickMode = (mode, interactivityData) => {
13
19
  const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
@@ -34,6 +40,9 @@ export class Repulser extends ExternalInteractorBase {
34
40
  }, repulseOpts.duration * millisecondsToSeconds);
35
41
  };
36
42
  }
43
+ get maxDistance() {
44
+ return this._maxDistance;
45
+ }
37
46
  clear() {
38
47
  }
39
48
  init() {
@@ -41,6 +50,7 @@ export class Repulser extends ExternalInteractorBase {
41
50
  if (!repulse) {
42
51
  return;
43
52
  }
53
+ this._maxDistance = repulse.distance;
44
54
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
45
55
  }
46
56
  interact(interactivityData) {
@@ -103,14 +113,15 @@ export class Repulser extends ExternalInteractorBase {
103
113
  if (mouseClickPos === undefined) {
104
114
  return;
105
115
  }
106
- const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
116
+ const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.grid.query(range, p => this.isEnabled(interactivityData, p));
107
117
  for (const particle of query) {
108
118
  const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
109
119
  if (d <= repulseRadius) {
110
120
  repulse.particles.push(particle);
111
- const vect = Vector.create(dx, dy);
112
- vect.length = force;
113
- particle.velocity.setTo(vect);
121
+ this._clickVec.x = dx;
122
+ this._clickVec.y = dy;
123
+ this._clickVec.length = force;
124
+ particle.velocity.setTo(this._clickVec);
114
125
  }
115
126
  }
116
127
  }
@@ -129,14 +140,16 @@ export class Repulser extends ExternalInteractorBase {
129
140
  this._processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
130
141
  };
131
142
  _processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
132
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
143
+ const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
133
144
  if (!repulseOptions) {
134
145
  return;
135
146
  }
136
147
  const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this._engine.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
137
148
  for (const particle of query) {
138
- 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);
139
- particle.position.addTo(normVec);
149
+ const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
150
+ this._normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
151
+ this._normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
152
+ particle.position.addTo(this._normVec);
140
153
  }
141
154
  };
142
155
  _singleSelectorRepulse = (interactivityData, selector, div) => {
package/browser/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export async function loadExternalRepulseInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.24");
2
+ engine.checkVersion("4.0.0-alpha.26");
3
3
  await engine.register(async (e) => {
4
4
  const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity");
5
5
  ensureInteractivityPluginLoaded(e);
package/cjs/Repulser.js CHANGED
@@ -4,10 +4,16 @@ import { Repulse } from "./Options/Classes/Repulse.js";
4
4
  const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
5
5
  export class Repulser extends ExternalInteractorBase {
6
6
  handleClickMode;
7
+ _clickVec;
7
8
  _engine;
9
+ _maxDistance;
10
+ _normVec;
8
11
  constructor(engine, container) {
9
12
  super(container);
10
13
  this._engine = engine;
14
+ this._maxDistance = 0;
15
+ this._normVec = Vector.origin;
16
+ this._clickVec = Vector.origin;
11
17
  container.repulse ??= { particles: [] };
12
18
  this.handleClickMode = (mode, interactivityData) => {
13
19
  const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
@@ -34,6 +40,9 @@ export class Repulser extends ExternalInteractorBase {
34
40
  }, repulseOpts.duration * millisecondsToSeconds);
35
41
  };
36
42
  }
43
+ get maxDistance() {
44
+ return this._maxDistance;
45
+ }
37
46
  clear() {
38
47
  }
39
48
  init() {
@@ -41,6 +50,7 @@ export class Repulser extends ExternalInteractorBase {
41
50
  if (!repulse) {
42
51
  return;
43
52
  }
53
+ this._maxDistance = repulse.distance;
44
54
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
45
55
  }
46
56
  interact(interactivityData) {
@@ -103,14 +113,15 @@ export class Repulser extends ExternalInteractorBase {
103
113
  if (mouseClickPos === undefined) {
104
114
  return;
105
115
  }
106
- const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
116
+ const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.grid.query(range, p => this.isEnabled(interactivityData, p));
107
117
  for (const particle of query) {
108
118
  const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
109
119
  if (d <= repulseRadius) {
110
120
  repulse.particles.push(particle);
111
- const vect = Vector.create(dx, dy);
112
- vect.length = force;
113
- particle.velocity.setTo(vect);
121
+ this._clickVec.x = dx;
122
+ this._clickVec.y = dy;
123
+ this._clickVec.length = force;
124
+ particle.velocity.setTo(this._clickVec);
114
125
  }
115
126
  }
116
127
  }
@@ -129,14 +140,16 @@ export class Repulser extends ExternalInteractorBase {
129
140
  this._processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
130
141
  };
131
142
  _processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
132
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
143
+ const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
133
144
  if (!repulseOptions) {
134
145
  return;
135
146
  }
136
147
  const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this._engine.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
137
148
  for (const particle of query) {
138
- 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);
139
- particle.position.addTo(normVec);
149
+ const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
150
+ this._normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
151
+ this._normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
152
+ particle.position.addTo(this._normVec);
140
153
  }
141
154
  };
142
155
  _singleSelectorRepulse = (interactivityData, selector, div) => {
package/cjs/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export async function loadExternalRepulseInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.24");
2
+ engine.checkVersion("4.0.0-alpha.26");
3
3
  await engine.register(async (e) => {
4
4
  const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity");
5
5
  ensureInteractivityPluginLoaded(e);
@@ -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
- * v4.0.0-alpha.24
7
+ * v4.0.0-alpha.26
8
8
  */
9
9
  "use strict";
10
10
  /*
@@ -23,7 +23,7 @@
23
23
  \**********************************/
24
24
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
25
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 _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\");\n/* harmony import */ var _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Repulse.js */ \"./dist/browser/Options/Classes/Repulse.js\");\n\n\n\nconst repulseMode = \"repulse\", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;\nclass Repulser extends _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.ExternalInteractorBase {\n handleClickMode;\n _engine;\n constructor(engine, container){\n super(container);\n this._engine = engine;\n container.repulse ??= {\n particles: []\n };\n this.handleClickMode = (mode, interactivityData)=>{\n const options = this.container.actualOptions, 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(interactivityData, 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, repulse = container.actualOptions.interactivity?.modes.repulse;\n if (!repulse) {\n return;\n }\n container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;\n }\n interact(interactivityData) {\n const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.mouseMoveEvent, events = options.interactivity?.events;\n if (!events) {\n return;\n }\n const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;\n if (mouseMoveStatus && hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode)) {\n this._hoverRepulse(interactivityData);\n } else if (clickEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, clickMode)) {\n this._clickRepulse(interactivityData);\n } else {\n (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divModeExecute)(repulseMode, divs, (selector, div)=>{\n this._singleSelectorRepulse(interactivityData, selector, div);\n });\n }\n }\n isEnabled(interactivityData, particle) {\n const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;\n if (!events) {\n return false;\n }\n const divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.isDivModeEnabled)(repulseMode, divs);\n if (!(divRepulse || hover.enable && !!mouse.position || click.enable && mouse.clickPosition)) {\n return false;\n }\n const hoverMode = hover.mode, 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_2__.Repulse();\n for (const source of sources){\n options.repulse.load(source?.repulse);\n }\n }\n reset() {}\n _clickRepulse = (interactivityData)=>{\n const container = this.container, 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), mouseClickPos = interactivityData.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), query = container.particles.quadTree.query(range, (p)=>this.isEnabled(interactivityData, p));\n for (const particle of query){\n const { dx, dy, distance } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, 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 _hoverRepulse = (interactivityData)=>{\n const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;\n if (!repulseRadius || repulseRadius < minRadius || !mousePos) {\n return;\n }\n this._processRepulse(interactivityData, mousePos, repulseRadius, new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(mousePos.x, mousePos.y, repulseRadius));\n };\n _processRepulse = (interactivityData, position, repulseRadius, area, divRepulse)=>{\n const container = this.container, query = container.particles.quadTree.query(area, (p)=>this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this._engine.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;\n for (const particle of query){\n const { dx, dy, distance } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(particle.position, position), repulseFactor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.clamp)(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed), 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 _singleSelectorRepulse = (interactivityData, selector, div)=>{\n const container = this.container, 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, pxRatio = container.retina.pixelRatio, pos = {\n x: (elem.offsetLeft + elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio\n }, repulseRadius = elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half * pxRatio, area = div.type === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.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), divs = repulse.divs, divRepulse = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divMode)(divs, elem);\n this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);\n });\n };\n}\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/Repulser.js?\n}");
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 _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\");\n/* harmony import */ var _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Repulse.js */ \"./dist/browser/Options/Classes/Repulse.js\");\n\n\n\nconst repulseMode = \"repulse\", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;\nclass Repulser extends _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.ExternalInteractorBase {\n handleClickMode;\n _clickVec;\n _engine;\n _maxDistance;\n _normVec;\n constructor(engine, container){\n super(container);\n this._engine = engine;\n this._maxDistance = 0;\n this._normVec = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.origin;\n this._clickVec = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.origin;\n container.repulse ??= {\n particles: []\n };\n this.handleClickMode = (mode, interactivityData)=>{\n const options = this.container.actualOptions, 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(interactivityData, 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 get maxDistance() {\n return this._maxDistance;\n }\n clear() {}\n init() {\n const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;\n if (!repulse) {\n return;\n }\n this._maxDistance = repulse.distance;\n container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;\n }\n interact(interactivityData) {\n const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.mouseMoveEvent, events = options.interactivity?.events;\n if (!events) {\n return;\n }\n const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;\n if (mouseMoveStatus && hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode)) {\n this._hoverRepulse(interactivityData);\n } else if (clickEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, clickMode)) {\n this._clickRepulse(interactivityData);\n } else {\n (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divModeExecute)(repulseMode, divs, (selector, div)=>{\n this._singleSelectorRepulse(interactivityData, selector, div);\n });\n }\n }\n isEnabled(interactivityData, particle) {\n const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;\n if (!events) {\n return false;\n }\n const divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.isDivModeEnabled)(repulseMode, divs);\n if (!(divRepulse || hover.enable && !!mouse.position || click.enable && mouse.clickPosition)) {\n return false;\n }\n const hoverMode = hover.mode, 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_2__.Repulse();\n for (const source of sources){\n options.repulse.load(source?.repulse);\n }\n }\n reset() {}\n _clickRepulse = (interactivityData)=>{\n const container = this.container, 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), mouseClickPos = interactivityData.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), query = container.particles.grid.query(range, (p)=>this.isEnabled(interactivityData, p));\n for (const particle of query){\n const { dx, dy, distance } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = -repulseRadius * velocity / d;\n if (d <= repulseRadius) {\n repulse.particles.push(particle);\n this._clickVec.x = dx;\n this._clickVec.y = dy;\n this._clickVec.length = force;\n particle.velocity.setTo(this._clickVec);\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 _hoverRepulse = (interactivityData)=>{\n const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;\n if (!repulseRadius || repulseRadius < minRadius || !mousePos) {\n return;\n }\n this._processRepulse(interactivityData, mousePos, repulseRadius, new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(mousePos.x, mousePos.y, repulseRadius));\n };\n _processRepulse = (interactivityData, position, repulseRadius, area, divRepulse)=>{\n const container = this.container, query = container.particles.grid.query(area, (p)=>this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this._engine.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;\n for (const particle of query){\n const { dx, dy, distance } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(particle.position, position), repulseFactor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.clamp)(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);\n this._normVec.x = !distance ? velocity : dx / distance * repulseFactor;\n this._normVec.y = !distance ? velocity : dy / distance * repulseFactor;\n particle.position.addTo(this._normVec);\n }\n };\n _singleSelectorRepulse = (interactivityData, selector, div)=>{\n const container = this.container, 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, pxRatio = container.retina.pixelRatio, pos = {\n x: (elem.offsetLeft + elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio\n }, repulseRadius = elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half * pxRatio, area = div.type === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.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), divs = repulse.divs, divRepulse = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divMode)(divs, elem);\n this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);\n });\n };\n}\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/Repulser.js?\n}");
27
27
 
28
28
  /***/ }
29
29
 
package/esm/Repulser.js CHANGED
@@ -4,10 +4,16 @@ import { Repulse } from "./Options/Classes/Repulse.js";
4
4
  const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
5
5
  export class Repulser extends ExternalInteractorBase {
6
6
  handleClickMode;
7
+ _clickVec;
7
8
  _engine;
9
+ _maxDistance;
10
+ _normVec;
8
11
  constructor(engine, container) {
9
12
  super(container);
10
13
  this._engine = engine;
14
+ this._maxDistance = 0;
15
+ this._normVec = Vector.origin;
16
+ this._clickVec = Vector.origin;
11
17
  container.repulse ??= { particles: [] };
12
18
  this.handleClickMode = (mode, interactivityData) => {
13
19
  const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
@@ -34,6 +40,9 @@ export class Repulser extends ExternalInteractorBase {
34
40
  }, repulseOpts.duration * millisecondsToSeconds);
35
41
  };
36
42
  }
43
+ get maxDistance() {
44
+ return this._maxDistance;
45
+ }
37
46
  clear() {
38
47
  }
39
48
  init() {
@@ -41,6 +50,7 @@ export class Repulser extends ExternalInteractorBase {
41
50
  if (!repulse) {
42
51
  return;
43
52
  }
53
+ this._maxDistance = repulse.distance;
44
54
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
45
55
  }
46
56
  interact(interactivityData) {
@@ -103,14 +113,15 @@ export class Repulser extends ExternalInteractorBase {
103
113
  if (mouseClickPos === undefined) {
104
114
  return;
105
115
  }
106
- const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
116
+ const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.grid.query(range, p => this.isEnabled(interactivityData, p));
107
117
  for (const particle of query) {
108
118
  const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
109
119
  if (d <= repulseRadius) {
110
120
  repulse.particles.push(particle);
111
- const vect = Vector.create(dx, dy);
112
- vect.length = force;
113
- particle.velocity.setTo(vect);
121
+ this._clickVec.x = dx;
122
+ this._clickVec.y = dy;
123
+ this._clickVec.length = force;
124
+ particle.velocity.setTo(this._clickVec);
114
125
  }
115
126
  }
116
127
  }
@@ -129,14 +140,16 @@ export class Repulser extends ExternalInteractorBase {
129
140
  this._processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
130
141
  };
131
142
  _processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
132
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
143
+ const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
133
144
  if (!repulseOptions) {
134
145
  return;
135
146
  }
136
147
  const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this._engine.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
137
148
  for (const particle of query) {
138
- 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);
139
- particle.position.addTo(normVec);
149
+ const { dx, dy, distance } = getDistances(particle.position, position), repulseFactor = clamp(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
150
+ this._normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
151
+ this._normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
152
+ particle.position.addTo(this._normVec);
140
153
  }
141
154
  };
142
155
  _singleSelectorRepulse = (interactivityData, selector, div) => {
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export async function loadExternalRepulseInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.24");
2
+ engine.checkVersion("4.0.0-alpha.26");
3
3
  await engine.register(async (e) => {
4
4
  const { ensureInteractivityPluginLoaded } = await import("@tsparticles/plugin-interactivity");
5
5
  ensureInteractivityPluginLoaded(e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/interaction-external-repulse",
3
- "version": "4.0.0-alpha.24",
3
+ "version": "4.0.0-alpha.26",
4
4
  "description": "tsParticles repulse external interaction",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -87,8 +87,8 @@
87
87
  "./package.json": "./package.json"
88
88
  },
89
89
  "dependencies": {
90
- "@tsparticles/engine": "4.0.0-alpha.24",
91
- "@tsparticles/plugin-interactivity": "4.0.0-alpha.24"
90
+ "@tsparticles/engine": "4.0.0-alpha.26",
91
+ "@tsparticles/plugin-interactivity": "4.0.0-alpha.26"
92
92
  },
93
93
  "publishConfig": {
94
94
  "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-repulse [12 Feb 2026 at 18:50]</title>
6
+ <title>@tsparticles/interaction-external-repulse [26 Feb 2026 at 18:07]</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>
@@ -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
- * v4.0.0-alpha.24
7
+ * v4.0.0-alpha.26
8
8
  */
9
9
  /*
10
10
  * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
@@ -84,7 +84,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
84
84
  \*******************************/
85
85
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
86
86
 
87
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Repulse: () => (/* reexport safe */ _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_2__.Repulse),\n/* harmony export */ RepulseBase: () => (/* reexport safe */ _Options_Classes_RepulseBase_js__WEBPACK_IMPORTED_MODULE_0__.RepulseBase),\n/* harmony export */ RepulseDiv: () => (/* reexport safe */ _Options_Classes_RepulseDiv_js__WEBPACK_IMPORTED_MODULE_1__.RepulseDiv),\n/* harmony export */ loadExternalRepulseInteraction: () => (/* binding */ loadExternalRepulseInteraction)\n/* harmony export */ });\n/* harmony import */ var _Options_Classes_RepulseBase_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Options/Classes/RepulseBase.js */ \"./dist/browser/Options/Classes/RepulseBase.js\");\n/* harmony import */ var _Options_Classes_RepulseDiv_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Options/Classes/RepulseDiv.js */ \"./dist/browser/Options/Classes/RepulseDiv.js\");\n/* harmony import */ var _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Repulse.js */ \"./dist/browser/Options/Classes/Repulse.js\");\nasync function loadExternalRepulseInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.24\");\n await engine.register(async (e)=>{\n const { ensureInteractivityPluginLoaded } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\", 19));\n ensureInteractivityPluginLoaded(e);\n e.addInteractor?.(\"externalRepulse\", async (container)=>{\n const { Repulser } = await __webpack_require__.e(/*! import() */ \"dist_browser_Repulser_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./Repulser.js */ \"./dist/browser/Repulser.js\"));\n return new Repulser(engine, container);\n });\n });\n}\n\n\n\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/index.js?\n}");
87
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Repulse: () => (/* reexport safe */ _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_2__.Repulse),\n/* harmony export */ RepulseBase: () => (/* reexport safe */ _Options_Classes_RepulseBase_js__WEBPACK_IMPORTED_MODULE_0__.RepulseBase),\n/* harmony export */ RepulseDiv: () => (/* reexport safe */ _Options_Classes_RepulseDiv_js__WEBPACK_IMPORTED_MODULE_1__.RepulseDiv),\n/* harmony export */ loadExternalRepulseInteraction: () => (/* binding */ loadExternalRepulseInteraction)\n/* harmony export */ });\n/* harmony import */ var _Options_Classes_RepulseBase_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Options/Classes/RepulseBase.js */ \"./dist/browser/Options/Classes/RepulseBase.js\");\n/* harmony import */ var _Options_Classes_RepulseDiv_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Options/Classes/RepulseDiv.js */ \"./dist/browser/Options/Classes/RepulseDiv.js\");\n/* harmony import */ var _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Options/Classes/Repulse.js */ \"./dist/browser/Options/Classes/Repulse.js\");\nasync function loadExternalRepulseInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.26\");\n await engine.register(async (e)=>{\n const { ensureInteractivityPluginLoaded } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\", 19));\n ensureInteractivityPluginLoaded(e);\n e.addInteractor?.(\"externalRepulse\", async (container)=>{\n const { Repulser } = await __webpack_require__.e(/*! import() */ \"dist_browser_Repulser_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./Repulser.js */ \"./dist/browser/Repulser.js\"));\n return new Repulser(engine, container);\n });\n });\n}\n\n\n\n\n\n//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/index.js?\n}");
88
88
 
89
89
  /***/ }
90
90
 
@@ -1,2 +1,2 @@
1
- !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine","@tsparticles/plugin-interactivity"],t);else{var r="object"==typeof exports?t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity")):t(e.window,e.window);for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(this,(e,t)=>(()=>{"use strict";var r,i,o,n={303(t){t.exports=e},702(e){e.exports=t},498(e,t,r){r.d(t,{Z:()=>s});var i=r(303),o=r(403),n=r(435);class s extends o._{divs;load(e){super.load(e),(0,i.isNull)(e)||(this.divs=(0,i.executeOnSingleOrMultiple)(e.divs,e=>{let t=new n.W;return t.load(e),t}))}}},403(e,t,r){r.d(t,{_:()=>o});var i=r(303);class o{distance;duration;easing;factor;maxSpeed;speed;constructor(){this.distance=200,this.duration=.4,this.factor=100,this.speed=1,this.maxSpeed=50,this.easing=i.EasingType.easeOutQuad}load(e){(0,i.isNull)(e)||(void 0!==e.distance&&(this.distance=e.distance),void 0!==e.duration&&(this.duration=e.duration),void 0!==e.easing&&(this.easing=e.easing),void 0!==e.factor&&(this.factor=e.factor),void 0!==e.speed&&(this.speed=e.speed),void 0!==e.maxSpeed&&(this.maxSpeed=e.maxSpeed))}}},435(e,t,r){r.d(t,{W:()=>n});var i=r(303),o=r(403);class n extends o._{selectors;constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,i.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}}},s={};function a(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}};return n[e](r,r.exports,a),r.exports}a.m=n,c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,a.t=function(e,t){if(1&t&&(e=this(e)),8&t||"object"==typeof e&&e&&(4&t&&e.__esModule||16&t&&"function"==typeof e.then))return e;var r=Object.create(null);a.r(r);var i={};l=l||[null,c({}),c([]),c(c)];for(var o=2&t&&e;("object"==typeof o||"function"==typeof o)&&!~l.indexOf(o);o=c(o))Object.getOwnPropertyNames(o).forEach(t=>i[t]=()=>e[t]);return i.default=()=>e,a.d(r,i),r},a.d=(e,t)=>{for(var r in t)a.o(t,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},a.f={},a.e=e=>Promise.all(Object.keys(a.f).reduce((t,r)=>(a.f[r](e,t),t),[])),a.u=e=>""+e+".min.js",a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),p={},a.l=(e,t,r,i)=>{if(p[e])return void p[e].push(t);if(void 0!==r)for(var o,n,s=document.getElementsByTagName("script"),l=0;l<s.length;l++){var c=s[l];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")=="@tsparticles/interaction-external-repulse:"+r){o=c;break}}o||(n=!0,(o=document.createElement("script")).charset="utf-8",a.nc&&o.setAttribute("nonce",a.nc),o.setAttribute("data-webpack","@tsparticles/interaction-external-repulse:"+r),o.src=e),p[e]=[t];var u=(t,r)=>{o.onerror=o.onload=null,clearTimeout(d);var i=p[e];if(delete p[e],o.parentNode&&o.parentNode.removeChild(o),i&&i.forEach(e=>e(r)),t)return t(r)},d=setTimeout(u.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=u.bind(null,o.onerror),o.onload=u.bind(null,o.onload),n&&document.head.appendChild(o)},a.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.g.importScripts&&(u=a.g.location+"");var l,c,p,u,d=a.g.document;if(!u&&d&&(d.currentScript&&"SCRIPT"===d.currentScript.tagName.toUpperCase()&&(u=d.currentScript.src),!u)){var f=d.getElementsByTagName("script");if(f.length)for(var h=f.length-1;h>-1&&(!u||!/^http(s?):/.test(u));)u=f[h--].src}if(!u)throw Error("Automatic publicPath is not supported in this browser");a.p=u=u.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r={64:0},a.f.j=(e,t)=>{var i=a.o(r,e)?r[e]:void 0;if(0!==i)if(i)t.push(i[2]);else{var o=new Promise((t,o)=>i=r[e]=[t,o]);t.push(i[2]=o);var n=a.p+a.u(e),s=Error();a.l(n,t=>{if(a.o(r,e)&&(0!==(i=r[e])&&(r[e]=void 0),i)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;s.message="Loading chunk "+e+` failed.
2
- (`+o+": "+n+")",s.name="ChunkLoadError",s.type=o,s.request=n,i[1](s)}},"chunk-"+e,e)}},i=(e,t)=>{var i,o,[n,s,l]=t,c=0;if(n.some(e=>0!==r[e])){for(i in s)a.o(s,i)&&(a.m[i]=s[i]);l&&l(a)}for(e&&e(t);c<n.length;c++)o=n[c],a.o(r,o)&&r[o]&&r[o][0](),r[o]=0},(o=this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[]).forEach(i.bind(null,0)),o.push=i.bind(null,o.push.bind(o));var v={};a.r(v),a.d(v,{Repulse:()=>m.Z,RepulseBase:()=>g._,RepulseDiv:()=>b.W,loadExternalRepulseInteraction:()=>y});var g=a(403),b=a(435),m=a(498);async function y(e){e.checkVersion("4.0.0-alpha.24"),await e.register(async t=>{let{ensureInteractivityPluginLoaded:r}=await Promise.resolve().then(a.t.bind(a,702,19));r(t),t.addInteractor?.("externalRepulse",async t=>{let{Repulser:r}=await a.e(780).then(a.bind(a,780));return new r(e,t)})})}return v})());
1
+ !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine","@tsparticles/plugin-interactivity"],t);else{var r="object"==typeof exports?t(require("@tsparticles/engine"),require("@tsparticles/plugin-interactivity")):t(e.window,e.window);for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(this,(e,t)=>(()=>{"use strict";var r,i,o,n={303(t){t.exports=e},702(e){e.exports=t},686(e,t,r){r.d(t,{Z:()=>s});var i=r(303),o=r(247),n=r(215);class s extends o._{divs;load(e){super.load(e),(0,i.isNull)(e)||(this.divs=(0,i.executeOnSingleOrMultiple)(e.divs,e=>{let t=new n.W;return t.load(e),t}))}}},247(e,t,r){r.d(t,{_:()=>o});var i=r(303);class o{distance;duration;easing;factor;maxSpeed;speed;constructor(){this.distance=200,this.duration=.4,this.factor=100,this.speed=1,this.maxSpeed=50,this.easing=i.EasingType.easeOutQuad}load(e){(0,i.isNull)(e)||(void 0!==e.distance&&(this.distance=e.distance),void 0!==e.duration&&(this.duration=e.duration),void 0!==e.easing&&(this.easing=e.easing),void 0!==e.factor&&(this.factor=e.factor),void 0!==e.speed&&(this.speed=e.speed),void 0!==e.maxSpeed&&(this.maxSpeed=e.maxSpeed))}}},215(e,t,r){r.d(t,{W:()=>n});var i=r(303),o=r(247);class n extends o._{selectors;constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,i.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}}},s={};function a(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}};return n[e](r,r.exports,a),r.exports}a.m=n,c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,a.t=function(e,t){if(1&t&&(e=this(e)),8&t||"object"==typeof e&&e&&(4&t&&e.__esModule||16&t&&"function"==typeof e.then))return e;var r=Object.create(null);a.r(r);var i={};l=l||[null,c({}),c([]),c(c)];for(var o=2&t&&e;("object"==typeof o||"function"==typeof o)&&!~l.indexOf(o);o=c(o))Object.getOwnPropertyNames(o).forEach(t=>i[t]=()=>e[t]);return i.default=()=>e,a.d(r,i),r},a.d=(e,t)=>{for(var r in t)a.o(t,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},a.f={},a.e=e=>Promise.all(Object.keys(a.f).reduce((t,r)=>(a.f[r](e,t),t),[])),a.u=e=>""+e+".min.js",a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),p={},a.l=(e,t,r,i)=>{if(p[e])return void p[e].push(t);if(void 0!==r)for(var o,n,s=document.getElementsByTagName("script"),l=0;l<s.length;l++){var c=s[l];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")=="@tsparticles/interaction-external-repulse:"+r){o=c;break}}o||(n=!0,(o=document.createElement("script")).charset="utf-8",a.nc&&o.setAttribute("nonce",a.nc),o.setAttribute("data-webpack","@tsparticles/interaction-external-repulse:"+r),o.src=e),p[e]=[t];var u=(t,r)=>{o.onerror=o.onload=null,clearTimeout(d);var i=p[e];if(delete p[e],o.parentNode&&o.parentNode.removeChild(o),i&&i.forEach(e=>e(r)),t)return t(r)},d=setTimeout(u.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=u.bind(null,o.onerror),o.onload=u.bind(null,o.onload),n&&document.head.appendChild(o)},a.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.g.importScripts&&(u=a.g.location+"");var l,c,p,u,d=a.g.document;if(!u&&d&&(d.currentScript&&"SCRIPT"===d.currentScript.tagName.toUpperCase()&&(u=d.currentScript.src),!u)){var f=d.getElementsByTagName("script");if(f.length)for(var h=f.length-1;h>-1&&(!u||!/^http(s?):/.test(u));)u=f[h--].src}if(!u)throw Error("Automatic publicPath is not supported in this browser");a.p=u=u.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r={64:0},a.f.j=(e,t)=>{var i=a.o(r,e)?r[e]:void 0;if(0!==i)if(i)t.push(i[2]);else{var o=new Promise((t,o)=>i=r[e]=[t,o]);t.push(i[2]=o);var n=a.p+a.u(e),s=Error();a.l(n,t=>{if(a.o(r,e)&&(0!==(i=r[e])&&(r[e]=void 0),i)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;s.message="Loading chunk "+e+` failed.
2
+ (`+o+": "+n+")",s.name="ChunkLoadError",s.type=o,s.request=n,i[1](s)}},"chunk-"+e,e)}},i=(e,t)=>{var i,o,[n,s,l]=t,c=0;if(n.some(e=>0!==r[e])){for(i in s)a.o(s,i)&&(a.m[i]=s[i]);l&&l(a)}for(e&&e(t);c<n.length;c++)o=n[c],a.o(r,o)&&r[o]&&r[o][0](),r[o]=0},(o=this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[]).forEach(i.bind(null,0)),o.push=i.bind(null,o.push.bind(o));var v={};a.r(v),a.d(v,{Repulse:()=>m.Z,RepulseBase:()=>g._,RepulseDiv:()=>b.W,loadExternalRepulseInteraction:()=>y});var g=a(247),b=a(215),m=a(686);async function y(e){e.checkVersion("4.0.0-alpha.26"),await e.register(async t=>{let{ensureInteractivityPluginLoaded:r}=await Promise.resolve().then(a.t.bind(a,702,19));r(t),t.addInteractor?.("externalRepulse",async t=>{let{Repulser:r}=await a.e(504).then(a.bind(a,504));return new r(e,t)})})}return v})());
@@ -3,8 +3,12 @@ import { ExternalInteractorBase, type IInteractivityData, type IModes, type Inte
3
3
  import type { IRepulseMode, RepulseContainer, RepulseMode } from "./Types.js";
4
4
  export declare class Repulser extends ExternalInteractorBase<RepulseContainer> {
5
5
  handleClickMode: (mode: string, interactivityData: IInteractivityData) => void;
6
+ private readonly _clickVec;
6
7
  private readonly _engine;
8
+ private _maxDistance;
9
+ private readonly _normVec;
7
10
  constructor(engine: Engine, container: RepulseContainer);
11
+ get maxDistance(): number;
8
12
  clear(): void;
9
13
  init(): void;
10
14
  interact(interactivityData: IInteractivityData): void;
package/umd/Repulser.js CHANGED
@@ -16,10 +16,16 @@
16
16
  const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
17
17
  class Repulser extends plugin_interactivity_1.ExternalInteractorBase {
18
18
  handleClickMode;
19
+ _clickVec;
19
20
  _engine;
21
+ _maxDistance;
22
+ _normVec;
20
23
  constructor(engine, container) {
21
24
  super(container);
22
25
  this._engine = engine;
26
+ this._maxDistance = 0;
27
+ this._normVec = engine_1.Vector.origin;
28
+ this._clickVec = engine_1.Vector.origin;
23
29
  container.repulse ??= { particles: [] };
24
30
  this.handleClickMode = (mode, interactivityData) => {
25
31
  const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
@@ -46,6 +52,9 @@
46
52
  }, repulseOpts.duration * engine_1.millisecondsToSeconds);
47
53
  };
48
54
  }
55
+ get maxDistance() {
56
+ return this._maxDistance;
57
+ }
49
58
  clear() {
50
59
  }
51
60
  init() {
@@ -53,6 +62,7 @@
53
62
  if (!repulse) {
54
63
  return;
55
64
  }
65
+ this._maxDistance = repulse.distance;
56
66
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
57
67
  }
58
68
  interact(interactivityData) {
@@ -115,14 +125,15 @@
115
125
  if (mouseClickPos === undefined) {
116
126
  return;
117
127
  }
118
- const range = new engine_1.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
128
+ const range = new engine_1.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.grid.query(range, p => this.isEnabled(interactivityData, p));
119
129
  for (const particle of query) {
120
130
  const { dx, dy, distance } = (0, engine_1.getDistances)(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
121
131
  if (d <= repulseRadius) {
122
132
  repulse.particles.push(particle);
123
- const vect = engine_1.Vector.create(dx, dy);
124
- vect.length = force;
125
- particle.velocity.setTo(vect);
133
+ this._clickVec.x = dx;
134
+ this._clickVec.y = dy;
135
+ this._clickVec.length = force;
136
+ particle.velocity.setTo(this._clickVec);
126
137
  }
127
138
  }
128
139
  }
@@ -141,14 +152,16 @@
141
152
  this._processRepulse(interactivityData, mousePos, repulseRadius, new engine_1.Circle(mousePos.x, mousePos.y, repulseRadius));
142
153
  };
143
154
  _processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
144
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
155
+ const container = this.container, query = container.particles.grid.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
145
156
  if (!repulseOptions) {
146
157
  return;
147
158
  }
148
159
  const { easing, speed, factor, maxSpeed } = repulseOptions, easingFunc = this._engine.getEasing(easing), velocity = (divRepulse?.speed ?? speed) * factor;
149
160
  for (const particle of query) {
150
- const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position), repulseFactor = (0, engine_1.clamp)(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed), normVec = engine_1.Vector.create(!distance ? velocity : (dx / distance) * repulseFactor, !distance ? velocity : (dy / distance) * repulseFactor);
151
- particle.position.addTo(normVec);
161
+ const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position), repulseFactor = (0, engine_1.clamp)(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed);
162
+ this._normVec.x = !distance ? velocity : (dx / distance) * repulseFactor;
163
+ this._normVec.y = !distance ? velocity : (dy / distance) * repulseFactor;
164
+ particle.position.addTo(this._normVec);
152
165
  }
153
166
  };
154
167
  _singleSelectorRepulse = (interactivityData, selector, div) => {
package/umd/index.js CHANGED
@@ -48,7 +48,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
49
  exports.loadExternalRepulseInteraction = loadExternalRepulseInteraction;
50
50
  async function loadExternalRepulseInteraction(engine) {
51
- engine.checkVersion("4.0.0-alpha.24");
51
+ engine.checkVersion("4.0.0-alpha.26");
52
52
  await engine.register(async (e) => {
53
53
  const { ensureInteractivityPluginLoaded } = await (__syncRequire ? Promise.resolve().then(() => __importStar(require("@tsparticles/plugin-interactivity"))) : new Promise((resolve_1, reject_1) => { require(["@tsparticles/plugin-interactivity"], resolve_1, reject_1); }).then(__importStar));
54
54
  ensureInteractivityPluginLoaded(e);
package/780.min.js DELETED
@@ -1 +0,0 @@
1
- "use strict";(this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[]).push([[780],{780(e,t,i){i.d(t,{Repulser:()=>o});var s=i(303),l=i(702),n=i(498);let r="repulse";class o extends l.ExternalInteractorBase{handleClickMode;_engine;constructor(e,t){super(t),this._engine=e,t.repulse??={particles:[]},this.handleClickMode=(e,i)=>{let l=this.container.actualOptions,n=l.interactivity?.modes.repulse;if(!n||e!==r)return;t.repulse??={particles:[]};let o=t.repulse;for(let e of(o.clicking=!0,o.count=0,t.repulse.particles))this.isEnabled(i,e)&&e.velocity.setTo(e.initialVelocity);o.particles=[],o.finish=!1,setTimeout(()=>{t.destroyed||(o.clicking=!1)},n.duration*s.millisecondsToSeconds)}}clear(){}init(){let e=this.container,t=e.actualOptions.interactivity?.modes.repulse;t&&(e.retina.repulseModeDistance=t.distance*e.retina.pixelRatio)}interact(e){let t=this.container.actualOptions,i=e.status===l.mouseMoveEvent,n=t.interactivity?.events;if(!n)return;let o=n.onHover,c=o.enable,a=o.mode,p=n.onClick,u=p.enable,f=p.mode,d=n.onDiv;i&&c&&(0,s.isInArray)(r,a)?this._hoverRepulse(e):u&&(0,s.isInArray)(r,f)?this._clickRepulse(e):(0,l.divModeExecute)(r,d,(t,i)=>{this._singleSelectorRepulse(e,t,i)})}isEnabled(e,t){let i=this.container.actualOptions,n=e.mouse,o=(t?.interactivity??i.interactivity)?.events;if(!o)return!1;let c=o.onDiv,a=o.onHover,p=o.onClick,u=(0,l.isDivModeEnabled)(r,c);if(!(u||a.enable&&n.position||p.enable&&n.clickPosition))return!1;let f=a.mode,d=p.mode;return(0,s.isInArray)(r,f)||(0,s.isInArray)(r,d)||u}loadModeOptions(e,...t){for(let i of(e.repulse??=new n.Z,t))e.repulse.load(i?.repulse)}reset(){}_clickRepulse=e=>{let t=this.container,i=t.actualOptions.interactivity?.modes.repulse;if(!i)return;let l=t.repulse??{particles:[]};if(l.finish||(l.count??=0,l.count++,l.count===t.particles.count&&(l.finish=!0)),l.clicking){let n=t.retina.repulseModeDistance;if(!n||n<0)return;let r=Math.pow(n/6,3),o=e.mouse.clickPosition;if(void 0===o)return;let c=new s.Circle(o.x,o.y,r);for(let n of t.particles.quadTree.query(c,t=>this.isEnabled(e,t))){let{dx:e,dy:t,distance:c}=(0,s.getDistances)(o,n.position),a=c**2,p=-r*i.speed/a;if(a<=r){l.particles.push(n);let i=s.Vector.create(e,t);i.length=p,n.velocity.setTo(i)}}}else if(!1===l.clicking){for(let e of l.particles)e.velocity.setTo(e.initialVelocity);l.particles=[]}};_hoverRepulse=e=>{let t=this.container,i=e.mouse.position,l=t.retina.repulseModeDistance;l&&!(l<0)&&i&&this._processRepulse(e,i,l,new s.Circle(i.x,i.y,l))};_processRepulse=(e,t,i,l,n)=>{let r=this.container,o=r.particles.quadTree.query(l,t=>this.isEnabled(e,t)),c=r.actualOptions.interactivity?.modes.repulse;if(!c)return;let{easing:a,speed:p,factor:u,maxSpeed:f}=c,d=this._engine.getEasing(a),h=(n?.speed??p)*u;for(let e of o){let{dx:l,dy:n,distance:r}=(0,s.getDistances)(e.position,t),o=(0,s.clamp)(d(1-r/i)*h,0,f),c=s.Vector.create(r?l/r*o:h,r?n/r*o:h);e.position.addTo(c)}};_singleSelectorRepulse=(e,t,i)=>{let n=this.container,r=n.actualOptions.interactivity?.modes.repulse;if(!r)return;let o=(0,s.safeDocument)().querySelectorAll(t);o.length&&o.forEach(t=>{let o=n.retina.pixelRatio,c={x:(t.offsetLeft+t.offsetWidth*s.half)*o,y:(t.offsetTop+t.offsetHeight*s.half)*o},a=t.offsetWidth*s.half*o,p=i.type===l.DivType.circle?new s.Circle(c.x,c.y,a):new s.Rectangle(t.offsetLeft*o,t.offsetTop*o,t.offsetWidth*o,t.offsetHeight*o),u=r.divs,f=(0,l.divMode)(u,t);this._processRepulse(e,c,a,p,f)})}}}}]);