@tsparticles/plugin-absorbers 4.0.0-alpha.3 → 4.0.0-alpha.5

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.
Files changed (64) hide show
  1. package/215.min.js +2 -0
  2. package/215.min.js.LICENSE.txt +1 -0
  3. package/384.min.js +2 -0
  4. package/384.min.js.LICENSE.txt +1 -0
  5. package/688.min.js +2 -0
  6. package/688.min.js.LICENSE.txt +1 -0
  7. package/903.min.js +2 -0
  8. package/903.min.js.LICENSE.txt +1 -0
  9. package/980.min.js +2 -0
  10. package/980.min.js.LICENSE.txt +1 -0
  11. package/browser/AbsorberInstance.js +6 -24
  12. package/browser/AbsorbersInstancesManager.js +47 -0
  13. package/browser/AbsorbersInteractor.js +90 -0
  14. package/browser/AbsorbersPlugin.js +6 -16
  15. package/browser/AbsorbersPluginInstance.js +40 -0
  16. package/browser/index.js +10 -6
  17. package/cjs/AbsorberInstance.js +6 -24
  18. package/cjs/AbsorbersInstancesManager.js +47 -0
  19. package/cjs/AbsorbersInteractor.js +90 -0
  20. package/cjs/AbsorbersPlugin.js +6 -16
  21. package/cjs/AbsorbersPluginInstance.js +40 -0
  22. package/cjs/index.js +10 -6
  23. package/dist_browser_AbsorberInstance_js.js +60 -0
  24. package/dist_browser_AbsorbersInstancesManager_js.js +30 -0
  25. package/dist_browser_AbsorbersInteractor_js.js +60 -0
  26. package/dist_browser_AbsorbersPluginInstance_js.js +30 -0
  27. package/dist_browser_AbsorbersPlugin_js.js +2 -22
  28. package/esm/AbsorberInstance.js +6 -24
  29. package/esm/AbsorbersInstancesManager.js +47 -0
  30. package/esm/AbsorbersInteractor.js +90 -0
  31. package/esm/AbsorbersPlugin.js +6 -16
  32. package/esm/AbsorbersPluginInstance.js +40 -0
  33. package/esm/index.js +10 -6
  34. package/package.json +3 -2
  35. package/report.html +1 -1
  36. package/tsparticles.plugin.absorbers.js +48 -30
  37. package/tsparticles.plugin.absorbers.min.js +1 -1
  38. package/tsparticles.plugin.absorbers.min.js.LICENSE.txt +1 -1
  39. package/types/AbsorberContainer.d.ts +5 -4
  40. package/types/AbsorberInstance.d.ts +5 -5
  41. package/types/AbsorbersInstancesManager.d.ts +14 -0
  42. package/types/AbsorbersInteractor.d.ts +18 -0
  43. package/types/AbsorbersPlugin.d.ts +6 -6
  44. package/types/AbsorbersPluginInstance.d.ts +13 -0
  45. package/types/index.d.ts +1 -2
  46. package/types/types.d.ts +12 -9
  47. package/umd/AbsorberInstance.js +5 -23
  48. package/umd/AbsorbersInstancesManager.js +95 -0
  49. package/umd/AbsorbersInteractor.js +104 -0
  50. package/umd/AbsorbersPlugin.js +40 -16
  51. package/umd/AbsorbersPluginInstance.js +54 -0
  52. package/umd/index.js +11 -10
  53. package/47.min.js +0 -2
  54. package/47.min.js.LICENSE.txt +0 -1
  55. package/browser/Absorbers.js +0 -70
  56. package/browser/Enums/AbsorberClickMode.js +0 -4
  57. package/cjs/Absorbers.js +0 -70
  58. package/cjs/Enums/AbsorberClickMode.js +0 -4
  59. package/esm/Absorbers.js +0 -70
  60. package/esm/Enums/AbsorberClickMode.js +0 -4
  61. package/types/Absorbers.d.ts +0 -21
  62. package/types/Enums/AbsorberClickMode.d.ts +0 -3
  63. package/umd/Absorbers.js +0 -84
  64. package/umd/Enums/AbsorberClickMode.js +0 -17
package/215.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 215.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_absorbers=this.webpackChunk_tsparticles_plugin_absorbers||[]).push([[215],{104(i,t,s){s.d(t,{h:()=>a});var o=s(303);class e{constructor(){this.radius=0,this.mass=0}load(i){(0,o.isNull)(i)||(void 0!==i.mass&&(this.mass=i.mass),void 0!==i.radius&&(this.radius=i.radius))}}class n extends o.ValueWithRandom{constructor(){super(),this.density=5,this.value=50,this.limit=new e}load(i){(0,o.isNull)(i)||(super.load(i),void 0!==i.density&&(this.density=i.density),(0,o.isNumber)(i.limit)?this.limit.radius=i.limit:this.limit.load(i.limit))}}class a{constructor(){this.color=new o.OptionsColor,this.color.value="#000000",this.draggable=!1,this.opacity=1,this.destroy=!0,this.orbits=!1,this.size=new n}load(i){(0,o.isNull)(i)||(void 0!==i.color&&(this.color=o.OptionsColor.create(this.color,i.color)),void 0!==i.draggable&&(this.draggable=i.draggable),this.name=i.name,void 0!==i.opacity&&(this.opacity=i.opacity),void 0!==i.position&&(this.position={},void 0!==i.position.x&&(this.position.x=(0,o.setRangeValue)(i.position.x)),void 0!==i.position.y&&(this.position.y=(0,o.setRangeValue)(i.position.y))),void 0!==i.size&&this.size.load(i.size),void 0!==i.destroy&&(this.destroy=i.destroy),void 0!==i.orbits&&(this.orbits=i.orbits))}}},215(i,t,s){s.d(t,{AbsorberInstance:()=>a});var o=s(303),e=s(104);const n=o.doublePI;class a{constructor(i,t,s,a){this._calcPosition=()=>{const i=(0,o.calcPositionOrRandomFromSizeRanged)({size:this._container.canvas.size,position:this.options.position});return o.Vector.create(i.x,i.y)},this._updateParticlePosition=(i,t)=>{if(i.destroyed)return;const s=this._container,e=s.canvas.size;if(i.needsNewPosition){const t=(0,o.calcPositionOrRandomFromSize)({size:e});i.position.setTo(t),i.velocity.setTo(i.initialVelocity),i.absorberOrbit=void 0,i.needsNewPosition=!1}if(this.options.orbits){if(void 0===i.absorberOrbit&&(i.absorberOrbit=o.Vector.origin,i.absorberOrbit.length=(0,o.getDistance)(i.getPosition(),this.position),i.absorberOrbit.angle=(0,o.getRandom)()*n),i.absorberOrbit.length<=this.size&&!this.options.destroy){const t=Math.min(e.width,e.height),s=1,n=.1,a=.2;i.absorberOrbit.length=t*(s+((0,o.getRandom)()*a-n))}i.absorberOrbitDirection??=i.velocity.x>=0?o.RotateDirection.clockwise:o.RotateDirection.counterClockwise;const a=i.absorberOrbit.length,r=i.absorberOrbit.angle,h=i.absorberOrbitDirection;i.velocity.setTo(o.Vector.origin);const c={x:h===o.RotateDirection.clockwise?Math.cos:Math.sin,y:h===o.RotateDirection.clockwise?Math.sin:Math.cos};i.position.x=this.position.x+a*c.x(r),i.position.y=this.position.y+a*c.y(r),i.absorberOrbit.length-=t.length,i.absorberOrbit.angle+=(i.retina.moveSpeed??0)*s.retina.pixelRatio/o.percentDenominator*s.retina.reduceFactor}else{const s=o.Vector.origin;s.length=t.length,s.angle=t.angle,i.velocity.addTo(s)}},this._container=t,this._engine=i,this.initialPosition=a?o.Vector.create(a.x,a.y):void 0,s instanceof e.h?this.options=s:(this.options=new e.h,this.options.load(s)),this.name=this.options.name,this.opacity=this.options.opacity,this.size=(0,o.getRangeValue)(this.options.size.value)*t.retina.pixelRatio,this.mass=this.size*this.options.size.density*t.retina.reduceFactor;const r=this.options.size.limit;this.limit={radius:r.radius*t.retina.pixelRatio*t.retina.reduceFactor,mass:r.mass},this.color=(0,o.rangeColorToRgb)(this._engine,this.options.color)??{b:0,g:0,r:0},this.position=this.initialPosition?.copy()??this._calcPosition()}attract(i,t){const s=this._container,e=this.options,n=i.getPosition(),{dx:a,dy:r,distance:h}=(0,o.getDistances)(this.position,n),c=o.Vector.create(a,r);if(c.length=this.mass/Math.pow(h,2)*s.retina.reduceFactor,h<this.size+i.getRadius()){const o=.033*i.getRadius()*s.retina.pixelRatio*t.factor;this.size>i.getRadius()&&h<this.size-i.getRadius()||void 0!==i.absorberOrbit&&i.absorberOrbit.length<0?e.destroy?i.destroy():(i.needsNewPosition=!0,this._updateParticlePosition(i,c)):(e.destroy&&(i.size.value-=o),this._updateParticlePosition(i,c)),(this.limit.radius<=0||this.size<this.limit.radius)&&(this.size+=o),(this.limit.mass<=0||this.mass<this.limit.mass)&&(this.mass+=o*this.options.size.density*s.retina.reduceFactor)}else this._updateParticlePosition(i,c)}draw(i){i.translate(this.position.x,this.position.y),i.beginPath(),i.arc(o.originPoint.x,o.originPoint.y,this.size,0,n,!1),i.closePath(),i.fillStyle=(0,o.getStyleFromRgb)(this.color,this._container.hdr,this.opacity),i.fill()}resize(){const i=this.initialPosition;this.position=i&&(0,o.isPointInside)(i,this._container.canvas.size,o.Vector.origin)?i:this._calcPosition()}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Absorbers Plugin v4.0.0-alpha.5 by Matteo Bruni */
package/384.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 384.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_absorbers=this.webpackChunk_tsparticles_plugin_absorbers||[]).push([[384],{104(s,i,t){t.d(i,{h:()=>a});var o=t(303);class e{constructor(){this.radius=0,this.mass=0}load(s){(0,o.isNull)(s)||(void 0!==s.mass&&(this.mass=s.mass),void 0!==s.radius&&(this.radius=s.radius))}}class r extends o.ValueWithRandom{constructor(){super(),this.density=5,this.value=50,this.limit=new e}load(s){(0,o.isNull)(s)||(super.load(s),void 0!==s.density&&(this.density=s.density),(0,o.isNumber)(s.limit)?this.limit.radius=s.limit:this.limit.load(s.limit))}}class a{constructor(){this.color=new o.OptionsColor,this.color.value="#000000",this.draggable=!1,this.opacity=1,this.destroy=!0,this.orbits=!1,this.size=new r}load(s){(0,o.isNull)(s)||(void 0!==s.color&&(this.color=o.OptionsColor.create(this.color,s.color)),void 0!==s.draggable&&(this.draggable=s.draggable),this.name=s.name,void 0!==s.opacity&&(this.opacity=s.opacity),void 0!==s.position&&(this.position={},void 0!==s.position.x&&(this.position.x=(0,o.setRangeValue)(s.position.x)),void 0!==s.position.y&&(this.position.y=(0,o.setRangeValue)(s.position.y))),void 0!==s.size&&this.size.load(s.size),void 0!==s.destroy&&(this.destroy=s.destroy),void 0!==s.orbits&&(this.orbits=s.orbits))}}},384(s,i,t){t.d(i,{AbsorbersPlugin:()=>r});var o=t(303),e=t(104);class r{constructor(s){this.id="absorbers",this._instancesManager=s}async getPlugin(s){const{AbsorbersPluginInstance:i}=await t.e(903).then(t.bind(t,903));return new i(s,this._instancesManager)}loadOptions(s,i,t){(this.needsPlugin(i)||this.needsPlugin(t))&&t?.absorbers&&(i.absorbers=(0,o.executeOnSingleOrMultiple)(t.absorbers,(s=>{const i=new e.h;return i.load(s),i})))}needsPlugin(s){if(!s)return!1;const i=s.absorbers;return(0,o.isArray)(i)?!!i.length:!!i}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Absorbers Plugin v4.0.0-alpha.5 by Matteo Bruni */
package/688.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 688.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_absorbers=this.webpackChunk_tsparticles_plugin_absorbers||[]).push([[688],{104(i,s,t){t.d(s,{h:()=>n});var o=t(303);class r{constructor(){this.radius=0,this.mass=0}load(i){(0,o.isNull)(i)||(void 0!==i.mass&&(this.mass=i.mass),void 0!==i.radius&&(this.radius=i.radius))}}class e extends o.ValueWithRandom{constructor(){super(),this.density=5,this.value=50,this.limit=new r}load(i){(0,o.isNull)(i)||(super.load(i),void 0!==i.density&&(this.density=i.density),(0,o.isNumber)(i.limit)?this.limit.radius=i.limit:this.limit.load(i.limit))}}class n{constructor(){this.color=new o.OptionsColor,this.color.value="#000000",this.draggable=!1,this.opacity=1,this.destroy=!0,this.orbits=!1,this.size=new e}load(i){(0,o.isNull)(i)||(void 0!==i.color&&(this.color=o.OptionsColor.create(this.color,i.color)),void 0!==i.draggable&&(this.draggable=i.draggable),this.name=i.name,void 0!==i.opacity&&(this.opacity=i.opacity),void 0!==i.position&&(this.position={},void 0!==i.position.x&&(this.position.x=(0,o.setRangeValue)(i.position.x)),void 0!==i.position.y&&(this.position.y=(0,o.setRangeValue)(i.position.y))),void 0!==i.size&&this.size.load(i.size),void 0!==i.destroy&&(this.destroy=i.destroy),void 0!==i.orbits&&(this.orbits=i.orbits))}}},688(i,s,t){t.d(s,{AbsorbersInteractor:()=>a});var o=t(702),r=t(303),e=t(104);const n="absorbers";class a extends o.ExternalInteractorBase{constructor(i,s){super(i),this.dragging=!1,this._instancesManager=s,this._instancesManager.initContainer(i),this.handleClickMode=(i,t)=>{const o=this.container,a=o.actualOptions.interactivity.modes.absorbers;if(!a||i!==n)return;const{clickPosition:c}=t.mouse;if(c){if(s.getArray(this.container).some((i=>(0,r.getDistance)(i.position,c)<i.size)))return}const d=(0,r.itemFromArray)(a)??new e.h;this._instancesManager.addAbsorber(o,d,c)}}clear(){}init(){}interact(i,s){for(const t of this.container.particles.filter((s=>this.isEnabled(i,s))))for(const o of this._instancesManager.getArray(this.container)){if(o.options.draggable){const s=i.mouse;if(s.clicking&&s.downPosition){(0,r.getDistance)(o.position,s.downPosition)<=o.size&&(this.dragging=!0,this.draggingAbsorber=o)}else this.dragging=!1,this.draggingAbsorber=void 0;this.dragging&&this.draggingAbsorber==o&&s.position&&(o.position.x=s.position.x,o.position.y=s.position.y)}if(o.attract(t,s),t.destroyed)break}}isEnabled(i,s){const t=this.container.actualOptions,o=i.mouse,e=(s?.interactivity??t.interactivity).events;return!(!o.clickPosition||!e.onClick.enable)&&(0,r.isInArray)(n,e.onClick.mode)}loadModeOptions(i,...s){i.absorbers??=[];for(const t of s)if(t)if((0,r.isArray)(t.absorbers))for(const s of t.absorbers){const t=new e.h;t.load(s),i.absorbers.push(t)}else{const s=new e.h;s.load(t.absorbers),i.absorbers.push(s)}}reset(){}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Absorbers Plugin v4.0.0-alpha.5 by Matteo Bruni */
package/903.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 903.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_absorbers=this.webpackChunk_tsparticles_plugin_absorbers||[]).push([[903],{903(a,s,t){t.d(s,{AbsorbersPluginInstance:()=>i});var n=t(303);class i{constructor(a,s){this._container=a,this._instancesManager=s,this._instancesManager.initContainer(a)}draw(a){for(const s of this._instancesManager.getArray(this._container))s.draw(a)}async init(){const a=this._container.actualOptions.absorbers,s=(0,n.executeOnSingleOrMultiple)(a,(async a=>{await this._instancesManager.addAbsorber(this._container,a)}));(0,n.isArray)(s)?await Promise.all(s):await s}particleUpdate(a,s){for(const t of this._instancesManager.getArray(this._container))if(t.attract(a,s),a.destroyed)break}resize(){for(const a of this._instancesManager.getArray(this._container))a.resize()}stop(){this._instancesManager.clear(this._container)}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Absorbers Plugin v4.0.0-alpha.5 by Matteo Bruni */
package/980.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 980.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_absorbers=this.webpackChunk_tsparticles_plugin_absorbers||[]).push([[980],{980(r,s,t){t.d(s,{AbsorbersInstancesManager:()=>n});var e=t(303);class n{constructor(r){this._containerArrays=new Map,this._engine=r}async addAbsorber(r,s,e){const{AbsorberInstance:n}=await t.e(215).then(t.bind(t,215)),i=new n(this._engine,r,s,e);return this.getArray(r).push(i),i}clear(r){this.initContainer(r),this._containerArrays.set(r,[])}getArray(r){this.initContainer(r);let s=this._containerArrays.get(r);return s||(s=[],this._containerArrays.set(r,s)),s}initContainer(r){this._containerArrays.has(r)||(this._containerArrays.set(r,[]),r.getAbsorber??=s=>{const t=this.getArray(r);return void 0===s||(0,e.isNumber)(s)?t[s??0]:t.find((r=>r.name===s))},r.addAbsorber??=(s,t)=>this.addAbsorber(r,s,t))}removeAbsorber(r,s){const t=this.getArray(r).indexOf(s);t>=0&&this.getArray(r).splice(t,1)}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Absorbers Plugin v4.0.0-alpha.5 by Matteo Bruni */
@@ -1,8 +1,8 @@
1
- import { RotateDirection, Vector, calcPositionOrRandomFromSize, calcPositionOrRandomFromSizeRanged, getDistance, getDistances, getRandom, getRangeValue, getStyleFromRgb, isPointInside, originPoint, percentDenominator, rangeColorToRgb, } from "@tsparticles/engine";
1
+ import { RotateDirection, Vector, calcPositionOrRandomFromSize, calcPositionOrRandomFromSizeRanged, doublePI, getDistance, getDistances, getRandom, getRangeValue, getStyleFromRgb, isPointInside, originPoint, percentDenominator, rangeColorToRgb, } from "@tsparticles/engine";
2
2
  import { Absorber } from "./Options/Classes/Absorber.js";
3
- const squareExp = 2, absorbFactor = 0.033, minOrbitLength = 0, minRadius = 0, minMass = 0, minAngle = 0, double = 2, maxAngle = Math.PI * double, minVelocity = 0;
3
+ const squareExp = 2, absorbFactor = 0.033, minOrbitLength = 0, minRadius = 0, minMass = 0, minAngle = 0, maxAngle = doublePI, minVelocity = 0;
4
4
  export class AbsorberInstance {
5
- constructor(container, engine, options, position) {
5
+ constructor(engine, container, options, position) {
6
6
  this._calcPosition = () => {
7
7
  const exactPosition = calcPositionOrRandomFromSizeRanged({
8
8
  size: this._container.canvas.size,
@@ -64,7 +64,6 @@ export class AbsorberInstance {
64
64
  this.options = new Absorber();
65
65
  this.options.load(options);
66
66
  }
67
- this.dragging = false;
68
67
  this.name = this.options.name;
69
68
  this.opacity = this.options.opacity;
70
69
  this.size = getRangeValue(this.options.size.value) * container.retina.pixelRatio;
@@ -81,28 +80,11 @@ export class AbsorberInstance {
81
80
  };
82
81
  this.position = this.initialPosition?.copy() ?? this._calcPosition();
83
82
  }
84
- attract(particle) {
85
- const container = this._container, options = this.options;
86
- if (options.draggable) {
87
- const mouse = container.interactivity.mouse;
88
- if (mouse.clicking && mouse.downPosition) {
89
- const mouseDist = getDistance(this.position, mouse.downPosition);
90
- if (mouseDist <= this.size) {
91
- this.dragging = true;
92
- }
93
- }
94
- else {
95
- this.dragging = false;
96
- }
97
- if (this.dragging && mouse.position) {
98
- this.position.x = mouse.position.x;
99
- this.position.y = mouse.position.y;
100
- }
101
- }
102
- const pos = particle.getPosition(), { dx, dy, distance } = getDistances(this.position, pos), v = Vector.create(dx, dy);
83
+ attract(particle, delta) {
84
+ const container = this._container, options = this.options, pos = particle.getPosition(), { dx, dy, distance } = getDistances(this.position, pos), v = Vector.create(dx, dy);
103
85
  v.length = (this.mass / Math.pow(distance, squareExp)) * container.retina.reduceFactor;
104
86
  if (distance < this.size + particle.getRadius()) {
105
- const sizeFactor = particle.getRadius() * absorbFactor * container.retina.pixelRatio;
87
+ const sizeFactor = particle.getRadius() * absorbFactor * container.retina.pixelRatio * delta.factor;
106
88
  if ((this.size > particle.getRadius() && distance < this.size - particle.getRadius()) ||
107
89
  (particle.absorberOrbit !== undefined && particle.absorberOrbit.length < minOrbitLength)) {
108
90
  if (options.destroy) {
@@ -0,0 +1,47 @@
1
+ import { isNumber } from "@tsparticles/engine";
2
+ const defaultIndex = 0;
3
+ export class AbsorbersInstancesManager {
4
+ constructor(engine) {
5
+ this._containerArrays = new Map();
6
+ this._engine = engine;
7
+ }
8
+ async addAbsorber(container, options, position) {
9
+ const { AbsorberInstance } = await import("./AbsorberInstance.js"), absorber = new AbsorberInstance(this._engine, container, options, position), array = this.getArray(container);
10
+ array.push(absorber);
11
+ return absorber;
12
+ }
13
+ clear(container) {
14
+ this.initContainer(container);
15
+ this._containerArrays.set(container, []);
16
+ }
17
+ getArray(container) {
18
+ this.initContainer(container);
19
+ let array = this._containerArrays.get(container);
20
+ if (!array) {
21
+ array = [];
22
+ this._containerArrays.set(container, array);
23
+ }
24
+ return array;
25
+ }
26
+ initContainer(container) {
27
+ if (this._containerArrays.has(container)) {
28
+ return;
29
+ }
30
+ this._containerArrays.set(container, []);
31
+ container.getAbsorber ??= (idxOrName) => {
32
+ const array = this.getArray(container);
33
+ return idxOrName === undefined || isNumber(idxOrName)
34
+ ? array[idxOrName ?? defaultIndex]
35
+ : array.find(t => t.name === idxOrName);
36
+ };
37
+ container.addAbsorber ??= (options, position) => {
38
+ return this.addAbsorber(container, options, position);
39
+ };
40
+ }
41
+ removeAbsorber(container, absorber) {
42
+ const index = this.getArray(container).indexOf(absorber), deleteCount = 1;
43
+ if (index >= defaultIndex) {
44
+ this.getArray(container).splice(index, deleteCount);
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,90 @@
1
+ import { ExternalInteractorBase, } from "@tsparticles/plugin-interactivity";
2
+ import { getDistance, isArray, isInArray, itemFromArray, } from "@tsparticles/engine";
3
+ import { Absorber } from "./Options/Classes/Absorber.js";
4
+ const absorbersMode = "absorbers";
5
+ export class AbsorbersInteractor extends ExternalInteractorBase {
6
+ constructor(container, instancesManager) {
7
+ super(container);
8
+ this.dragging = false;
9
+ this._instancesManager = instancesManager;
10
+ this._instancesManager.initContainer(container);
11
+ this.handleClickMode = (mode, interactivityData) => {
12
+ const container = this.container, options = container.actualOptions, absorbers = options.interactivity.modes.absorbers;
13
+ if (!absorbers || mode !== absorbersMode) {
14
+ return;
15
+ }
16
+ const { clickPosition } = interactivityData.mouse;
17
+ if (clickPosition) {
18
+ const existingAbsorber = instancesManager
19
+ .getArray(this.container)
20
+ .some(t => getDistance(t.position, clickPosition) < t.size);
21
+ if (existingAbsorber) {
22
+ return;
23
+ }
24
+ }
25
+ const absorbersModeOptions = itemFromArray(absorbers) ?? new Absorber();
26
+ void this._instancesManager.addAbsorber(container, absorbersModeOptions, clickPosition);
27
+ };
28
+ }
29
+ clear() {
30
+ }
31
+ init() {
32
+ }
33
+ interact(interactivityData, delta) {
34
+ for (const particle of this.container.particles.filter(p => this.isEnabled(interactivityData, p))) {
35
+ for (const absorber of this._instancesManager.getArray(this.container)) {
36
+ if (absorber.options.draggable) {
37
+ const mouse = interactivityData.mouse;
38
+ if (mouse.clicking && mouse.downPosition) {
39
+ const mouseDist = getDistance(absorber.position, mouse.downPosition);
40
+ if (mouseDist <= absorber.size) {
41
+ this.dragging = true;
42
+ this.draggingAbsorber = absorber;
43
+ }
44
+ }
45
+ else {
46
+ this.dragging = false;
47
+ this.draggingAbsorber = undefined;
48
+ }
49
+ if (this.dragging && this.draggingAbsorber == absorber && mouse.position) {
50
+ absorber.position.x = mouse.position.x;
51
+ absorber.position.y = mouse.position.y;
52
+ }
53
+ }
54
+ absorber.attract(particle, delta);
55
+ if (particle.destroyed) {
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ }
61
+ isEnabled(interactivityData, particle) {
62
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity).events;
63
+ if (!mouse.clickPosition || !events.onClick.enable) {
64
+ return false;
65
+ }
66
+ return isInArray(absorbersMode, events.onClick.mode);
67
+ }
68
+ loadModeOptions(options, ...sources) {
69
+ options.absorbers ??= [];
70
+ for (const source of sources) {
71
+ if (!source) {
72
+ continue;
73
+ }
74
+ if (isArray(source.absorbers)) {
75
+ for (const absorber of source.absorbers) {
76
+ const tmp = new Absorber();
77
+ tmp.load(absorber);
78
+ options.absorbers.push(tmp);
79
+ }
80
+ }
81
+ else {
82
+ const tmp = new Absorber();
83
+ tmp.load(source.absorbers);
84
+ options.absorbers.push(tmp);
85
+ }
86
+ }
87
+ }
88
+ reset() {
89
+ }
90
+ }
@@ -1,16 +1,15 @@
1
- import { executeOnSingleOrMultiple, isArray, isInArray, } from "@tsparticles/engine";
1
+ import { executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
2
2
  import { Absorber } from "./Options/Classes/Absorber.js";
3
- import { AbsorberClickMode } from "./Enums/AbsorberClickMode.js";
4
- import { Absorbers } from "./Absorbers.js";
5
3
  export class AbsorbersPlugin {
6
- constructor(engine) {
4
+ constructor(instancesManager) {
7
5
  this.id = "absorbers";
8
- this._engine = engine;
6
+ this._instancesManager = instancesManager;
9
7
  }
10
8
  async getPlugin(container) {
11
- return Promise.resolve(new Absorbers(container, this._engine));
9
+ const { AbsorbersPluginInstance } = await import("./AbsorbersPluginInstance.js");
10
+ return new AbsorbersPluginInstance(container, this._instancesManager);
12
11
  }
13
- loadOptions(options, source) {
12
+ loadOptions(_container, options, source) {
14
13
  if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
15
14
  return;
16
15
  }
@@ -21,11 +20,6 @@ export class AbsorbersPlugin {
21
20
  return tmp;
22
21
  });
23
22
  }
24
- options.interactivity.modes.absorbers = executeOnSingleOrMultiple(source?.interactivity?.modes?.absorbers, absorber => {
25
- const tmp = new Absorber();
26
- tmp.load(absorber);
27
- return tmp;
28
- });
29
23
  }
30
24
  needsPlugin(options) {
31
25
  if (!options) {
@@ -38,10 +32,6 @@ export class AbsorbersPlugin {
38
32
  else if (absorbers) {
39
33
  return true;
40
34
  }
41
- else if (options.interactivity?.events?.onClick?.mode &&
42
- isInArray(AbsorberClickMode.absorber, options.interactivity.events.onClick.mode)) {
43
- return true;
44
- }
45
35
  return false;
46
36
  }
47
37
  }
@@ -0,0 +1,40 @@
1
+ import { executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
2
+ export class AbsorbersPluginInstance {
3
+ constructor(container, instancesManager) {
4
+ this._container = container;
5
+ this._instancesManager = instancesManager;
6
+ this._instancesManager.initContainer(container);
7
+ }
8
+ draw(context) {
9
+ for (const absorber of this._instancesManager.getArray(this._container)) {
10
+ absorber.draw(context);
11
+ }
12
+ }
13
+ async init() {
14
+ const absorbers = this._container.actualOptions.absorbers, promises = executeOnSingleOrMultiple(absorbers, async (absorber) => {
15
+ await this._instancesManager.addAbsorber(this._container, absorber);
16
+ });
17
+ if (isArray(promises)) {
18
+ await Promise.all(promises);
19
+ }
20
+ else {
21
+ await promises;
22
+ }
23
+ }
24
+ particleUpdate(particle, delta) {
25
+ for (const absorber of this._instancesManager.getArray(this._container)) {
26
+ absorber.attract(particle, delta);
27
+ if (particle.destroyed) {
28
+ break;
29
+ }
30
+ }
31
+ }
32
+ resize() {
33
+ for (const absorber of this._instancesManager.getArray(this._container)) {
34
+ absorber.resize();
35
+ }
36
+ }
37
+ stop() {
38
+ this._instancesManager.clear(this._container);
39
+ }
40
+ }
package/browser/index.js CHANGED
@@ -1,8 +1,12 @@
1
- export function loadAbsorbersPlugin(engine) {
2
- engine.checkVersion("4.0.0-alpha.3");
3
- engine.register(async (e) => {
4
- const { AbsorbersPlugin } = await import("./AbsorbersPlugin.js");
5
- e.addPlugin(new AbsorbersPlugin(e));
1
+ export async function loadAbsorbersPlugin(engine) {
2
+ engine.checkVersion("4.0.0-alpha.5");
3
+ await engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity"), { AbsorbersInstancesManager } = await import("./AbsorbersInstancesManager.js"), { AbsorbersPlugin } = await import("./AbsorbersPlugin.js"), instancesManager = new AbsorbersInstancesManager(e);
5
+ await loadInteractivityPlugin(e);
6
+ e.addPlugin(new AbsorbersPlugin(instancesManager));
7
+ e.addInteractor?.("externalAbsorbers", async (container) => {
8
+ const { AbsorbersInteractor } = await import("./AbsorbersInteractor.js");
9
+ return new AbsorbersInteractor(container, instancesManager);
10
+ });
6
11
  });
7
12
  }
8
- export * from "./Enums/AbsorberClickMode.js";
@@ -1,8 +1,8 @@
1
- import { RotateDirection, Vector, calcPositionOrRandomFromSize, calcPositionOrRandomFromSizeRanged, getDistance, getDistances, getRandom, getRangeValue, getStyleFromRgb, isPointInside, originPoint, percentDenominator, rangeColorToRgb, } from "@tsparticles/engine";
1
+ import { RotateDirection, Vector, calcPositionOrRandomFromSize, calcPositionOrRandomFromSizeRanged, doublePI, getDistance, getDistances, getRandom, getRangeValue, getStyleFromRgb, isPointInside, originPoint, percentDenominator, rangeColorToRgb, } from "@tsparticles/engine";
2
2
  import { Absorber } from "./Options/Classes/Absorber.js";
3
- const squareExp = 2, absorbFactor = 0.033, minOrbitLength = 0, minRadius = 0, minMass = 0, minAngle = 0, double = 2, maxAngle = Math.PI * double, minVelocity = 0;
3
+ const squareExp = 2, absorbFactor = 0.033, minOrbitLength = 0, minRadius = 0, minMass = 0, minAngle = 0, maxAngle = doublePI, minVelocity = 0;
4
4
  export class AbsorberInstance {
5
- constructor(container, engine, options, position) {
5
+ constructor(engine, container, options, position) {
6
6
  this._calcPosition = () => {
7
7
  const exactPosition = calcPositionOrRandomFromSizeRanged({
8
8
  size: this._container.canvas.size,
@@ -64,7 +64,6 @@ export class AbsorberInstance {
64
64
  this.options = new Absorber();
65
65
  this.options.load(options);
66
66
  }
67
- this.dragging = false;
68
67
  this.name = this.options.name;
69
68
  this.opacity = this.options.opacity;
70
69
  this.size = getRangeValue(this.options.size.value) * container.retina.pixelRatio;
@@ -81,28 +80,11 @@ export class AbsorberInstance {
81
80
  };
82
81
  this.position = this.initialPosition?.copy() ?? this._calcPosition();
83
82
  }
84
- attract(particle) {
85
- const container = this._container, options = this.options;
86
- if (options.draggable) {
87
- const mouse = container.interactivity.mouse;
88
- if (mouse.clicking && mouse.downPosition) {
89
- const mouseDist = getDistance(this.position, mouse.downPosition);
90
- if (mouseDist <= this.size) {
91
- this.dragging = true;
92
- }
93
- }
94
- else {
95
- this.dragging = false;
96
- }
97
- if (this.dragging && mouse.position) {
98
- this.position.x = mouse.position.x;
99
- this.position.y = mouse.position.y;
100
- }
101
- }
102
- const pos = particle.getPosition(), { dx, dy, distance } = getDistances(this.position, pos), v = Vector.create(dx, dy);
83
+ attract(particle, delta) {
84
+ const container = this._container, options = this.options, pos = particle.getPosition(), { dx, dy, distance } = getDistances(this.position, pos), v = Vector.create(dx, dy);
103
85
  v.length = (this.mass / Math.pow(distance, squareExp)) * container.retina.reduceFactor;
104
86
  if (distance < this.size + particle.getRadius()) {
105
- const sizeFactor = particle.getRadius() * absorbFactor * container.retina.pixelRatio;
87
+ const sizeFactor = particle.getRadius() * absorbFactor * container.retina.pixelRatio * delta.factor;
106
88
  if ((this.size > particle.getRadius() && distance < this.size - particle.getRadius()) ||
107
89
  (particle.absorberOrbit !== undefined && particle.absorberOrbit.length < minOrbitLength)) {
108
90
  if (options.destroy) {
@@ -0,0 +1,47 @@
1
+ import { isNumber } from "@tsparticles/engine";
2
+ const defaultIndex = 0;
3
+ export class AbsorbersInstancesManager {
4
+ constructor(engine) {
5
+ this._containerArrays = new Map();
6
+ this._engine = engine;
7
+ }
8
+ async addAbsorber(container, options, position) {
9
+ const { AbsorberInstance } = await import("./AbsorberInstance.js"), absorber = new AbsorberInstance(this._engine, container, options, position), array = this.getArray(container);
10
+ array.push(absorber);
11
+ return absorber;
12
+ }
13
+ clear(container) {
14
+ this.initContainer(container);
15
+ this._containerArrays.set(container, []);
16
+ }
17
+ getArray(container) {
18
+ this.initContainer(container);
19
+ let array = this._containerArrays.get(container);
20
+ if (!array) {
21
+ array = [];
22
+ this._containerArrays.set(container, array);
23
+ }
24
+ return array;
25
+ }
26
+ initContainer(container) {
27
+ if (this._containerArrays.has(container)) {
28
+ return;
29
+ }
30
+ this._containerArrays.set(container, []);
31
+ container.getAbsorber ??= (idxOrName) => {
32
+ const array = this.getArray(container);
33
+ return idxOrName === undefined || isNumber(idxOrName)
34
+ ? array[idxOrName ?? defaultIndex]
35
+ : array.find(t => t.name === idxOrName);
36
+ };
37
+ container.addAbsorber ??= (options, position) => {
38
+ return this.addAbsorber(container, options, position);
39
+ };
40
+ }
41
+ removeAbsorber(container, absorber) {
42
+ const index = this.getArray(container).indexOf(absorber), deleteCount = 1;
43
+ if (index >= defaultIndex) {
44
+ this.getArray(container).splice(index, deleteCount);
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,90 @@
1
+ import { ExternalInteractorBase, } from "@tsparticles/plugin-interactivity";
2
+ import { getDistance, isArray, isInArray, itemFromArray, } from "@tsparticles/engine";
3
+ import { Absorber } from "./Options/Classes/Absorber.js";
4
+ const absorbersMode = "absorbers";
5
+ export class AbsorbersInteractor extends ExternalInteractorBase {
6
+ constructor(container, instancesManager) {
7
+ super(container);
8
+ this.dragging = false;
9
+ this._instancesManager = instancesManager;
10
+ this._instancesManager.initContainer(container);
11
+ this.handleClickMode = (mode, interactivityData) => {
12
+ const container = this.container, options = container.actualOptions, absorbers = options.interactivity.modes.absorbers;
13
+ if (!absorbers || mode !== absorbersMode) {
14
+ return;
15
+ }
16
+ const { clickPosition } = interactivityData.mouse;
17
+ if (clickPosition) {
18
+ const existingAbsorber = instancesManager
19
+ .getArray(this.container)
20
+ .some(t => getDistance(t.position, clickPosition) < t.size);
21
+ if (existingAbsorber) {
22
+ return;
23
+ }
24
+ }
25
+ const absorbersModeOptions = itemFromArray(absorbers) ?? new Absorber();
26
+ void this._instancesManager.addAbsorber(container, absorbersModeOptions, clickPosition);
27
+ };
28
+ }
29
+ clear() {
30
+ }
31
+ init() {
32
+ }
33
+ interact(interactivityData, delta) {
34
+ for (const particle of this.container.particles.filter(p => this.isEnabled(interactivityData, p))) {
35
+ for (const absorber of this._instancesManager.getArray(this.container)) {
36
+ if (absorber.options.draggable) {
37
+ const mouse = interactivityData.mouse;
38
+ if (mouse.clicking && mouse.downPosition) {
39
+ const mouseDist = getDistance(absorber.position, mouse.downPosition);
40
+ if (mouseDist <= absorber.size) {
41
+ this.dragging = true;
42
+ this.draggingAbsorber = absorber;
43
+ }
44
+ }
45
+ else {
46
+ this.dragging = false;
47
+ this.draggingAbsorber = undefined;
48
+ }
49
+ if (this.dragging && this.draggingAbsorber == absorber && mouse.position) {
50
+ absorber.position.x = mouse.position.x;
51
+ absorber.position.y = mouse.position.y;
52
+ }
53
+ }
54
+ absorber.attract(particle, delta);
55
+ if (particle.destroyed) {
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ }
61
+ isEnabled(interactivityData, particle) {
62
+ const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity).events;
63
+ if (!mouse.clickPosition || !events.onClick.enable) {
64
+ return false;
65
+ }
66
+ return isInArray(absorbersMode, events.onClick.mode);
67
+ }
68
+ loadModeOptions(options, ...sources) {
69
+ options.absorbers ??= [];
70
+ for (const source of sources) {
71
+ if (!source) {
72
+ continue;
73
+ }
74
+ if (isArray(source.absorbers)) {
75
+ for (const absorber of source.absorbers) {
76
+ const tmp = new Absorber();
77
+ tmp.load(absorber);
78
+ options.absorbers.push(tmp);
79
+ }
80
+ }
81
+ else {
82
+ const tmp = new Absorber();
83
+ tmp.load(source.absorbers);
84
+ options.absorbers.push(tmp);
85
+ }
86
+ }
87
+ }
88
+ reset() {
89
+ }
90
+ }
@@ -1,16 +1,15 @@
1
- import { executeOnSingleOrMultiple, isArray, isInArray, } from "@tsparticles/engine";
1
+ import { executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
2
2
  import { Absorber } from "./Options/Classes/Absorber.js";
3
- import { AbsorberClickMode } from "./Enums/AbsorberClickMode.js";
4
- import { Absorbers } from "./Absorbers.js";
5
3
  export class AbsorbersPlugin {
6
- constructor(engine) {
4
+ constructor(instancesManager) {
7
5
  this.id = "absorbers";
8
- this._engine = engine;
6
+ this._instancesManager = instancesManager;
9
7
  }
10
8
  async getPlugin(container) {
11
- return Promise.resolve(new Absorbers(container, this._engine));
9
+ const { AbsorbersPluginInstance } = await import("./AbsorbersPluginInstance.js");
10
+ return new AbsorbersPluginInstance(container, this._instancesManager);
12
11
  }
13
- loadOptions(options, source) {
12
+ loadOptions(_container, options, source) {
14
13
  if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
15
14
  return;
16
15
  }
@@ -21,11 +20,6 @@ export class AbsorbersPlugin {
21
20
  return tmp;
22
21
  });
23
22
  }
24
- options.interactivity.modes.absorbers = executeOnSingleOrMultiple(source?.interactivity?.modes?.absorbers, absorber => {
25
- const tmp = new Absorber();
26
- tmp.load(absorber);
27
- return tmp;
28
- });
29
23
  }
30
24
  needsPlugin(options) {
31
25
  if (!options) {
@@ -38,10 +32,6 @@ export class AbsorbersPlugin {
38
32
  else if (absorbers) {
39
33
  return true;
40
34
  }
41
- else if (options.interactivity?.events?.onClick?.mode &&
42
- isInArray(AbsorberClickMode.absorber, options.interactivity.events.onClick.mode)) {
43
- return true;
44
- }
45
35
  return false;
46
36
  }
47
37
  }
@@ -0,0 +1,40 @@
1
+ import { executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
2
+ export class AbsorbersPluginInstance {
3
+ constructor(container, instancesManager) {
4
+ this._container = container;
5
+ this._instancesManager = instancesManager;
6
+ this._instancesManager.initContainer(container);
7
+ }
8
+ draw(context) {
9
+ for (const absorber of this._instancesManager.getArray(this._container)) {
10
+ absorber.draw(context);
11
+ }
12
+ }
13
+ async init() {
14
+ const absorbers = this._container.actualOptions.absorbers, promises = executeOnSingleOrMultiple(absorbers, async (absorber) => {
15
+ await this._instancesManager.addAbsorber(this._container, absorber);
16
+ });
17
+ if (isArray(promises)) {
18
+ await Promise.all(promises);
19
+ }
20
+ else {
21
+ await promises;
22
+ }
23
+ }
24
+ particleUpdate(particle, delta) {
25
+ for (const absorber of this._instancesManager.getArray(this._container)) {
26
+ absorber.attract(particle, delta);
27
+ if (particle.destroyed) {
28
+ break;
29
+ }
30
+ }
31
+ }
32
+ resize() {
33
+ for (const absorber of this._instancesManager.getArray(this._container)) {
34
+ absorber.resize();
35
+ }
36
+ }
37
+ stop() {
38
+ this._instancesManager.clear(this._container);
39
+ }
40
+ }
package/cjs/index.js CHANGED
@@ -1,8 +1,12 @@
1
- export function loadAbsorbersPlugin(engine) {
2
- engine.checkVersion("4.0.0-alpha.3");
3
- engine.register(async (e) => {
4
- const { AbsorbersPlugin } = await import("./AbsorbersPlugin.js");
5
- e.addPlugin(new AbsorbersPlugin(e));
1
+ export async function loadAbsorbersPlugin(engine) {
2
+ engine.checkVersion("4.0.0-alpha.5");
3
+ await engine.register(async (e) => {
4
+ const { loadInteractivityPlugin } = await import("@tsparticles/plugin-interactivity"), { AbsorbersInstancesManager } = await import("./AbsorbersInstancesManager.js"), { AbsorbersPlugin } = await import("./AbsorbersPlugin.js"), instancesManager = new AbsorbersInstancesManager(e);
5
+ await loadInteractivityPlugin(e);
6
+ e.addPlugin(new AbsorbersPlugin(instancesManager));
7
+ e.addInteractor?.("externalAbsorbers", async (container) => {
8
+ const { AbsorbersInteractor } = await import("./AbsorbersInteractor.js");
9
+ return new AbsorbersInteractor(container, instancesManager);
10
+ });
6
11
  });
7
12
  }
8
- export * from "./Enums/AbsorberClickMode.js";