@tsparticles/interaction-external-repulse 3.0.0-alpha.1 → 3.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/umd/Repulser.js CHANGED
@@ -15,36 +15,113 @@
15
15
  class Repulser extends engine_1.ExternalInteractorBase {
16
16
  constructor(engine, container) {
17
17
  super(container);
18
+ this._clickRepulse = () => {
19
+ const container = this.container, repulseOptions = container.actualOptions.interactivity.modes.repulse;
20
+ if (!repulseOptions) {
21
+ return;
22
+ }
23
+ const repulse = container.repulse || { particles: [] };
24
+ if (!repulse.finish) {
25
+ if (!repulse.count) {
26
+ repulse.count = 0;
27
+ }
28
+ repulse.count++;
29
+ if (repulse.count === container.particles.count) {
30
+ repulse.finish = true;
31
+ }
32
+ }
33
+ if (repulse.clicking) {
34
+ const repulseDistance = container.retina.repulseModeDistance;
35
+ if (!repulseDistance || repulseDistance < 0) {
36
+ return;
37
+ }
38
+ const repulseRadius = Math.pow(repulseDistance / 6, 3), mouseClickPos = container.interactivity.mouse.clickPosition;
39
+ if (mouseClickPos === undefined) {
40
+ return;
41
+ }
42
+ const range = new engine_1.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, (p) => this.isEnabled(p));
43
+ for (const particle of query) {
44
+ const { dx, dy, distance } = (0, engine_1.getDistances)(mouseClickPos, particle.position), d = distance ** 2, velocity = repulseOptions.speed, force = (-repulseRadius * velocity) / d;
45
+ if (d <= repulseRadius) {
46
+ repulse.particles.push(particle);
47
+ const vect = engine_1.Vector.create(dx, dy);
48
+ vect.length = force;
49
+ particle.velocity.setTo(vect);
50
+ }
51
+ }
52
+ }
53
+ else if (repulse.clicking === false) {
54
+ for (const particle of repulse.particles) {
55
+ particle.velocity.setTo(particle.initialVelocity);
56
+ }
57
+ repulse.particles = [];
58
+ }
59
+ };
60
+ this._hoverRepulse = () => {
61
+ const container = this.container, mousePos = container.interactivity.mouse.position, repulseRadius = container.retina.repulseModeDistance;
62
+ if (!repulseRadius || repulseRadius < 0 || !mousePos) {
63
+ return;
64
+ }
65
+ this._processRepulse(mousePos, repulseRadius, new engine_1.Circle(mousePos.x, mousePos.y, repulseRadius));
66
+ };
67
+ this._processRepulse = (position, repulseRadius, area, divRepulse) => {
68
+ const container = this.container, query = container.particles.quadTree.query(area, (p) => this.isEnabled(p)), repulseOptions = container.actualOptions.interactivity.modes.repulse;
69
+ if (!repulseOptions) {
70
+ return;
71
+ }
72
+ for (const particle of query) {
73
+ const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position), velocity = (divRepulse?.speed ?? repulseOptions.speed) * repulseOptions.factor, repulseFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(repulseOptions.easing)(1 - distance / repulseRadius) * velocity, 0, repulseOptions.maxSpeed), normVec = engine_1.Vector.create(distance === 0 ? velocity : (dx / distance) * repulseFactor, distance === 0 ? velocity : (dy / distance) * repulseFactor);
74
+ particle.position.addTo(normVec);
75
+ }
76
+ };
77
+ this._singleSelectorRepulse = (selector, div) => {
78
+ const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
79
+ if (!repulse) {
80
+ return;
81
+ }
82
+ const query = document.querySelectorAll(selector);
83
+ if (!query.length) {
84
+ return;
85
+ }
86
+ query.forEach((item) => {
87
+ const elem = item, pxRatio = container.retina.pixelRatio, pos = {
88
+ x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
89
+ y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
90
+ }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
91
+ ? 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);
94
+ });
95
+ };
18
96
  this._engine = engine;
19
97
  if (!container.repulse) {
20
98
  container.repulse = { particles: [] };
21
99
  }
22
100
  this.handleClickMode = (mode) => {
23
- const options = this.container.actualOptions, repulse = options.interactivity.modes.repulse;
24
- if (!repulse || mode !== "repulse") {
101
+ const options = this.container.actualOptions, repulseOpts = options.interactivity.modes.repulse;
102
+ if (!repulseOpts || mode !== "repulse") {
25
103
  return;
26
104
  }
27
105
  if (!container.repulse) {
28
106
  container.repulse = { particles: [] };
29
107
  }
30
- container.repulse.clicking = true;
31
- container.repulse.count = 0;
108
+ const repulse = container.repulse;
109
+ repulse.clicking = true;
110
+ repulse.count = 0;
32
111
  for (const particle of container.repulse.particles) {
33
112
  if (!this.isEnabled(particle)) {
34
113
  continue;
35
114
  }
36
115
  particle.velocity.setTo(particle.initialVelocity);
37
116
  }
38
- container.repulse.particles = [];
39
- container.repulse.finish = false;
117
+ repulse.particles = [];
118
+ repulse.finish = false;
40
119
  setTimeout(() => {
41
- if (!container.destroyed) {
42
- if (!container.repulse) {
43
- container.repulse = { particles: [] };
44
- }
45
- container.repulse.clicking = false;
120
+ if (container.destroyed) {
121
+ return;
46
122
  }
47
- }, repulse.duration * 1000);
123
+ repulse.clicking = false;
124
+ }, repulseOpts.duration * 1000);
48
125
  };
49
126
  }
50
127
  clear() {
@@ -57,24 +134,23 @@
57
134
  container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
58
135
  }
59
136
  async interact() {
60
- const container = this.container, options = container.actualOptions, mouseMoveStatus = container.interactivity.status === engine_1.mouseMoveEvent, events = options.interactivity.events, hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, clickEnabled = events.onClick.enable, clickMode = events.onClick.mode, divs = events.onDiv;
137
+ 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;
61
138
  if (mouseMoveStatus && hoverEnabled && (0, engine_1.isInArray)("repulse", hoverMode)) {
62
- this.hoverRepulse();
139
+ this._hoverRepulse();
63
140
  }
64
141
  else if (clickEnabled && (0, engine_1.isInArray)("repulse", clickMode)) {
65
- this.clickRepulse();
142
+ this._clickRepulse();
66
143
  }
67
144
  else {
68
- (0, engine_1.divModeExecute)("repulse", divs, (selector, div) => this.singleSelectorRepulse(selector, div));
145
+ (0, engine_1.divModeExecute)("repulse", divs, (selector, div) => this._singleSelectorRepulse(selector, div));
69
146
  }
70
147
  }
71
148
  isEnabled(particle) {
72
- var _a;
73
- const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events, divs = events.onDiv, divRepulse = (0, engine_1.isDivModeEnabled)("repulse", divs);
74
- if (!(divRepulse || (events.onHover.enable && mouse.position) || (events.onClick.enable && mouse.clickPosition))) {
149
+ 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)("repulse", divs);
150
+ if (!(divRepulse || (hover.enable && mouse.position) || (click.enable && mouse.clickPosition))) {
75
151
  return false;
76
152
  }
77
- const hoverMode = events.onHover.mode, clickMode = events.onClick.mode;
153
+ const hoverMode = hover.mode, clickMode = click.mode;
78
154
  return (0, engine_1.isInArray)("repulse", hoverMode) || (0, engine_1.isInArray)("repulse", clickMode) || divRepulse;
79
155
  }
80
156
  loadModeOptions(options, ...sources) {
@@ -82,92 +158,11 @@
82
158
  options.repulse = new Repulse_1.Repulse();
83
159
  }
84
160
  for (const source of sources) {
85
- options.repulse.load(source === null || source === void 0 ? void 0 : source.repulse);
161
+ options.repulse.load(source?.repulse);
86
162
  }
87
163
  }
88
164
  reset() {
89
165
  }
90
- clickRepulse() {
91
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
92
- if (!repulse) {
93
- return;
94
- }
95
- if (!container.repulse) {
96
- container.repulse = { particles: [] };
97
- }
98
- if (!container.repulse.finish) {
99
- if (!container.repulse.count) {
100
- container.repulse.count = 0;
101
- }
102
- container.repulse.count++;
103
- if (container.repulse.count === container.particles.count) {
104
- container.repulse.finish = true;
105
- }
106
- }
107
- if (container.repulse.clicking) {
108
- const repulseDistance = container.retina.repulseModeDistance;
109
- if (!repulseDistance || repulseDistance < 0) {
110
- return;
111
- }
112
- const repulseRadius = Math.pow(repulseDistance / 6, 3), mouseClickPos = container.interactivity.mouse.clickPosition;
113
- if (mouseClickPos === undefined) {
114
- return;
115
- }
116
- const range = new engine_1.Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius), query = container.particles.quadTree.query(range, (p) => this.isEnabled(p));
117
- for (const particle of query) {
118
- const { dx, dy, distance } = (0, engine_1.getDistances)(mouseClickPos, particle.position), d = distance ** 2, velocity = repulse.speed, force = (-repulseRadius * velocity) / d;
119
- if (d <= repulseRadius) {
120
- container.repulse.particles.push(particle);
121
- const vect = engine_1.Vector.create(dx, dy);
122
- vect.length = force;
123
- particle.velocity.setTo(vect);
124
- }
125
- }
126
- }
127
- else if (container.repulse.clicking === false) {
128
- for (const particle of container.repulse.particles) {
129
- particle.velocity.setTo(particle.initialVelocity);
130
- }
131
- container.repulse.particles = [];
132
- }
133
- }
134
- hoverRepulse() {
135
- const container = this.container, mousePos = container.interactivity.mouse.position, repulseRadius = container.retina.repulseModeDistance;
136
- if (!repulseRadius || repulseRadius < 0 || !mousePos) {
137
- return;
138
- }
139
- this.processRepulse(mousePos, repulseRadius, new engine_1.Circle(mousePos.x, mousePos.y, repulseRadius));
140
- }
141
- processRepulse(position, repulseRadius, area, divRepulse) {
142
- var _a;
143
- const container = this.container, query = container.particles.quadTree.query(area, (p) => this.isEnabled(p)), repulseOptions = container.actualOptions.interactivity.modes.repulse;
144
- if (!repulseOptions) {
145
- return;
146
- }
147
- for (const particle of query) {
148
- const { dx, dy, distance } = (0, engine_1.getDistances)(particle.position, position), velocity = ((_a = divRepulse === null || divRepulse === void 0 ? void 0 : divRepulse.speed) !== null && _a !== void 0 ? _a : repulseOptions.speed) * repulseOptions.factor, repulseFactor = (0, engine_1.clamp)((0, engine_1.getEasing)(repulseOptions.easing)(1 - distance / repulseRadius) * velocity, 0, repulseOptions.maxSpeed), normVec = engine_1.Vector.create(distance === 0 ? velocity : (dx / distance) * repulseFactor, distance === 0 ? velocity : (dy / distance) * repulseFactor);
149
- particle.position.addTo(normVec);
150
- }
151
- }
152
- singleSelectorRepulse(selector, div) {
153
- const container = this.container, repulse = container.actualOptions.interactivity.modes.repulse;
154
- if (!repulse) {
155
- return;
156
- }
157
- const query = document.querySelectorAll(selector);
158
- if (!query.length) {
159
- return;
160
- }
161
- query.forEach((item) => {
162
- const elem = item, pxRatio = container.retina.pixelRatio, pos = {
163
- x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
164
- y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
165
- }, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
166
- ? new engine_1.Circle(pos.x, pos.y, repulseRadius)
167
- : 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);
168
- this.processRepulse(pos, repulseRadius, area, divRepulse);
169
- });
170
- }
171
166
  }
172
167
  exports.Repulser = Repulser;
173
168
  });
package/umd/index.js CHANGED
@@ -25,8 +25,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.loadExternalRepulseInteraction = void 0;
27
27
  const Repulser_1 = require("./Repulser");
28
- async function loadExternalRepulseInteraction(engine) {
29
- await engine.addInteractor("externalRepulse", (container) => new Repulser_1.Repulser(engine, container));
28
+ async function loadExternalRepulseInteraction(engine, refresh = true) {
29
+ await engine.addInteractor("externalRepulse", (container) => new Repulser_1.Repulser(engine, container), refresh);
30
30
  }
31
31
  exports.loadExternalRepulseInteraction = loadExternalRepulseInteraction;
32
32
  __exportStar(require("./Options/Classes/RepulseBase"), exports);