@tsparticles/interaction-external-repulse 4.0.0-alpha.2 → 4.0.0-alpha.4

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/783.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 783.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[]).push([[783],{783(e,t,i){i.d(t,{Repulser:()=>r});var s=i(303),n=i(702),o=i(591);const c="repulse";class r extends n.ExternalInteractorBase{constructor(e,t){super(t),this._clickRepulse=e=>{const t=this.container,i=t.actualOptions.interactivity?.modes.repulse;if(!i)return;const n=t.repulse??{particles:[]};if(n.finish||(n.count??=0,n.count++,n.count===t.particles.count&&(n.finish=!0)),n.clicking){const o=t.retina.repulseModeDistance;if(!o||o<0)return;const c=Math.pow(o/6,3),r=e.mouse.clickPosition;if(void 0===r)return;const a=new s.Circle(r.x,r.y,c),l=t.particles.quadTree.query(a,(t=>this.isEnabled(e,t)));for(const e of l){const{dx:t,dy:o,distance:a}=(0,s.getDistances)(r,e.position),l=a**2,p=-c*i.speed/l;if(l<=c){n.particles.push(e);const i=s.Vector.create(t,o);i.length=p,e.velocity.setTo(i)}}}else if(!1===n.clicking){for(const e of n.particles)e.velocity.setTo(e.initialVelocity);n.particles=[]}},this._hoverRepulse=e=>{const 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))},this._processRepulse=(e,t,i,n,o)=>{const c=this.container,r=c.particles.quadTree.query(n,(t=>this.isEnabled(e,t))),a=c.actualOptions.interactivity?.modes.repulse;if(!a)return;const{easing:l,speed:p,factor:u,maxSpeed:d}=a,f=this._engine.getEasing(l),h=(o?.speed??p)*u;for(const e of r){const{dx:n,dy:o,distance:c}=(0,s.getDistances)(e.position,t),r=(0,s.clamp)(f(1-c/i)*h,0,d),a=s.Vector.create(c?n/c*r:h,c?o/c*r:h);e.position.addTo(a)}},this._singleSelectorRepulse=(e,t,i)=>{const o=this.container,c=o.actualOptions.interactivity?.modes.repulse;if(!c)return;const r=(0,s.safeDocument)().querySelectorAll(t);r.length&&r.forEach((t=>{const r=t,a=o.retina.pixelRatio,l={x:(r.offsetLeft+r.offsetWidth*s.half)*a,y:(r.offsetTop+r.offsetHeight*s.half)*a},p=r.offsetWidth*s.half*a,u=i.type===n.DivType.circle?new s.Circle(l.x,l.y,p):new s.Rectangle(r.offsetLeft*a,r.offsetTop*a,r.offsetWidth*a,r.offsetHeight*a),d=c.divs,f=(0,n.divMode)(d,r);this._processRepulse(e,l,p,u,f)}))},this._engine=e,t.repulse??={particles:[]},this.handleClickMode=(e,i)=>{const n=this.container.actualOptions,o=n.interactivity?.modes.repulse;if(!o||e!==c)return;t.repulse??={particles:[]};const r=t.repulse;r.clicking=!0,r.count=0;for(const e of t.repulse.particles)this.isEnabled(i,e)&&e.velocity.setTo(e.initialVelocity);r.particles=[],r.finish=!1,setTimeout((()=>{t.destroyed||(r.clicking=!1)}),o.duration*s.millisecondsToSeconds)}}clear(){}init(){const e=this.container,t=e.actualOptions.interactivity?.modes.repulse;t&&(e.retina.repulseModeDistance=t.distance*e.retina.pixelRatio)}interact(e){const t=this.container.actualOptions,i=e.status===n.mouseMoveEvent,o=t.interactivity?.events;if(!o)return;const r=o.onHover,a=r.enable,l=r.mode,p=o.onClick,u=p.enable,d=p.mode,f=o.onDiv;i&&a&&(0,s.isInArray)(c,l)?this._hoverRepulse(e):u&&(0,s.isInArray)(c,d)?this._clickRepulse(e):(0,n.divModeExecute)(c,f,((t,i)=>{this._singleSelectorRepulse(e,t,i)}))}isEnabled(e,t){const i=this.container.actualOptions,o=e.mouse,r=(t?.interactivity??i.interactivity)?.events;if(!r)return!1;const a=r.onDiv,l=r.onHover,p=r.onClick,u=(0,n.isDivModeEnabled)(c,a);if(!(u||l.enable&&o.position||p.enable&&o.clickPosition))return!1;const d=l.mode,f=p.mode;return(0,s.isInArray)(c,d)||(0,s.isInArray)(c,f)||u}loadModeOptions(e,...t){e.repulse??=new o.Z;for(const i of t)e.repulse.load(i?.repulse)}reset(){}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Repulse External Interaction v4.0.0-alpha.4 by Matteo Bruni */
@@ -1,11 +1,12 @@
1
- import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, safeDocument, } from "@tsparticles/engine";
1
+ import { Circle, Rectangle, Vector, clamp, getDistances, half, isInArray, millisecondsToSeconds, safeDocument, } from "@tsparticles/engine";
2
+ import { DivType, ExternalInteractorBase, divMode, divModeExecute, isDivModeEnabled, mouseMoveEvent, } from "@tsparticles/plugin-interactivity";
2
3
  import { Repulse } from "./Options/Classes/Repulse.js";
3
- const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, half = 0.5;
4
+ const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
4
5
  export class Repulser extends ExternalInteractorBase {
5
6
  constructor(engine, container) {
6
7
  super(container);
7
- this._clickRepulse = () => {
8
- const container = this.container, repulseOptions = container.actualOptions.interactivity.modes.repulse;
8
+ this._clickRepulse = interactivityData => {
9
+ const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
9
10
  if (!repulseOptions) {
10
11
  return;
11
12
  }
@@ -22,11 +23,11 @@ export class Repulser extends ExternalInteractorBase {
22
23
  if (!repulseDistance || repulseDistance < minDistance) {
23
24
  return;
24
25
  }
25
- const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = container.interactivity.mouse.clickPosition;
26
+ const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = interactivityData.mouse.clickPosition;
26
27
  if (mouseClickPos === undefined) {
27
28
  return;
28
29
  }
29
- const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(p));
30
+ const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
30
31
  for (const particle of query) {
31
32
  const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
32
33
  if (d <= repulseRadius) {
@@ -44,15 +45,15 @@ export class Repulser extends ExternalInteractorBase {
44
45
  repulse.particles = [];
45
46
  }
46
47
  };
47
- this._hoverRepulse = () => {
48
- const container = this.container, mousePos = container.interactivity.mouse.position, repulseRadius = container.retina.repulseModeDistance;
48
+ this._hoverRepulse = interactivityData => {
49
+ const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
49
50
  if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
50
51
  return;
51
52
  }
52
- this._processRepulse(mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
53
+ this._processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
53
54
  };
54
- this._processRepulse = (position, repulseRadius, area, divRepulse) => {
55
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(p)), repulseOptions = container.actualOptions.interactivity.modes.repulse;
55
+ this._processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
56
+ const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
56
57
  if (!repulseOptions) {
57
58
  return;
58
59
  }
@@ -62,8 +63,8 @@ export class Repulser extends ExternalInteractorBase {
62
63
  particle.position.addTo(normVec);
63
64
  }
64
65
  };
65
- this._singleSelectorRepulse = (selector, div) => {
66
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
66
+ this._singleSelectorRepulse = (interactivityData, selector, div) => {
67
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
67
68
  if (!repulse) {
68
69
  return;
69
70
  }
@@ -78,13 +79,13 @@ export class Repulser extends ExternalInteractorBase {
78
79
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
79
80
  ? new Circle(pos.x, pos.y, repulseRadius)
80
81
  : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
81
- this._processRepulse(pos, repulseRadius, area, divRepulse);
82
+ this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
82
83
  });
83
84
  };
84
85
  this._engine = engine;
85
86
  container.repulse ??= { particles: [] };
86
- this.handleClickMode = (mode) => {
87
- const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
87
+ this.handleClickMode = (mode, interactivityData) => {
88
+ const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
88
89
  if (!repulseOpts || mode !== repulseMode) {
89
90
  return;
90
91
  }
@@ -93,7 +94,7 @@ export class Repulser extends ExternalInteractorBase {
93
94
  repulse.clicking = true;
94
95
  repulse.count = 0;
95
96
  for (const particle of container.repulse.particles) {
96
- if (!this.isEnabled(particle)) {
97
+ if (!this.isEnabled(interactivityData, particle)) {
97
98
  continue;
98
99
  }
99
100
  particle.velocity.setTo(particle.initialVelocity);
@@ -111,28 +112,36 @@ export class Repulser extends ExternalInteractorBase {
111
112
  clear() {
112
113
  }
113
114
  init() {
114
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
115
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
115
116
  if (!repulse) {
116
117
  return;
117
118
  }
118
119
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
119
120
  }
120
- interact() {
121
- const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === mouseMoveEvent, events = options.interactivity.events, hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
121
+ interact(interactivityData) {
122
+ const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
123
+ if (!events) {
124
+ return;
125
+ }
126
+ const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
122
127
  if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
123
- this._hoverRepulse();
128
+ this._hoverRepulse(interactivityData);
124
129
  }
125
130
  else if (clickEnabled && isInArray(repulseMode, clickMode)) {
126
- this._clickRepulse();
131
+ this._clickRepulse(interactivityData);
127
132
  }
128
133
  else {
129
134
  divModeExecute(repulseMode, divs, (selector, div) => {
130
- this._singleSelectorRepulse(selector, div);
135
+ this._singleSelectorRepulse(interactivityData, selector, div);
131
136
  });
132
137
  }
133
138
  }
134
- isEnabled(particle) {
135
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
139
+ isEnabled(interactivityData, particle) {
140
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
141
+ if (!events) {
142
+ return false;
143
+ }
144
+ const divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
136
145
  if (!(divRepulse || (hover.enable && !!mouse.position) || (click.enable && mouse.clickPosition))) {
137
146
  return false;
138
147
  }
package/browser/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  export function loadExternalRepulseInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.2");
3
- engine.register(e => {
4
- e.addInteractor("externalRepulse", async (container) => {
2
+ engine.checkVersion("4.0.0-alpha.4");
3
+ engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity");
5
+ loadInteractivityPlugin(e);
6
+ e.addInteractor?.("externalRepulse", async (container) => {
5
7
  const { Repulser } = await import("./Repulser.js");
6
8
  return new Repulser(engine, container);
7
9
  });
package/cjs/Repulser.js CHANGED
@@ -1,11 +1,12 @@
1
- import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, safeDocument, } from "@tsparticles/engine";
1
+ import { Circle, Rectangle, Vector, clamp, getDistances, half, isInArray, millisecondsToSeconds, safeDocument, } from "@tsparticles/engine";
2
+ import { DivType, ExternalInteractorBase, divMode, divModeExecute, isDivModeEnabled, mouseMoveEvent, } from "@tsparticles/plugin-interactivity";
2
3
  import { Repulse } from "./Options/Classes/Repulse.js";
3
- const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, half = 0.5;
4
+ const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
4
5
  export class Repulser extends ExternalInteractorBase {
5
6
  constructor(engine, container) {
6
7
  super(container);
7
- this._clickRepulse = () => {
8
- const container = this.container, repulseOptions = container.actualOptions.interactivity.modes.repulse;
8
+ this._clickRepulse = interactivityData => {
9
+ const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
9
10
  if (!repulseOptions) {
10
11
  return;
11
12
  }
@@ -22,11 +23,11 @@ export class Repulser extends ExternalInteractorBase {
22
23
  if (!repulseDistance || repulseDistance < minDistance) {
23
24
  return;
24
25
  }
25
- const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = container.interactivity.mouse.clickPosition;
26
+ const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = interactivityData.mouse.clickPosition;
26
27
  if (mouseClickPos === undefined) {
27
28
  return;
28
29
  }
29
- const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(p));
30
+ const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
30
31
  for (const particle of query) {
31
32
  const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
32
33
  if (d <= repulseRadius) {
@@ -44,15 +45,15 @@ export class Repulser extends ExternalInteractorBase {
44
45
  repulse.particles = [];
45
46
  }
46
47
  };
47
- this._hoverRepulse = () => {
48
- const container = this.container, mousePos = container.interactivity.mouse.position, repulseRadius = container.retina.repulseModeDistance;
48
+ this._hoverRepulse = interactivityData => {
49
+ const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
49
50
  if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
50
51
  return;
51
52
  }
52
- this._processRepulse(mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
53
+ this._processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
53
54
  };
54
- this._processRepulse = (position, repulseRadius, area, divRepulse) => {
55
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(p)), repulseOptions = container.actualOptions.interactivity.modes.repulse;
55
+ this._processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
56
+ const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
56
57
  if (!repulseOptions) {
57
58
  return;
58
59
  }
@@ -62,8 +63,8 @@ export class Repulser extends ExternalInteractorBase {
62
63
  particle.position.addTo(normVec);
63
64
  }
64
65
  };
65
- this._singleSelectorRepulse = (selector, div) => {
66
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
66
+ this._singleSelectorRepulse = (interactivityData, selector, div) => {
67
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
67
68
  if (!repulse) {
68
69
  return;
69
70
  }
@@ -78,13 +79,13 @@ export class Repulser extends ExternalInteractorBase {
78
79
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
79
80
  ? new Circle(pos.x, pos.y, repulseRadius)
80
81
  : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
81
- this._processRepulse(pos, repulseRadius, area, divRepulse);
82
+ this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
82
83
  });
83
84
  };
84
85
  this._engine = engine;
85
86
  container.repulse ??= { particles: [] };
86
- this.handleClickMode = (mode) => {
87
- const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
87
+ this.handleClickMode = (mode, interactivityData) => {
88
+ const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
88
89
  if (!repulseOpts || mode !== repulseMode) {
89
90
  return;
90
91
  }
@@ -93,7 +94,7 @@ export class Repulser extends ExternalInteractorBase {
93
94
  repulse.clicking = true;
94
95
  repulse.count = 0;
95
96
  for (const particle of container.repulse.particles) {
96
- if (!this.isEnabled(particle)) {
97
+ if (!this.isEnabled(interactivityData, particle)) {
97
98
  continue;
98
99
  }
99
100
  particle.velocity.setTo(particle.initialVelocity);
@@ -111,28 +112,36 @@ export class Repulser extends ExternalInteractorBase {
111
112
  clear() {
112
113
  }
113
114
  init() {
114
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
115
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
115
116
  if (!repulse) {
116
117
  return;
117
118
  }
118
119
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
119
120
  }
120
- interact() {
121
- const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === mouseMoveEvent, events = options.interactivity.events, hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
121
+ interact(interactivityData) {
122
+ const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
123
+ if (!events) {
124
+ return;
125
+ }
126
+ const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
122
127
  if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
123
- this._hoverRepulse();
128
+ this._hoverRepulse(interactivityData);
124
129
  }
125
130
  else if (clickEnabled && isInArray(repulseMode, clickMode)) {
126
- this._clickRepulse();
131
+ this._clickRepulse(interactivityData);
127
132
  }
128
133
  else {
129
134
  divModeExecute(repulseMode, divs, (selector, div) => {
130
- this._singleSelectorRepulse(selector, div);
135
+ this._singleSelectorRepulse(interactivityData, selector, div);
131
136
  });
132
137
  }
133
138
  }
134
- isEnabled(particle) {
135
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
139
+ isEnabled(interactivityData, particle) {
140
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
141
+ if (!events) {
142
+ return false;
143
+ }
144
+ const divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
136
145
  if (!(divRepulse || (hover.enable && !!mouse.position) || (click.enable && mouse.clickPosition))) {
137
146
  return false;
138
147
  }
package/cjs/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  export function loadExternalRepulseInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.2");
3
- engine.register(e => {
4
- e.addInteractor("externalRepulse", async (container) => {
2
+ engine.checkVersion("4.0.0-alpha.4");
3
+ engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity");
5
+ loadInteractivityPlugin(e);
6
+ e.addInteractor?.("externalRepulse", async (container) => {
5
7
  const { Repulser } = await import("./Repulser.js");
6
8
  return new Repulser(engine, container);
7
9
  });
@@ -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.2
7
+ * v4.0.0-alpha.4
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 _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Options/Classes/Repulse.js */ \"./dist/browser/Options/Classes/Repulse.js\");\n\n\nconst repulseMode = \"repulse\",\n minDistance = 0,\n repulseRadiusFactor = 6,\n repulseRadiusPower = 3,\n squarePower = 2,\n minRadius = 0,\n minSpeed = 0,\n easingOffset = 1,\n half = 0.5;\nclass Repulser extends _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.ExternalInteractorBase {\n constructor(engine, container) {\n super(container);\n this._clickRepulse = () => {\n const container = this.container,\n repulseOptions = container.actualOptions.interactivity.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const repulse = container.repulse ?? {\n particles: []\n };\n if (!repulse.finish) {\n repulse.count ??= 0;\n repulse.count++;\n if (repulse.count === container.particles.count) {\n repulse.finish = true;\n }\n }\n if (repulse.clicking) {\n const repulseDistance = container.retina.repulseModeDistance;\n if (!repulseDistance || repulseDistance < minDistance) {\n return;\n }\n const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower),\n mouseClickPos = container.interactivity.mouse.clickPosition;\n if (mouseClickPos === undefined) {\n return;\n }\n const range = new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius),\n query = container.particles.quadTree.query(range, p => this.isEnabled(p));\n for (const particle of query) {\n const {\n dx,\n dy,\n distance\n } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(mouseClickPos, particle.position),\n d = distance ** squarePower,\n velocity = repulseOptions.speed,\n force = -repulseRadius * velocity / d;\n if (d <= repulseRadius) {\n repulse.particles.push(particle);\n const vect = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.create(dx, dy);\n vect.length = force;\n particle.velocity.setTo(vect);\n }\n }\n } else if (repulse.clicking === false) {\n for (const particle of repulse.particles) {\n particle.velocity.setTo(particle.initialVelocity);\n }\n repulse.particles = [];\n }\n };\n this._hoverRepulse = () => {\n const container = this.container,\n mousePos = container.interactivity.mouse.position,\n repulseRadius = container.retina.repulseModeDistance;\n if (!repulseRadius || repulseRadius < minRadius || !mousePos) {\n return;\n }\n this._processRepulse(mousePos, repulseRadius, new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(mousePos.x, mousePos.y, repulseRadius));\n };\n this._processRepulse = (position, repulseRadius, area, divRepulse) => {\n const container = this.container,\n query = container.particles.quadTree.query(area, p => this.isEnabled(p)),\n repulseOptions = container.actualOptions.interactivity.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const {\n easing,\n speed,\n factor,\n maxSpeed\n } = repulseOptions,\n easingFunc = this._engine.getEasing(easing),\n velocity = (divRepulse?.speed ?? speed) * factor;\n for (const particle of query) {\n const {\n dx,\n dy,\n distance\n } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(particle.position, position),\n repulseFactor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.clamp)(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed),\n normVec = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.create(!distance ? velocity : dx / distance * repulseFactor, !distance ? velocity : dy / distance * repulseFactor);\n particle.position.addTo(normVec);\n }\n };\n this._singleSelectorRepulse = (selector, div) => {\n const container = this.container,\n repulse = container.actualOptions.interactivity.modes.repulse;\n if (!repulse) {\n return;\n }\n const query = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.safeDocument)().querySelectorAll(selector);\n if (!query.length) {\n return;\n }\n query.forEach(item => {\n const elem = item,\n pxRatio = container.retina.pixelRatio,\n pos = {\n x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio\n },\n repulseRadius = elem.offsetWidth * half * pxRatio,\n area = div.type === _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.DivType.circle ? new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Circle(pos.x, pos.y, repulseRadius) : new _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio),\n divs = repulse.divs,\n divRepulse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.divMode)(divs, elem);\n this._processRepulse(pos, repulseRadius, area, divRepulse);\n });\n };\n this._engine = engine;\n container.repulse ??= {\n particles: []\n };\n this.handleClickMode = mode => {\n const options = this.container.actualOptions,\n repulseOpts = options.interactivity.modes.repulse;\n if (!repulseOpts || mode !== repulseMode) {\n return;\n }\n container.repulse ??= {\n particles: []\n };\n const repulse = container.repulse;\n repulse.clicking = true;\n repulse.count = 0;\n for (const particle of container.repulse.particles) {\n if (!this.isEnabled(particle)) {\n continue;\n }\n particle.velocity.setTo(particle.initialVelocity);\n }\n repulse.particles = [];\n repulse.finish = false;\n setTimeout(() => {\n if (container.destroyed) {\n return;\n }\n repulse.clicking = false;\n }, repulseOpts.duration * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.millisecondsToSeconds);\n };\n }\n clear() {}\n init() {\n const container = this.container,\n repulse = container.actualOptions.interactivity.modes.repulse;\n if (!repulse) {\n return;\n }\n container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;\n }\n interact() {\n const container = this.container,\n options = container.actualOptions,\n mouseMoveStatus = container.interactivity.status === _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.mouseMoveEvent,\n events = options.interactivity.events,\n hover = events.onHover,\n hoverEnabled = hover.enable,\n hoverMode = hover.mode,\n click = events.onClick,\n clickEnabled = click.enable,\n clickMode = click.mode,\n divs = events.onDiv;\n if (mouseMoveStatus && hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode)) {\n this._hoverRepulse();\n } else if (clickEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, clickMode)) {\n this._clickRepulse();\n } else {\n (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.divModeExecute)(repulseMode, divs, (selector, div) => {\n this._singleSelectorRepulse(selector, div);\n });\n }\n }\n isEnabled(particle) {\n const container = this.container,\n options = container.actualOptions,\n mouse = container.interactivity.mouse,\n events = (particle?.interactivity ?? options.interactivity).events,\n divs = events.onDiv,\n hover = events.onHover,\n click = events.onClick,\n divRepulse = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isDivModeEnabled)(repulseMode, divs);\n if (!(divRepulse || hover.enable && !!mouse.position || click.enable && mouse.clickPosition)) {\n return false;\n }\n const hoverMode = hover.mode,\n clickMode = click.mode;\n return (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode) || (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, clickMode) || divRepulse;\n }\n loadModeOptions(options, ...sources) {\n options.repulse ??= new _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_1__.Repulse();\n for (const source of sources) {\n options.repulse.load(source?.repulse);\n }\n }\n reset() {}\n}\n\n//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/Repulser.js?\n}");
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\",\n minDistance = 0,\n repulseRadiusFactor = 6,\n repulseRadiusPower = 3,\n squarePower = 2,\n minRadius = 0,\n minSpeed = 0,\n easingOffset = 1;\nclass Repulser extends _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.ExternalInteractorBase {\n constructor(engine, container) {\n super(container);\n this._clickRepulse = interactivityData => {\n const container = this.container,\n repulseOptions = container.actualOptions.interactivity?.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const repulse = container.repulse ?? {\n particles: []\n };\n if (!repulse.finish) {\n repulse.count ??= 0;\n repulse.count++;\n if (repulse.count === container.particles.count) {\n repulse.finish = true;\n }\n }\n if (repulse.clicking) {\n const repulseDistance = container.retina.repulseModeDistance;\n if (!repulseDistance || repulseDistance < minDistance) {\n return;\n }\n const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower),\n mouseClickPos = 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),\n query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));\n for (const particle of query) {\n const {\n dx,\n dy,\n distance\n } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(mouseClickPos, particle.position),\n d = distance ** squarePower,\n velocity = repulseOptions.speed,\n force = -repulseRadius * velocity / d;\n if (d <= repulseRadius) {\n repulse.particles.push(particle);\n const vect = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.create(dx, dy);\n vect.length = force;\n particle.velocity.setTo(vect);\n }\n }\n } else if (repulse.clicking === false) {\n for (const particle of repulse.particles) {\n particle.velocity.setTo(particle.initialVelocity);\n }\n repulse.particles = [];\n }\n };\n this._hoverRepulse = interactivityData => {\n const container = this.container,\n mousePos = interactivityData.mouse.position,\n 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 this._processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {\n const container = this.container,\n query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)),\n repulseOptions = container.actualOptions.interactivity?.modes.repulse;\n if (!repulseOptions) {\n return;\n }\n const {\n easing,\n speed,\n factor,\n maxSpeed\n } = repulseOptions,\n easingFunc = this._engine.getEasing(easing),\n velocity = (divRepulse?.speed ?? speed) * factor;\n for (const particle of query) {\n const {\n dx,\n dy,\n distance\n } = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(particle.position, position),\n repulseFactor = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.clamp)(easingFunc(easingOffset - distance / repulseRadius) * velocity, minSpeed, maxSpeed),\n normVec = _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.Vector.create(!distance ? velocity : dx / distance * repulseFactor, !distance ? velocity : dy / distance * repulseFactor);\n particle.position.addTo(normVec);\n }\n };\n this._singleSelectorRepulse = (interactivityData, selector, div) => {\n const container = this.container,\n repulse = container.actualOptions.interactivity?.modes.repulse;\n if (!repulse) {\n return;\n }\n const query = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.safeDocument)().querySelectorAll(selector);\n if (!query.length) {\n return;\n }\n query.forEach(item => {\n const elem = item,\n pxRatio = container.retina.pixelRatio,\n pos = {\n x: (elem.offsetLeft + elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio,\n y: (elem.offsetTop + elem.offsetHeight * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half) * pxRatio\n },\n repulseRadius = elem.offsetWidth * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half * pxRatio,\n 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),\n divs = repulse.divs,\n divRepulse = (0,_tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.divMode)(divs, elem);\n this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);\n });\n };\n this._engine = engine;\n container.repulse ??= {\n particles: []\n };\n this.handleClickMode = (mode, interactivityData) => {\n const options = this.container.actualOptions,\n repulseOpts = options.interactivity?.modes.repulse;\n if (!repulseOpts || mode !== repulseMode) {\n return;\n }\n container.repulse ??= {\n particles: []\n };\n const repulse = container.repulse;\n repulse.clicking = true;\n repulse.count = 0;\n for (const particle of container.repulse.particles) {\n if (!this.isEnabled(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,\n repulse = container.actualOptions.interactivity?.modes.repulse;\n if (!repulse) {\n return;\n }\n container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;\n }\n interact(interactivityData) {\n const container = this.container,\n options = container.actualOptions,\n mouseMoveStatus = interactivityData.status === _tsparticles_plugin_interactivity__WEBPACK_IMPORTED_MODULE_1__.mouseMoveEvent,\n events = options.interactivity?.events;\n if (!events) {\n return;\n }\n const hover = events.onHover,\n hoverEnabled = hover.enable,\n hoverMode = hover.mode,\n click = events.onClick,\n clickEnabled = click.enable,\n clickMode = click.mode,\n divs = events.onDiv;\n if (mouseMoveStatus && hoverEnabled && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode)) {\n this._hoverRepulse(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,\n options = container.actualOptions,\n mouse = interactivityData.mouse,\n events = (particle?.interactivity ?? options.interactivity)?.events;\n if (!events) {\n return false;\n }\n const divs = events.onDiv,\n hover = events.onHover,\n click = events.onClick,\n 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,\n clickMode = click.mode;\n return (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, hoverMode) || (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isInArray)(repulseMode, clickMode) || divRepulse;\n }\n loadModeOptions(options, ...sources) {\n options.repulse ??= new _Options_Classes_Repulse_js__WEBPACK_IMPORTED_MODULE_2__.Repulse();\n for (const source of sources) {\n options.repulse.load(source?.repulse);\n }\n }\n reset() {}\n}\n\n//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/Repulser.js?\n}");
27
27
 
28
28
  /***/ }
29
29
 
package/esm/Repulser.js CHANGED
@@ -1,11 +1,12 @@
1
- import { Circle, DivType, ExternalInteractorBase, Rectangle, Vector, clamp, divMode, divModeExecute, getDistances, isDivModeEnabled, isInArray, millisecondsToSeconds, mouseMoveEvent, safeDocument, } from "@tsparticles/engine";
1
+ import { Circle, Rectangle, Vector, clamp, getDistances, half, isInArray, millisecondsToSeconds, safeDocument, } from "@tsparticles/engine";
2
+ import { DivType, ExternalInteractorBase, divMode, divModeExecute, isDivModeEnabled, mouseMoveEvent, } from "@tsparticles/plugin-interactivity";
2
3
  import { Repulse } from "./Options/Classes/Repulse.js";
3
- const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, half = 0.5;
4
+ const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
4
5
  export class Repulser extends ExternalInteractorBase {
5
6
  constructor(engine, container) {
6
7
  super(container);
7
- this._clickRepulse = () => {
8
- const container = this.container, repulseOptions = container.actualOptions.interactivity.modes.repulse;
8
+ this._clickRepulse = interactivityData => {
9
+ const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
9
10
  if (!repulseOptions) {
10
11
  return;
11
12
  }
@@ -22,11 +23,11 @@ export class Repulser extends ExternalInteractorBase {
22
23
  if (!repulseDistance || repulseDistance < minDistance) {
23
24
  return;
24
25
  }
25
- const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = container.interactivity.mouse.clickPosition;
26
+ const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = interactivityData.mouse.clickPosition;
26
27
  if (mouseClickPos === undefined) {
27
28
  return;
28
29
  }
29
- const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(p));
30
+ const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
30
31
  for (const particle of query) {
31
32
  const { dx, dy, distance } = getDistances(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
32
33
  if (d <= repulseRadius) {
@@ -44,15 +45,15 @@ export class Repulser extends ExternalInteractorBase {
44
45
  repulse.particles = [];
45
46
  }
46
47
  };
47
- this._hoverRepulse = () => {
48
- const container = this.container, mousePos = container.interactivity.mouse.position, repulseRadius = container.retina.repulseModeDistance;
48
+ this._hoverRepulse = interactivityData => {
49
+ const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
49
50
  if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
50
51
  return;
51
52
  }
52
- this._processRepulse(mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
53
+ this._processRepulse(interactivityData, mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
53
54
  };
54
- this._processRepulse = (position, repulseRadius, area, divRepulse) => {
55
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(p)), repulseOptions = container.actualOptions.interactivity.modes.repulse;
55
+ this._processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
56
+ const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
56
57
  if (!repulseOptions) {
57
58
  return;
58
59
  }
@@ -62,8 +63,8 @@ export class Repulser extends ExternalInteractorBase {
62
63
  particle.position.addTo(normVec);
63
64
  }
64
65
  };
65
- this._singleSelectorRepulse = (selector, div) => {
66
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
66
+ this._singleSelectorRepulse = (interactivityData, selector, div) => {
67
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
67
68
  if (!repulse) {
68
69
  return;
69
70
  }
@@ -78,13 +79,13 @@ export class Repulser extends ExternalInteractorBase {
78
79
  }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === DivType.circle
79
80
  ? new Circle(pos.x, pos.y, repulseRadius)
80
81
  : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = divMode(divs, elem);
81
- this._processRepulse(pos, repulseRadius, area, divRepulse);
82
+ this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
82
83
  });
83
84
  };
84
85
  this._engine = engine;
85
86
  container.repulse ??= { particles: [] };
86
- this.handleClickMode = (mode) => {
87
- const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
87
+ this.handleClickMode = (mode, interactivityData) => {
88
+ const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
88
89
  if (!repulseOpts || mode !== repulseMode) {
89
90
  return;
90
91
  }
@@ -93,7 +94,7 @@ export class Repulser extends ExternalInteractorBase {
93
94
  repulse.clicking = true;
94
95
  repulse.count = 0;
95
96
  for (const particle of container.repulse.particles) {
96
- if (!this.isEnabled(particle)) {
97
+ if (!this.isEnabled(interactivityData, particle)) {
97
98
  continue;
98
99
  }
99
100
  particle.velocity.setTo(particle.initialVelocity);
@@ -111,28 +112,36 @@ export class Repulser extends ExternalInteractorBase {
111
112
  clear() {
112
113
  }
113
114
  init() {
114
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
115
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
115
116
  if (!repulse) {
116
117
  return;
117
118
  }
118
119
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
119
120
  }
120
- interact() {
121
- const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === mouseMoveEvent, events = options.interactivity.events, hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
121
+ interact(interactivityData) {
122
+ const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === mouseMoveEvent, events = options.interactivity?.events;
123
+ if (!events) {
124
+ return;
125
+ }
126
+ const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
122
127
  if (mouseMoveStatus && hoverEnabled && isInArray(repulseMode, hoverMode)) {
123
- this._hoverRepulse();
128
+ this._hoverRepulse(interactivityData);
124
129
  }
125
130
  else if (clickEnabled && isInArray(repulseMode, clickMode)) {
126
- this._clickRepulse();
131
+ this._clickRepulse(interactivityData);
127
132
  }
128
133
  else {
129
134
  divModeExecute(repulseMode, divs, (selector, div) => {
130
- this._singleSelectorRepulse(selector, div);
135
+ this._singleSelectorRepulse(interactivityData, selector, div);
131
136
  });
132
137
  }
133
138
  }
134
- isEnabled(particle) {
135
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
139
+ isEnabled(interactivityData, particle) {
140
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
141
+ if (!events) {
142
+ return false;
143
+ }
144
+ const divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = isDivModeEnabled(repulseMode, divs);
136
145
  if (!(divRepulse || (hover.enable && !!mouse.position) || (click.enable && mouse.clickPosition))) {
137
146
  return false;
138
147
  }
package/esm/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  export function loadExternalRepulseInteraction(engine) {
2
- engine.checkVersion("4.0.0-alpha.2");
3
- engine.register(e => {
4
- e.addInteractor("externalRepulse", async (container) => {
2
+ engine.checkVersion("4.0.0-alpha.4");
3
+ engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity");
5
+ loadInteractivityPlugin(e);
6
+ e.addInteractor?.("externalRepulse", async (container) => {
5
7
  const { Repulser } = await import("./Repulser.js");
6
8
  return new Repulser(engine, container);
7
9
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/interaction-external-repulse",
3
- "version": "4.0.0-alpha.2",
3
+ "version": "4.0.0-alpha.4",
4
4
  "description": "tsParticles repulse external interaction",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -87,7 +87,8 @@
87
87
  "./package.json": "./package.json"
88
88
  },
89
89
  "dependencies": {
90
- "@tsparticles/engine": "4.0.0-alpha.2"
90
+ "@tsparticles/engine": "4.0.0-alpha.4",
91
+ "@tsparticles/plugin-interactivity": "4.0.0-alpha.4"
91
92
  },
92
93
  "publishConfig": {
93
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 [8 Jan 2026 at 10:04]</title>
6
+ <title>@tsparticles/interaction-external-repulse [21 Jan 2026 at 14:44]</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.2
7
+ * v4.0.0-alpha.4
8
8
  */
9
9
  /*
10
10
  * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
@@ -16,14 +16,14 @@
16
16
  */
17
17
  (function webpackUniversalModuleDefinition(root, factory) {
18
18
  if(typeof exports === 'object' && typeof module === 'object')
19
- module.exports = factory(require("@tsparticles/engine"));
19
+ module.exports = factory(require("@tsparticles/engine"), require("@tsparticles/plugin-interactivity"));
20
20
  else if(typeof define === 'function' && define.amd)
21
- define(["@tsparticles/engine"], factory);
21
+ define(["@tsparticles/engine", "@tsparticles/plugin-interactivity"], factory);
22
22
  else {
23
- var a = typeof exports === 'object' ? factory(require("@tsparticles/engine")) : factory(root["window"]);
23
+ var a = typeof exports === 'object' ? factory(require("@tsparticles/engine"), require("@tsparticles/plugin-interactivity")) : factory(root["window"], root["window"]);
24
24
  for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
25
25
  }
26
- })(this, (__WEBPACK_EXTERNAL_MODULE__tsparticles_engine__) => {
26
+ })(this, (__WEBPACK_EXTERNAL_MODULE__tsparticles_engine__, __WEBPACK_EXTERNAL_MODULE__tsparticles_plugin_interactivity__) => {
27
27
  return /******/ (() => { // webpackBootstrap
28
28
  /******/ "use strict";
29
29
  /******/ var __webpack_modules__ = ({
@@ -64,7 +64,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
64
64
  \*******************************/
65
65
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
66
66
 
67
- 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\");\nfunction loadExternalRepulseInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.2\");\n engine.register(e => {\n e.addInteractor(\"externalRepulse\", async container => {\n const {\n Repulser\n } = 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//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/index.js?\n}");
67
+ 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\");\nfunction loadExternalRepulseInteraction(engine) {\n engine.checkVersion(\"4.0.0-alpha.4\");\n engine.register(async e => {\n const {\n loadInteractivityPlugin\n } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @tsparticles/plugin-interactivity */ \"@tsparticles/plugin-interactivity\", 19));\n loadInteractivityPlugin(e);\n e.addInteractor?.(\"externalRepulse\", async container => {\n const {\n Repulser\n } = 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//# sourceURL=webpack://@tsparticles/interaction-external-repulse/./dist/browser/index.js?\n}");
68
68
 
69
69
  /***/ },
70
70
 
@@ -76,6 +76,16 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
76
76
 
77
77
  module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
78
78
 
79
+ /***/ },
80
+
81
+ /***/ "@tsparticles/plugin-interactivity"
82
+ /*!***************************************************************************************************************************************************************************!*\
83
+ !*** external {"commonjs":"@tsparticles/plugin-interactivity","commonjs2":"@tsparticles/plugin-interactivity","amd":"@tsparticles/plugin-interactivity","root":"window"} ***!
84
+ \***************************************************************************************************************************************************************************/
85
+ (module) {
86
+
87
+ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_plugin_interactivity__;
88
+
79
89
  /***/ }
80
90
 
81
91
  /******/ });
@@ -114,6 +124,36 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
114
124
  /******/ __webpack_require__.m = __webpack_modules__;
115
125
  /******/
116
126
  /************************************************************************/
127
+ /******/ /* webpack/runtime/create fake namespace object */
128
+ /******/ (() => {
129
+ /******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
130
+ /******/ var leafPrototypes;
131
+ /******/ // create a fake namespace object
132
+ /******/ // mode & 1: value is a module id, require it
133
+ /******/ // mode & 2: merge all properties of value into the ns
134
+ /******/ // mode & 4: return value when already ns object
135
+ /******/ // mode & 16: return value when it's Promise-like
136
+ /******/ // mode & 8|1: behave like require
137
+ /******/ __webpack_require__.t = function(value, mode) {
138
+ /******/ if(mode & 1) value = this(value);
139
+ /******/ if(mode & 8) return value;
140
+ /******/ if(typeof value === 'object' && value) {
141
+ /******/ if((mode & 4) && value.__esModule) return value;
142
+ /******/ if((mode & 16) && typeof value.then === 'function') return value;
143
+ /******/ }
144
+ /******/ var ns = Object.create(null);
145
+ /******/ __webpack_require__.r(ns);
146
+ /******/ var def = {};
147
+ /******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
148
+ /******/ for(var current = mode & 2 && value; (typeof current == 'object' || typeof current == 'function') && !~leafPrototypes.indexOf(current); current = getProto(current)) {
149
+ /******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
150
+ /******/ }
151
+ /******/ def['default'] = () => (value);
152
+ /******/ __webpack_require__.d(ns, def);
153
+ /******/ return ns;
154
+ /******/ };
155
+ /******/ })();
156
+ /******/
117
157
  /******/ /* webpack/runtime/define property getters */
118
158
  /******/ (() => {
119
159
  /******/ // define getter functions for harmony exports
@@ -148,18 +188,6 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
148
188
  /******/ };
149
189
  /******/ })();
150
190
  /******/
151
- /******/ /* webpack/runtime/global */
152
- /******/ (() => {
153
- /******/ __webpack_require__.g = (function() {
154
- /******/ if (typeof globalThis === 'object') return globalThis;
155
- /******/ try {
156
- /******/ return this || new Function('return this')();
157
- /******/ } catch (e) {
158
- /******/ if (typeof window === 'object') return window;
159
- /******/ }
160
- /******/ })();
161
- /******/ })();
162
- /******/
163
191
  /******/ /* webpack/runtime/hasOwnProperty shorthand */
164
192
  /******/ (() => {
165
193
  /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
@@ -224,8 +252,8 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__tsparticles_engine__;
224
252
  /******/ /* webpack/runtime/publicPath */
225
253
  /******/ (() => {
226
254
  /******/ var scriptUrl;
227
- /******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
228
- /******/ var document = __webpack_require__.g.document;
255
+ /******/ if (globalThis.importScripts) scriptUrl = globalThis.location + "";
256
+ /******/ var document = globalThis.document;
229
257
  /******/ if (!scriptUrl && document) {
230
258
  /******/ if (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT')
231
259
  /******/ scriptUrl = document.currentScript.src;
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see tsparticles.interaction.external.repulse.min.js.LICENSE.txt */
2
- !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var r="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(this,(e=>(()=>{var t,r,i={39(e,t,r){r.d(t,{W:()=>n});var i=r(303),o=r(447);class n extends o._{constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,i.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}},246(e,t,r){r.d(t,{Z:()=>s});var i=r(303),o=r(447),n=r(39);class s extends o._{load(e){super.load(e),(0,i.isNull)(e)||(this.divs=(0,i.executeOnSingleOrMultiple)(e.divs,(e=>{const t=new n.W;return t.load(e),t})))}}},303(t){t.exports=e},447(e,t,r){r.d(t,{_:()=>o});var i=r(303);class o{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))}}}},o={};function n(e){var t=o[e];if(void 0!==t)return t.exports;var r=o[e]={exports:{}};return i[e](r,r.exports,n),r.exports}n.m=i,n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.f={},n.e=e=>Promise.all(Object.keys(n.f).reduce(((t,r)=>(n.f[r](e,t),t)),[])),n.u=e=>e+".min.js",n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),t={},r="@tsparticles/interaction-external-repulse:",n.l=(e,i,o,s)=>{if(t[e])t[e].push(i);else{var a,l;if(void 0!==o)for(var c=document.getElementsByTagName("script"),d=0;d<c.length;d++){var p=c[d];if(p.getAttribute("src")==e||p.getAttribute("data-webpack")==r+o){a=p;break}}a||(l=!0,(a=document.createElement("script")).charset="utf-8",n.nc&&a.setAttribute("nonce",n.nc),a.setAttribute("data-webpack",r+o),a.src=e),t[e]=[i];var u=(r,i)=>{a.onerror=a.onload=null,clearTimeout(f);var o=t[e];if(delete t[e],a.parentNode&&a.parentNode.removeChild(a),o&&o.forEach((e=>e(i))),r)return r(i)},f=setTimeout(u.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=u.bind(null,a.onerror),a.onload=u.bind(null,a.onload),l&&document.head.appendChild(a)}},n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;n.g.importScripts&&(e=n.g.location+"");var t=n.g.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var r=t.getElementsByTagName("script");if(r.length)for(var i=r.length-1;i>-1&&(!e||!/^http(s?):/.test(e));)e=r[i--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),n.p=e})(),(()=>{var e={64:0};n.f.j=(t,r)=>{var i=n.o(e,t)?e[t]:void 0;if(0!==i)if(i)r.push(i[2]);else{var o=new Promise(((r,o)=>i=e[t]=[r,o]));r.push(i[2]=o);var s=n.p+n.u(t),a=new Error;n.l(s,(r=>{if(n.o(e,t)&&(0!==(i=e[t])&&(e[t]=void 0),i)){var o=r&&("load"===r.type?"missing":r.type),s=r&&r.target&&r.target.src;a.message="Loading chunk "+t+" failed.\n("+o+": "+s+")",a.name="ChunkLoadError",a.type=o,a.request=s,i[1](a)}}),"chunk-"+t,t)}};var t=(t,r)=>{var i,o,[s,a,l]=r,c=0;if(s.some((t=>0!==e[t]))){for(i in a)n.o(a,i)&&(n.m[i]=a[i]);if(l)l(n)}for(t&&t(r);c<s.length;c++)o=s[c],n.o(e,o)&&e[o]&&e[o][0](),e[o]=0},r=this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var s={};n.r(s),n.d(s,{Repulse:()=>c.Z,RepulseBase:()=>a._,RepulseDiv:()=>l.W,loadExternalRepulseInteraction:()=>d});var a=n(447),l=n(39),c=n(246);function d(e){e.checkVersion("4.0.0-alpha.2"),e.register((t=>{t.addInteractor("externalRepulse",(async t=>{const{Repulser:r}=await n.e(176).then(n.bind(n,176));return new r(e,t)}))}))}return s})()));
2
+ !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)=>(()=>{var r,i,o,n,a={303(t){t.exports=e},591(e,t,r){r.d(t,{Z:()=>a});var i=r(303),o=r(790),n=r(680);class a extends o._{load(e){super.load(e),(0,i.isNull)(e)||(this.divs=(0,i.executeOnSingleOrMultiple)(e.divs,(e=>{const t=new n.W;return t.load(e),t})))}}},680(e,t,r){r.d(t,{W:()=>n});var i=r(303),o=r(790);class n extends o._{constructor(){super(),this.selectors=[]}load(e){super.load(e),(0,i.isNull)(e)||void 0!==e.selectors&&(this.selectors=e.selectors)}}},702(e){e.exports=t},790(e,t,r){r.d(t,{_:()=>o});var i=r(303);class o{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))}}}},s={};function l(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}};return a[e](r,r.exports,l),r.exports}l.m=a,i=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,l.t=function(e,t){if(1&t&&(e=this(e)),8&t)return e;if("object"==typeof e&&e){if(4&t&&e.__esModule)return e;if(16&t&&"function"==typeof e.then)return e}var o=Object.create(null);l.r(o);var n={};r=r||[null,i({}),i([]),i(i)];for(var a=2&t&&e;("object"==typeof a||"function"==typeof a)&&!~r.indexOf(a);a=i(a))Object.getOwnPropertyNames(a).forEach((t=>n[t]=()=>e[t]));return n.default=()=>e,l.d(o,n),o},l.d=(e,t)=>{for(var r in t)l.o(t,r)&&!l.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},l.f={},l.e=e=>Promise.all(Object.keys(l.f).reduce(((t,r)=>(l.f[r](e,t),t)),[])),l.u=e=>e+".min.js",l.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o={},n="@tsparticles/interaction-external-repulse:",l.l=(e,t,r,i)=>{if(o[e])o[e].push(t);else{var a,s;if(void 0!==r)for(var c=document.getElementsByTagName("script"),p=0;p<c.length;p++){var u=c[p];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==n+r){a=u;break}}a||(s=!0,(a=document.createElement("script")).charset="utf-8",l.nc&&a.setAttribute("nonce",l.nc),a.setAttribute("data-webpack",n+r),a.src=e),o[e]=[t];var d=(t,r)=>{a.onerror=a.onload=null,clearTimeout(f);var i=o[e];if(delete o[e],a.parentNode&&a.parentNode.removeChild(a),i&&i.forEach((e=>e(r))),t)return t(r)},f=setTimeout(d.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=d.bind(null,a.onerror),a.onload=d.bind(null,a.onload),s&&document.head.appendChild(a)}},l.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;globalThis.importScripts&&(e=globalThis.location+"");var t=globalThis.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var r=t.getElementsByTagName("script");if(r.length)for(var i=r.length-1;i>-1&&(!e||!/^http(s?):/.test(e));)e=r[i--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),l.p=e})(),(()=>{var e={64:0};l.f.j=(t,r)=>{var i=l.o(e,t)?e[t]:void 0;if(0!==i)if(i)r.push(i[2]);else{var o=new Promise(((r,o)=>i=e[t]=[r,o]));r.push(i[2]=o);var n=l.p+l.u(t),a=new Error;l.l(n,(r=>{if(l.o(e,t)&&(0!==(i=e[t])&&(e[t]=void 0),i)){var o=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;a.message="Loading chunk "+t+" failed.\n("+o+": "+n+")",a.name="ChunkLoadError",a.type=o,a.request=n,i[1](a)}}),"chunk-"+t,t)}};var t=(t,r)=>{var i,o,[n,a,s]=r,c=0;if(n.some((t=>0!==e[t]))){for(i in a)l.o(a,i)&&(l.m[i]=a[i]);if(s)s(l)}for(t&&t(r);c<n.length;c++)o=n[c],l.o(e,o)&&e[o]&&e[o][0](),e[o]=0},r=this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var c={};l.r(c),l.d(c,{Repulse:()=>d.Z,RepulseBase:()=>p._,RepulseDiv:()=>u.W,loadExternalRepulseInteraction:()=>f});var p=l(790),u=l(680),d=l(591);function f(e){e.checkVersion("4.0.0-alpha.4"),e.register((async t=>{const{loadInteractivityPlugin:r}=await Promise.resolve().then(l.t.bind(l,702,19));r(t),t.addInteractor?.("externalRepulse",(async t=>{const{Repulser:r}=await l.e(783).then(l.bind(l,783));return new r(e,t)}))}))}return c})()));
@@ -1 +1 @@
1
- /*! tsParticles Repulse External Interaction v4.0.0-alpha.2 by Matteo Bruni */
1
+ /*! tsParticles Repulse External Interaction v4.0.0-alpha.4 by Matteo Bruni */
@@ -1,7 +1,7 @@
1
- import type { Options } from "@tsparticles/engine";
1
+ import type { InteractivityOptions } from "@tsparticles/plugin-interactivity";
2
2
  import type { RepulseMode } from "../../Types.js";
3
- export type RepulseOptions = Options & {
4
- interactivity: {
3
+ export type RepulseOptions = InteractivityOptions & {
4
+ interactivity?: {
5
5
  modes: RepulseMode;
6
6
  };
7
7
  };
@@ -1,4 +1,4 @@
1
- import type { IModeDiv } from "@tsparticles/engine";
1
+ import type { IModeDiv } from "@tsparticles/plugin-interactivity";
2
2
  import type { IRepulseBase } from "./IRepulseBase.js";
3
3
  export interface IRepulseDiv extends IRepulseBase, IModeDiv {
4
4
  }
@@ -1,13 +1,14 @@
1
- import { type Engine, ExternalInteractorBase, type IModes, type Modes, type Particle, type RecursivePartial } from "@tsparticles/engine";
1
+ import { type Engine, type RecursivePartial } from "@tsparticles/engine";
2
+ import { ExternalInteractorBase, type IInteractivityData, type IModes, type InteractivityParticle, type Modes } from "@tsparticles/plugin-interactivity";
2
3
  import type { IRepulseMode, RepulseContainer, RepulseMode } from "./Types.js";
3
4
  export declare class Repulser extends ExternalInteractorBase<RepulseContainer> {
4
- handleClickMode: (mode: string) => void;
5
+ handleClickMode: (mode: string, interactivityData: IInteractivityData) => void;
5
6
  private readonly _engine;
6
7
  constructor(engine: Engine, container: RepulseContainer);
7
8
  clear(): void;
8
9
  init(): void;
9
- interact(): void;
10
- isEnabled(particle?: Particle): boolean;
10
+ interact(interactivityData: IInteractivityData): void;
11
+ isEnabled(interactivityData: IInteractivityData, particle?: InteractivityParticle): boolean;
11
12
  loadModeOptions(options: Modes & RepulseMode, ...sources: RecursivePartial<(IModes & IRepulseMode) | undefined>[]): void;
12
13
  reset(): void;
13
14
  private readonly _clickRepulse;
package/types/Types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { Container, Particle } from "@tsparticles/engine";
2
1
  import type { IRepulse } from "./Options/Interfaces/IRepulse.js";
2
+ import type { InteractivityContainer } from "@tsparticles/plugin-interactivity";
3
+ import type { Particle } from "@tsparticles/engine";
3
4
  import type { Repulse } from "./Options/Classes/Repulse.js";
4
5
  import type { RepulseOptions } from "./Options/Classes/RepulseOptions.js";
5
6
  export interface IRepulseMode {
@@ -14,7 +15,7 @@ interface IContainerRepulse {
14
15
  finish?: boolean;
15
16
  particles: Particle[];
16
17
  }
17
- export type RepulseContainer = Container & {
18
+ export type RepulseContainer = InteractivityContainer & {
18
19
  actualOptions: RepulseOptions;
19
20
  repulse?: IContainerRepulse;
20
21
  retina: {
package/umd/Repulser.js CHANGED
@@ -4,20 +4,21 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "@tsparticles/engine", "./Options/Classes/Repulse.js"], factory);
7
+ define(["require", "exports", "@tsparticles/engine", "@tsparticles/plugin-interactivity", "./Options/Classes/Repulse.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.Repulser = void 0;
13
13
  const engine_1 = require("@tsparticles/engine");
14
+ const plugin_interactivity_1 = require("@tsparticles/plugin-interactivity");
14
15
  const Repulse_js_1 = require("./Options/Classes/Repulse.js");
15
- const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1, half = 0.5;
16
- class Repulser extends engine_1.ExternalInteractorBase {
16
+ const repulseMode = "repulse", minDistance = 0, repulseRadiusFactor = 6, repulseRadiusPower = 3, squarePower = 2, minRadius = 0, minSpeed = 0, easingOffset = 1;
17
+ class Repulser extends plugin_interactivity_1.ExternalInteractorBase {
17
18
  constructor(engine, container) {
18
19
  super(container);
19
- this._clickRepulse = () => {
20
- const container = this.container, repulseOptions = container.actualOptions.interactivity.modes.repulse;
20
+ this._clickRepulse = interactivityData => {
21
+ const container = this.container, repulseOptions = container.actualOptions.interactivity?.modes.repulse;
21
22
  if (!repulseOptions) {
22
23
  return;
23
24
  }
@@ -34,11 +35,11 @@
34
35
  if (!repulseDistance || repulseDistance < minDistance) {
35
36
  return;
36
37
  }
37
- const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = container.interactivity.mouse.clickPosition;
38
+ const repulseRadius = Math.pow(repulseDistance / repulseRadiusFactor, repulseRadiusPower), mouseClickPos = interactivityData.mouse.clickPosition;
38
39
  if (mouseClickPos === undefined) {
39
40
  return;
40
41
  }
41
- const range = new engine_1.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(p));
42
+ const range = new engine_1.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, p => this.isEnabled(interactivityData, p));
42
43
  for (const particle of query) {
43
44
  const { dx, dy, distance } = (0, engine_1.getDistances)(mouseClickPos, particle.position), d = distance ** squarePower, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
44
45
  if (d <= repulseRadius) {
@@ -56,15 +57,15 @@
56
57
  repulse.particles = [];
57
58
  }
58
59
  };
59
- this._hoverRepulse = () => {
60
- const container = this.container, mousePos = container.interactivity.mouse.position, repulseRadius = container.retina.repulseModeDistance;
60
+ this._hoverRepulse = interactivityData => {
61
+ const container = this.container, mousePos = interactivityData.mouse.position, repulseRadius = container.retina.repulseModeDistance;
61
62
  if (!repulseRadius || repulseRadius < minRadius || !mousePos) {
62
63
  return;
63
64
  }
64
- this._processRepulse(mousePos, repulseRadius, new engine_1.Circle(mousePos.x, mousePos.y, repulseRadius));
65
+ this._processRepulse(interactivityData, mousePos, repulseRadius, new engine_1.Circle(mousePos.x, mousePos.y, repulseRadius));
65
66
  };
66
- this._processRepulse = (position, repulseRadius, area, divRepulse) => {
67
- const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(p)), repulseOptions = container.actualOptions.interactivity.modes.repulse;
67
+ this._processRepulse = (interactivityData, position, repulseRadius, area, divRepulse) => {
68
+ const container = this.container, query = container.particles.quadTree.query(area, p => this.isEnabled(interactivityData, p)), repulseOptions = container.actualOptions.interactivity?.modes.repulse;
68
69
  if (!repulseOptions) {
69
70
  return;
70
71
  }
@@ -74,8 +75,8 @@
74
75
  particle.position.addTo(normVec);
75
76
  }
76
77
  };
77
- this._singleSelectorRepulse = (selector, div) => {
78
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
78
+ this._singleSelectorRepulse = (interactivityData, selector, div) => {
79
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
79
80
  if (!repulse) {
80
81
  return;
81
82
  }
@@ -85,18 +86,18 @@
85
86
  }
86
87
  query.forEach(item => {
87
88
  const elem = item, pxRatio = container.retina.pixelRatio, pos = {
88
- x: (elem.offsetLeft + elem.offsetWidth * half) * pxRatio,
89
- y: (elem.offsetTop + elem.offsetHeight * half) * pxRatio,
90
- }, repulseRadius = elem.offsetWidth * half * pxRatio, area = div.type === engine_1.DivType.circle
89
+ x: (elem.offsetLeft + elem.offsetWidth * engine_1.half) * pxRatio,
90
+ y: (elem.offsetTop + elem.offsetHeight * engine_1.half) * pxRatio,
91
+ }, repulseRadius = elem.offsetWidth * engine_1.half * pxRatio, area = div.type === plugin_interactivity_1.DivType.circle
91
92
  ? new engine_1.Circle(pos.x, pos.y, repulseRadius)
92
- : new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = (0, engine_1.divMode)(divs, elem);
93
- this._processRepulse(pos, repulseRadius, area, divRepulse);
93
+ : new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), divs = repulse.divs, divRepulse = (0, plugin_interactivity_1.divMode)(divs, elem);
94
+ this._processRepulse(interactivityData, pos, repulseRadius, area, divRepulse);
94
95
  });
95
96
  };
96
97
  this._engine = engine;
97
98
  container.repulse ??= { particles: [] };
98
- this.handleClickMode = (mode) => {
99
- const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
99
+ this.handleClickMode = (mode, interactivityData) => {
100
+ const options = this.container.actualOptions, repulseOpts = options.interactivity?.modes.repulse;
100
101
  if (!repulseOpts || mode !== repulseMode) {
101
102
  return;
102
103
  }
@@ -105,7 +106,7 @@
105
106
  repulse.clicking = true;
106
107
  repulse.count = 0;
107
108
  for (const particle of container.repulse.particles) {
108
- if (!this.isEnabled(particle)) {
109
+ if (!this.isEnabled(interactivityData, particle)) {
109
110
  continue;
110
111
  }
111
112
  particle.velocity.setTo(particle.initialVelocity);
@@ -123,28 +124,36 @@
123
124
  clear() {
124
125
  }
125
126
  init() {
126
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
127
+ const container = this.container, repulse = container.actualOptions.interactivity?.modes.repulse;
127
128
  if (!repulse) {
128
129
  return;
129
130
  }
130
131
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
131
132
  }
132
- interact() {
133
- const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === engine_1.mouseMoveEvent, events = options.interactivity.events, hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
133
+ interact(interactivityData) {
134
+ const container = this.container, options = container.actualOptions, mouseMoveStatus = interactivityData.status === plugin_interactivity_1.mouseMoveEvent, events = options.interactivity?.events;
135
+ if (!events) {
136
+ return;
137
+ }
138
+ const hover = events.onHover, hoverEnabled = hover.enable, hoverMode = hover.mode, click = events.onClick, clickEnabled = click.enable, clickMode = click.mode, divs = events.onDiv;
134
139
  if (mouseMoveStatus && hoverEnabled && (0, engine_1.isInArray)(repulseMode, hoverMode)) {
135
- this._hoverRepulse();
140
+ this._hoverRepulse(interactivityData);
136
141
  }
137
142
  else if (clickEnabled && (0, engine_1.isInArray)(repulseMode, clickMode)) {
138
- this._clickRepulse();
143
+ this._clickRepulse(interactivityData);
139
144
  }
140
145
  else {
141
- (0, engine_1.divModeExecute)(repulseMode, divs, (selector, div) => {
142
- this._singleSelectorRepulse(selector, div);
146
+ (0, plugin_interactivity_1.divModeExecute)(repulseMode, divs, (selector, div) => {
147
+ this._singleSelectorRepulse(interactivityData, selector, div);
143
148
  });
144
149
  }
145
150
  }
146
- isEnabled(particle) {
147
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = (0, engine_1.isDivModeEnabled)(repulseMode, divs);
151
+ isEnabled(interactivityData, particle) {
152
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
153
+ if (!events) {
154
+ return false;
155
+ }
156
+ const divs = events.onDiv, hover = events.onHover, click = events.onClick, divRepulse = (0, plugin_interactivity_1.isDivModeEnabled)(repulseMode, divs);
148
157
  if (!(divRepulse || (hover.enable && !!mouse.position) || (click.enable && mouse.clickPosition))) {
149
158
  return false;
150
159
  }
package/umd/index.js CHANGED
@@ -48,10 +48,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
49
  exports.loadExternalRepulseInteraction = loadExternalRepulseInteraction;
50
50
  function loadExternalRepulseInteraction(engine) {
51
- engine.checkVersion("4.0.0-alpha.2");
52
- engine.register(e => {
53
- e.addInteractor("externalRepulse", async (container) => {
54
- const { Repulser } = await (__syncRequire ? Promise.resolve().then(() => __importStar(require("./Repulser.js"))) : new Promise((resolve_1, reject_1) => { require(["./Repulser.js"], resolve_1, reject_1); }).then(__importStar));
51
+ engine.checkVersion("4.0.0-alpha.4");
52
+ engine.register(async (e) => {
53
+ const { loadInteractivityPlugin } = 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
+ loadInteractivityPlugin(e);
55
+ e.addInteractor?.("externalRepulse", async (container) => {
56
+ const { Repulser } = await (__syncRequire ? Promise.resolve().then(() => __importStar(require("./Repulser.js"))) : new Promise((resolve_2, reject_2) => { require(["./Repulser.js"], resolve_2, reject_2); }).then(__importStar));
55
57
  return new Repulser(engine, container);
56
58
  });
57
59
  });
package/176.min.js DELETED
@@ -1,2 +0,0 @@
1
- /*! For license information please see 176.min.js.LICENSE.txt */
2
- (this.webpackChunk_tsparticles_interaction_external_repulse=this.webpackChunk_tsparticles_interaction_external_repulse||[]).push([[176],{176(e,t,i){i.d(t,{Repulser:()=>c});var s=i(303),n=i(246);const o="repulse";class c extends s.ExternalInteractorBase{constructor(e,t){super(t),this._clickRepulse=()=>{const e=this.container,t=e.actualOptions.interactivity.modes.repulse;if(!t)return;const i=e.repulse??{particles:[]};if(i.finish||(i.count??=0,i.count++,i.count===e.particles.count&&(i.finish=!0)),i.clicking){const n=e.retina.repulseModeDistance;if(!n||n<0)return;const o=Math.pow(n/6,3),c=e.interactivity.mouse.clickPosition;if(void 0===c)return;const r=new s.Circle(c.x,c.y,o),a=e.particles.quadTree.query(r,(e=>this.isEnabled(e)));for(const e of a){const{dx:n,dy:r,distance:a}=(0,s.getDistances)(c,e.position),l=a**2,p=-o*t.speed/l;if(l<=o){i.particles.push(e);const t=s.Vector.create(n,r);t.length=p,e.velocity.setTo(t)}}}else if(!1===i.clicking){for(const e of i.particles)e.velocity.setTo(e.initialVelocity);i.particles=[]}},this._hoverRepulse=()=>{const e=this.container,t=e.interactivity.mouse.position,i=e.retina.repulseModeDistance;!i||i<0||!t||this._processRepulse(t,i,new s.Circle(t.x,t.y,i))},this._processRepulse=(e,t,i,n)=>{const o=this.container,c=o.particles.quadTree.query(i,(e=>this.isEnabled(e))),r=o.actualOptions.interactivity.modes.repulse;if(!r)return;const{easing:a,speed:l,factor:p,maxSpeed:u}=r,d=this._engine.getEasing(a),f=(n?.speed??l)*p;for(const i of c){const{dx:n,dy:o,distance:c}=(0,s.getDistances)(i.position,e),r=(0,s.clamp)(d(1-c/t)*f,0,u),a=s.Vector.create(c?n/c*r:f,c?o/c*r:f);i.position.addTo(a)}},this._singleSelectorRepulse=(e,t)=>{const i=this.container,n=i.actualOptions.interactivity.modes.repulse;if(!n)return;const o=(0,s.safeDocument)().querySelectorAll(e);o.length&&o.forEach((e=>{const o=e,c=i.retina.pixelRatio,r={x:(o.offsetLeft+.5*o.offsetWidth)*c,y:(o.offsetTop+.5*o.offsetHeight)*c},a=.5*o.offsetWidth*c,l=t.type===s.DivType.circle?new s.Circle(r.x,r.y,a):new s.Rectangle(o.offsetLeft*c,o.offsetTop*c,o.offsetWidth*c,o.offsetHeight*c),p=n.divs,u=(0,s.divMode)(p,o);this._processRepulse(r,a,l,u)}))},this._engine=e,t.repulse??={particles:[]},this.handleClickMode=e=>{const i=this.container.actualOptions.interactivity.modes.repulse;if(!i||e!==o)return;t.repulse??={particles:[]};const n=t.repulse;n.clicking=!0,n.count=0;for(const e of t.repulse.particles)this.isEnabled(e)&&e.velocity.setTo(e.initialVelocity);n.particles=[],n.finish=!1,setTimeout((()=>{t.destroyed||(n.clicking=!1)}),i.duration*s.millisecondsToSeconds)}}clear(){}init(){const e=this.container,t=e.actualOptions.interactivity.modes.repulse;t&&(e.retina.repulseModeDistance=t.distance*e.retina.pixelRatio)}interact(){const e=this.container,t=e.actualOptions,i=e.interactivity.status===s.mouseMoveEvent,n=t.interactivity.events,c=n.onHover,r=c.enable,a=c.mode,l=n.onClick,p=l.enable,u=l.mode,d=n.onDiv;i&&r&&(0,s.isInArray)(o,a)?this._hoverRepulse():p&&(0,s.isInArray)(o,u)?this._clickRepulse():(0,s.divModeExecute)(o,d,((e,t)=>{this._singleSelectorRepulse(e,t)}))}isEnabled(e){const t=this.container,i=t.actualOptions,n=t.interactivity.mouse,c=(e?.interactivity??i.interactivity).events,r=c.onDiv,a=c.onHover,l=c.onClick,p=(0,s.isDivModeEnabled)(o,r);if(!(p||a.enable&&n.position||l.enable&&n.clickPosition))return!1;const u=a.mode,d=l.mode;return(0,s.isInArray)(o,u)||(0,s.isInArray)(o,d)||p}loadModeOptions(e,...t){e.repulse??=new n.Z;for(const i of t)e.repulse.load(i?.repulse)}reset(){}}}}]);
@@ -1 +0,0 @@
1
- /*! tsParticles Repulse External Interaction v4.0.0-alpha.2 by Matteo Bruni */