@tsparticles/plugin-interactivity 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.
Files changed (171) hide show
  1. package/284.min.js +2 -0
  2. package/284.min.js.LICENSE.txt +1 -0
  3. package/721.min.js +2 -0
  4. package/721.min.js.LICENSE.txt +1 -0
  5. package/LICENSE +21 -0
  6. package/README.md +74 -0
  7. package/browser/DivType.js +5 -0
  8. package/browser/ExternalInteractorBase.js +7 -0
  9. package/browser/IExternalInteractor.js +1 -0
  10. package/browser/IInteractivityData.js +1 -0
  11. package/browser/IInteractor.js +1 -0
  12. package/browser/IMouseData.js +1 -0
  13. package/browser/IParticlesInteractor.js +1 -0
  14. package/browser/InteractionManager.js +202 -0
  15. package/browser/InteractivityConstants.js +1 -0
  16. package/browser/InteractivityDetect.js +6 -0
  17. package/browser/InteractivityEventListeners.js +235 -0
  18. package/browser/InteractivityPlugin.js +48 -0
  19. package/browser/InteractivityPluginInstance.js +52 -0
  20. package/browser/InteractorType.js +5 -0
  21. package/browser/Options/Classes/Events/ClickEvent.js +18 -0
  22. package/browser/Options/Classes/Events/DivEvent.js +27 -0
  23. package/browser/Options/Classes/Events/Events.js +26 -0
  24. package/browser/Options/Classes/Events/HoverEvent.js +18 -0
  25. package/browser/Options/Classes/Interactivity.js +22 -0
  26. package/browser/Options/Classes/Modes/Modes.js +25 -0
  27. package/browser/Options/Interfaces/Events/IClickEvent.js +1 -0
  28. package/browser/Options/Interfaces/Events/IDivEvent.js +1 -0
  29. package/browser/Options/Interfaces/Events/IEvents.js +1 -0
  30. package/browser/Options/Interfaces/Events/IHoverEvent.js +1 -0
  31. package/browser/Options/Interfaces/IInteractivity.js +1 -0
  32. package/browser/Options/Interfaces/Modes/IModeDiv.js +1 -0
  33. package/browser/Options/Interfaces/Modes/IModes.js +1 -0
  34. package/browser/ParticlesInteractorBase.js +7 -0
  35. package/browser/index.js +38 -0
  36. package/browser/package.json +1 -0
  37. package/browser/types.js +1 -0
  38. package/browser/utils.js +32 -0
  39. package/cjs/DivType.js +5 -0
  40. package/cjs/ExternalInteractorBase.js +7 -0
  41. package/cjs/IExternalInteractor.js +1 -0
  42. package/cjs/IInteractivityData.js +1 -0
  43. package/cjs/IInteractor.js +1 -0
  44. package/cjs/IMouseData.js +1 -0
  45. package/cjs/IParticlesInteractor.js +1 -0
  46. package/cjs/InteractionManager.js +202 -0
  47. package/cjs/InteractivityConstants.js +1 -0
  48. package/cjs/InteractivityDetect.js +6 -0
  49. package/cjs/InteractivityEventListeners.js +235 -0
  50. package/cjs/InteractivityPlugin.js +48 -0
  51. package/cjs/InteractivityPluginInstance.js +52 -0
  52. package/cjs/InteractorType.js +5 -0
  53. package/cjs/Options/Classes/Events/ClickEvent.js +18 -0
  54. package/cjs/Options/Classes/Events/DivEvent.js +27 -0
  55. package/cjs/Options/Classes/Events/Events.js +26 -0
  56. package/cjs/Options/Classes/Events/HoverEvent.js +18 -0
  57. package/cjs/Options/Classes/Interactivity.js +22 -0
  58. package/cjs/Options/Classes/Modes/Modes.js +25 -0
  59. package/cjs/Options/Interfaces/Events/IClickEvent.js +1 -0
  60. package/cjs/Options/Interfaces/Events/IDivEvent.js +1 -0
  61. package/cjs/Options/Interfaces/Events/IEvents.js +1 -0
  62. package/cjs/Options/Interfaces/Events/IHoverEvent.js +1 -0
  63. package/cjs/Options/Interfaces/IInteractivity.js +1 -0
  64. package/cjs/Options/Interfaces/Modes/IModeDiv.js +1 -0
  65. package/cjs/Options/Interfaces/Modes/IModes.js +1 -0
  66. package/cjs/ParticlesInteractorBase.js +7 -0
  67. package/cjs/index.js +38 -0
  68. package/cjs/package.json +1 -0
  69. package/cjs/types.js +1 -0
  70. package/cjs/utils.js +32 -0
  71. package/dist_browser_InteractivityPluginInstance_js.js +50 -0
  72. package/dist_browser_InteractivityPlugin_js.js +70 -0
  73. package/esm/DivType.js +5 -0
  74. package/esm/ExternalInteractorBase.js +7 -0
  75. package/esm/IExternalInteractor.js +1 -0
  76. package/esm/IInteractivityData.js +1 -0
  77. package/esm/IInteractor.js +1 -0
  78. package/esm/IMouseData.js +1 -0
  79. package/esm/IParticlesInteractor.js +1 -0
  80. package/esm/InteractionManager.js +202 -0
  81. package/esm/InteractivityConstants.js +1 -0
  82. package/esm/InteractivityDetect.js +6 -0
  83. package/esm/InteractivityEventListeners.js +235 -0
  84. package/esm/InteractivityPlugin.js +48 -0
  85. package/esm/InteractivityPluginInstance.js +52 -0
  86. package/esm/InteractorType.js +5 -0
  87. package/esm/Options/Classes/Events/ClickEvent.js +18 -0
  88. package/esm/Options/Classes/Events/DivEvent.js +27 -0
  89. package/esm/Options/Classes/Events/Events.js +26 -0
  90. package/esm/Options/Classes/Events/HoverEvent.js +18 -0
  91. package/esm/Options/Classes/Interactivity.js +22 -0
  92. package/esm/Options/Classes/Modes/Modes.js +25 -0
  93. package/esm/Options/Interfaces/Events/IClickEvent.js +1 -0
  94. package/esm/Options/Interfaces/Events/IDivEvent.js +1 -0
  95. package/esm/Options/Interfaces/Events/IEvents.js +1 -0
  96. package/esm/Options/Interfaces/Events/IHoverEvent.js +1 -0
  97. package/esm/Options/Interfaces/IInteractivity.js +1 -0
  98. package/esm/Options/Interfaces/Modes/IModeDiv.js +1 -0
  99. package/esm/Options/Interfaces/Modes/IModes.js +1 -0
  100. package/esm/ParticlesInteractorBase.js +7 -0
  101. package/esm/index.js +38 -0
  102. package/esm/package.json +1 -0
  103. package/esm/types.js +1 -0
  104. package/esm/utils.js +32 -0
  105. package/package.json +95 -0
  106. package/report.html +40 -0
  107. package/tsparticles.plugin.interactivity.js +395 -0
  108. package/tsparticles.plugin.interactivity.min.js +2 -0
  109. package/tsparticles.plugin.interactivity.min.js.LICENSE.txt +1 -0
  110. package/types/DivType.d.ts +4 -0
  111. package/types/ExternalInteractorBase.d.ts +15 -0
  112. package/types/IExternalInteractor.d.ts +11 -0
  113. package/types/IInteractivityData.d.ts +6 -0
  114. package/types/IInteractor.d.ts +12 -0
  115. package/types/IMouseData.d.ts +9 -0
  116. package/types/IParticlesInteractor.d.ts +7 -0
  117. package/types/InteractionManager.d.ts +27 -0
  118. package/types/InteractivityConstants.d.ts +1 -0
  119. package/types/InteractivityDetect.d.ts +5 -0
  120. package/types/InteractivityEventListeners.d.ts +23 -0
  121. package/types/InteractivityPlugin.d.ts +11 -0
  122. package/types/InteractivityPluginInstance.d.ts +20 -0
  123. package/types/InteractorType.d.ts +4 -0
  124. package/types/Options/Classes/Events/ClickEvent.d.ts +8 -0
  125. package/types/Options/Classes/Events/DivEvent.d.ts +11 -0
  126. package/types/Options/Classes/Events/Events.d.ts +12 -0
  127. package/types/Options/Classes/Events/HoverEvent.d.ts +8 -0
  128. package/types/Options/Classes/Interactivity.d.ts +14 -0
  129. package/types/Options/Classes/Modes/Modes.d.ts +10 -0
  130. package/types/Options/Interfaces/Events/IClickEvent.d.ts +5 -0
  131. package/types/Options/Interfaces/Events/IDivEvent.d.ts +8 -0
  132. package/types/Options/Interfaces/Events/IEvents.d.ts +9 -0
  133. package/types/Options/Interfaces/Events/IHoverEvent.d.ts +5 -0
  134. package/types/Options/Interfaces/IInteractivity.d.ts +9 -0
  135. package/types/Options/Interfaces/Modes/IModeDiv.d.ts +4 -0
  136. package/types/Options/Interfaces/Modes/IModes.d.ts +1 -0
  137. package/types/ParticlesInteractorBase.d.ts +15 -0
  138. package/types/index.d.ts +19 -0
  139. package/types/types.d.ts +32 -0
  140. package/types/utils.d.ts +7 -0
  141. package/umd/DivType.js +18 -0
  142. package/umd/ExternalInteractorBase.js +21 -0
  143. package/umd/IExternalInteractor.js +12 -0
  144. package/umd/IInteractivityData.js +12 -0
  145. package/umd/IInteractor.js +12 -0
  146. package/umd/IMouseData.js +12 -0
  147. package/umd/IParticlesInteractor.js +12 -0
  148. package/umd/InteractionManager.js +216 -0
  149. package/umd/InteractivityConstants.js +14 -0
  150. package/umd/InteractivityDetect.js +19 -0
  151. package/umd/InteractivityEventListeners.js +249 -0
  152. package/umd/InteractivityPlugin.js +96 -0
  153. package/umd/InteractivityPluginInstance.js +66 -0
  154. package/umd/InteractorType.js +18 -0
  155. package/umd/Options/Classes/Events/ClickEvent.js +32 -0
  156. package/umd/Options/Classes/Events/DivEvent.js +41 -0
  157. package/umd/Options/Classes/Events/Events.js +40 -0
  158. package/umd/Options/Classes/Events/HoverEvent.js +32 -0
  159. package/umd/Options/Classes/Interactivity.js +36 -0
  160. package/umd/Options/Classes/Modes/Modes.js +39 -0
  161. package/umd/Options/Interfaces/Events/IClickEvent.js +12 -0
  162. package/umd/Options/Interfaces/Events/IDivEvent.js +12 -0
  163. package/umd/Options/Interfaces/Events/IEvents.js +12 -0
  164. package/umd/Options/Interfaces/Events/IHoverEvent.js +12 -0
  165. package/umd/Options/Interfaces/IInteractivity.js +12 -0
  166. package/umd/Options/Interfaces/Modes/IModeDiv.js +12 -0
  167. package/umd/Options/Interfaces/Modes/IModes.js +12 -0
  168. package/umd/ParticlesInteractorBase.js +21 -0
  169. package/umd/index.js +88 -0
  170. package/umd/types.js +12 -0
  171. package/umd/utils.js +48 -0
package/284.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 284.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_interactivity=this.webpackChunk_tsparticles_plugin_interactivity||[]).push([[284],{284(t,i,e){e.d(i,{InteractivityPlugin:()=>o});var n=e(303),s=e(688);class o{constructor(t){this._engine=t,this.id="interactivity"}async getPlugin(t){const{InteractivityPluginInstance:i}=await e.e(721).then(e.bind(e,721));return new i(this._engine,t)}loadOptions(t,i,e){if(!this.needsPlugin())return;let n=i.interactivity;n?.load||(i.interactivity=n=new s.k(this._engine,t)),n.load(e?.interactivity);const o=this._engine.interactors?.get(t);if(o)for(const t of o)t.loadOptions&&t.loadOptions(i,e)}loadParticlesOptions(t,i,e){e?.interactivity&&(i.interactivity=(0,n.deepExtend)({},e.interactivity));const s=this._engine.interactors?.get(t);if(s)for(const t of s)t.loadParticlesOptions&&t.loadParticlesOptions(i,e)}needsPlugin(){return!0}}},688(t,i,e){e.d(i,{k:()=>d});var n=e(303);class s{constructor(){this.enable=!1,this.mode=[]}load(t){(0,n.isNull)(t)||(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.mode&&(this.mode=t.mode))}}var o=e(897);class a{constructor(){this.enable=!1,this.mode=[]}load(t){(0,n.isNull)(t)||(void 0!==t.enable&&(this.enable=t.enable),void 0!==t.mode&&(this.mode=t.mode))}}class l{constructor(){this.onClick=new s,this.onDiv=new o.G,this.onHover=new a}load(t){if((0,n.isNull)(t))return;this.onClick.load(t.onClick);const i=t.onDiv;void 0!==i&&(this.onDiv=(0,n.executeOnSingleOrMultiple)(i,(t=>{const i=new o.G;return i.load(t),i}))),this.onHover.load(t.onHover)}}var c=e(784),r=e(617);class d{constructor(t,i){this.detectsOn=c.h.window,this.events=new l,this.modes=new r.d(t,i)}load(t){if((0,n.isNull)(t))return;const i=t.detectsOn;void 0!==i&&(this.detectsOn=i),this.events.load(t.events),this.modes.load(t.modes)}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Interactivity Plugin v4.0.0-alpha.4 by Matteo Bruni */
package/721.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 721.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_interactivity=this.webpackChunk_tsparticles_plugin_interactivity||[]).push([[721],{721(t,e,i){i.d(e,{InteractivityPluginInstance:()=>l});var n=i(303),s=i(170),a=i(784);class r{constructor(t,e){this._canPush=!0,this._doMouseTouchClick=t=>{const e=this._container,i=this._interactionManager,s=e.actualOptions;if(this._canPush){const t=i.interactivityData.mouse,e=t.position;if(!e)return;t.clickPosition={...e},t.clickTime=Date.now();const a=s.interactivity?.events.onClick;if(!a?.mode)return;(0,n.executeOnSingleOrMultiple)(a.mode,(t=>{i.handleClickMode(t)}))}"touchend"===t.type&&setTimeout((()=>{this._mouseTouchFinish()}),n.touchDelay)},this._handleVisibilityChange=()=>{this._mouseTouchFinish()},this._manageInteractivityListeners=(t,e)=>{const i=this._handlers,a=this._container,r=this._interactionManager,o=a.actualOptions,c=r.interactivityData.element;if(!c)return;const h=c,l=a.canvas;l.setPointerEvents(h===l.element?"initial":"none"),(o.interactivity?.events.onHover.enable||o.interactivity?.events.onClick.enable)&&((0,n.manageListener)(c,s.Rb,i.mouseMove,e),(0,n.manageListener)(c,s.s7,i.touchStart,e),(0,n.manageListener)(c,s.DG,i.touchMove,e),o.interactivity.events.onClick.enable?((0,n.manageListener)(c,s.Bp,i.touchEndClick,e),(0,n.manageListener)(c,s.vo,i.mouseUp,e),(0,n.manageListener)(c,s.ms,i.mouseDown,e)):(0,n.manageListener)(c,s.Bp,i.touchEnd,e),(0,n.manageListener)(c,t,i.mouseLeave,e),(0,n.manageListener)(c,s.G3,i.touchCancel,e))},this._manageListeners=t=>{const e=this._handlers,i=this._container,r=this._interactionManager,o=i.actualOptions,c=o.interactivity?.detectsOn,h=i.canvas.element;let l=s.Z0;c===a.h.window?(r.interactivityData.element=globalThis,l=s.sf):c===a.h.parent&&h?r.interactivityData.element=h.parentElement??h.parentNode:r.interactivityData.element=h,this._manageInteractivityListeners(l,t),(0,n.manageListener)(document,n.visibilityChangeEvent,e.visibilityChange,t,!1)},this._mouseDown=()=>{const{interactivityData:t}=this._interactionManager,{mouse:e}=t;e.clicking=!0,e.downPosition=e.position},this._mouseTouchClick=t=>{const e=this._container,i=this._interactionManager,n=e.actualOptions,{mouse:s}=i.interactivityData;s.inside=!0;let a=!1;const r=s.position;if(r&&n.interactivity?.events.onClick.enable){for(const t of e.plugins)if(t.clickPositionValid&&(a=t.clickPositionValid(r),a))break;a||this._doMouseTouchClick(t),s.clicking=!1}},this._mouseTouchFinish=()=>{const{interactivityData:t}=this._interactionManager,{mouse:e}=t;delete e.position,delete e.clickPosition,delete e.downPosition,t.status=s.Z0,e.inside=!1,e.clicking=!1},this._mouseTouchMove=t=>{const e=this._container,i=this._interactionManager,r=e.actualOptions,o=i.interactivityData,c=e.canvas.element;if(!o.element)return;let h;if(o.mouse.inside=!0,t.type.startsWith("pointer")){this._canPush=!0;const e=t;if(o.element===globalThis){if(c){const t=c.getBoundingClientRect();h={x:e.clientX-t.left,y:e.clientY-t.top}}}else if(r.interactivity?.detectsOn===a.h.parent){const t=e.target,i=e.currentTarget;if(c){const s=t.getBoundingClientRect(),a=i.getBoundingClientRect(),r=c.getBoundingClientRect();h={x:e.offsetX+n.double*s.left-(a.left+r.left),y:e.offsetY+n.double*s.top-(a.top+r.top)}}else h={x:e.offsetX,y:e.offsetY}}else e.target===c&&(h={x:e.offsetX,y:e.offsetY})}else if(this._canPush="touchmove"!==t.type,c){const e=t,i=e.touches[e.touches.length-n.lengthOffset],s=c.getBoundingClientRect();if(!i)return;h={x:i.clientX-s.left,y:i.clientY-s.top}}const l=e.retina.pixelRatio;h&&(h.x*=l,h.y*=l),o.mouse.position=h,o.status=s.Rb},this._touchEnd=t=>{const e=t,i=Array.from(e.changedTouches);for(const t of i)this._touches.delete(t.identifier);this._mouseTouchFinish()},this._touchEndClick=t=>{const e=t,i=Array.from(e.changedTouches);for(const t of i)this._touches.delete(t.identifier);this._mouseTouchClick(t)},this._touchStart=t=>{const e=t,i=Array.from(e.changedTouches);for(const t of i)this._touches.set(t.identifier,performance.now());this._mouseTouchMove(t)},this._container=t,this._interactionManager=e,this._touches=new Map,this._handlers={mouseDown:()=>{this._mouseDown()},mouseLeave:()=>{this._mouseTouchFinish()},mouseMove:t=>{this._mouseTouchMove(t)},mouseUp:t=>{this._mouseTouchClick(t)},touchStart:t=>{this._touchStart(t)},touchMove:t=>{this._mouseTouchMove(t)},touchEnd:t=>{this._touchEnd(t)},touchCancel:t=>{this._touchEnd(t)},touchEndClick:t=>{this._touchEndClick(t)},visibilityChange:()=>{this._handleVisibilityChange()}}}addListeners(){this._manageListeners(!0)}removeListeners(){this._manageListeners(!1)}}var o=i(309);class c{constructor(t,e){this.container=e,this._intersectionManager=t=>{const{container:e}=this;if(!e.destroyed&&e.actualOptions.pauseOnOutsideViewport)for(const i of t)i.target===this.interactivityData.element&&(i.isIntersecting?e.play():e.pause())},this._engine=t,this._interactors=[],this._externalInteractors=[],this._particleInteractors=[],this._clickHandlers=new Map,this._eventListeners=new r(e,this),this.interactivityData={mouse:{clicking:!1,inside:!1}},this._intersectionObserver=(0,n.safeIntersectionObserver)((t=>{this._intersectionManager(t)}))}addClickHandler(t){const{container:e,interactivityData:i}=this;if(e.destroyed)return;const a=i.element;if(!a)return;const r=(i,n,s)=>{if(e.destroyed)return;const a=e.retina.pixelRatio,r={x:n.x*a,y:n.y*a},o=e.particles.quadTree.queryCircle(r,s*a);t(i,o)};let o=!1,c=!1;this._clickHandlers.set(s.xO,(t=>{if(e.destroyed)return;const i=t,s={x:i.offsetX,y:i.offsetY};r(t,s,n.clickRadius)})),this._clickHandlers.set(s.s7,(()=>{e.destroyed||(o=!0,c=!1)})),this._clickHandlers.set(s.DG,(()=>{e.destroyed||(c=!0)})),this._clickHandlers.set(s.Bp,(t=>{if(!e.destroyed){if(o&&!c){const i=t,s=i.touches[i.touches.length-n.touchEndLengthOffset];if(!s)return;const a=e.canvas.element,o=a?a.getBoundingClientRect():void 0,c={x:s.clientX-(o?o.left:n.minCoordinate),y:s.clientY-(o?o.top:n.minCoordinate)};r(t,c,Math.max(s.radiusX,s.radiusY))}o=!1,c=!1}})),this._clickHandlers.set(s.G3,(()=>{e.destroyed||(o=!1,c=!1)}));for(const[t,e]of this._clickHandlers)a.addEventListener(t,e)}addListeners(){this._eventListeners.addListeners()}clearClickHandlers(){const{container:t,interactivityData:e}=this;if(!t.destroyed){for(const[t,i]of this._clickHandlers)e.element?.removeEventListener(t,i);this._clickHandlers.clear()}}externalInteract(t){for(const e of this._externalInteractors){const{interactivityData:i}=this;e.isEnabled(i)&&e.interact(i,t)}}handleClickMode(t){if(this.container.destroyed)return;const{interactivityData:e}=this;for(const i of this._externalInteractors)i.handleClickMode?.(t,e)}async init(){const t=await(this._engine.getInteractors?.(this.container,!0));if(t){this._interactors=t,this._externalInteractors=[],this._particleInteractors=[];for(const t of this._interactors){switch(t.type){case o.e.external:this._externalInteractors.push(t);break;case o.e.particles:this._particleInteractors.push(t)}t.init()}}}particlesInteract(t,e){const{interactivityData:i}=this;for(const i of this._externalInteractors)i.clear(t,e);for(const n of this._particleInteractors)n.isEnabled(t,i)&&n.interact(t,i,e)}removeListeners(){this._eventListeners.removeListeners()}reset(t){const{interactivityData:e}=this;for(const i of this._externalInteractors)i.isEnabled(e)&&i.reset(e,t);for(const i of this._particleInteractors)i.isEnabled(t,e)&&i.reset(e,t)}startObserving(){const{interactivityData:t}=this;t.element instanceof HTMLElement&&this._intersectionObserver&&this._intersectionObserver.observe(t.element)}stopObserving(){const{interactivityData:t}=this;t.element instanceof HTMLElement&&this._intersectionObserver&&this._intersectionObserver.unobserve(t.element)}}var h=i(688);class l{constructor(t,e){this._container=e,this._engine=t,this.interactionManager=new c(t,e),this._container.addClickHandler=t=>{this.interactionManager.addClickHandler(t)}}addClickHandler(t){this.interactionManager.addClickHandler(t)}clearClickHandlers(){this.interactionManager.clearClickHandlers()}destroy(){this.clearClickHandlers(),this._engine.interactors?.delete(this._container)}particleCreated(t){const e=t,i=new h.k(this._engine,this._container);i.load(this._container.actualOptions.interactivity),i.load(e.options.interactivity),e.interactivity=i}particleReset(t){this.interactionManager.reset(t)}postParticleUpdate(t,e){this.interactionManager.particlesInteract(t,e)}postUpdate(t){this.interactionManager.externalInteract(t)}async preInit(){await this.interactionManager.init()}async redrawInit(){await this.interactionManager.init()}start(){return this.interactionManager.addListeners(),this.interactionManager.startObserving(),Promise.resolve()}stop(){this.interactionManager.removeListeners(),this.interactionManager.stopObserving()}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Interactivity Plugin v4.0.0-alpha.4 by Matteo Bruni */
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Matteo Bruni
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ [![banner](https://particles.js.org/images/banner2.png)](https://particles.js.org)
2
+
3
+ # tsParticles Interactivity Plugin
4
+
5
+ [![jsDelivr](https://data.jsdelivr.com/v1/package/npm/@tsparticles/plugin-interactivity/badge)](https://www.jsdelivr.com/package/npm/@tsparticles/plugin-interactivity)
6
+ [![npmjs](https://badge.fury.io/js/@tsparticles/plugin-interactivity.svg)](https://www.npmjs.com/package/@tsparticles/plugin-interactivity)
7
+ [![npmjs](https://img.shields.io/npm/dt/@tsparticles/plugin-interactivity)](https://www.npmjs.com/package/@tsparticles/plugin-interactivity) [![GitHub Sponsors](https://img.shields.io/github/sponsors/matteobruni)](https://github.com/sponsors/matteobruni)
8
+
9
+ [tsParticles](https://github.com/tsparticles/tsparticles) plugin for handling interactivity sickness CSS value.
10
+
11
+ ## How to use it
12
+
13
+ ### CDN / Vanilla JS / jQuery
14
+
15
+ The CDN/Vanilla version JS has one required file in vanilla configuration:
16
+
17
+ Including the `tsparticles.plugin.interactivity.min.js` file will export the function to load the plugin:
18
+
19
+ ```javascript
20
+ loadInteractivityPlugin;
21
+ ```
22
+
23
+ ### Usage
24
+
25
+ Once the scripts are loaded you can set up `tsParticles` and the plugin like this:
26
+
27
+ ```javascript
28
+ (async () => {
29
+ await loadInteractivityPlugin(tsParticles);
30
+
31
+ await tsParticles.load({
32
+ id: "tsparticles",
33
+ options: {
34
+ /* options */
35
+ },
36
+ });
37
+ })();
38
+ ```
39
+
40
+ ### ESM / CommonJS
41
+
42
+ This package is compatible also with ES or CommonJS modules, firstly this needs to be installed, like this:
43
+
44
+ ```shell
45
+ $ npm install @tsparticles/plugin-interactivity
46
+ ```
47
+
48
+ or
49
+
50
+ ```shell
51
+ $ yarn add @tsparticles/plugin-interactivity
52
+ ```
53
+
54
+ Then you need to import it in the app, like this:
55
+
56
+ ```javascript
57
+ const { tsParticles } = require("@tsparticles/engine");
58
+ const { loadInteractivityPlugin } = require("@tsparticles/plugin-interactivity");
59
+
60
+ (async () => {
61
+ await loadInteractivityPlugin(tsParticles);
62
+ })();
63
+ ```
64
+
65
+ or
66
+
67
+ ```javascript
68
+ import { tsParticles } from "@tsparticles/engine";
69
+ import { loadInteractivityPlugin } from "@tsparticles/plugin-interactivity";
70
+
71
+ (async () => {
72
+ await loadInteractivityPlugin(tsParticles);
73
+ })();
74
+ ```
@@ -0,0 +1,5 @@
1
+ export var DivType;
2
+ (function (DivType) {
3
+ DivType["circle"] = "circle";
4
+ DivType["rectangle"] = "rectangle";
5
+ })(DivType || (DivType = {}));
@@ -0,0 +1,7 @@
1
+ import { InteractorType } from "./InteractorType.js";
2
+ export class ExternalInteractorBase {
3
+ constructor(container) {
4
+ this.type = InteractorType.external;
5
+ this.container = container;
6
+ }
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,202 @@
1
+ import { clickRadius, minCoordinate, safeIntersectionObserver, touchEndLengthOffset, } from "@tsparticles/engine";
2
+ import { clickEvent, touchCancelEvent, touchEndEvent, touchMoveEvent, touchStartEvent, } from "./InteractivityConstants.js";
3
+ import { InteractivityEventListeners } from "./InteractivityEventListeners.js";
4
+ import { InteractorType } from "./InteractorType.js";
5
+ export class InteractionManager {
6
+ constructor(engine, container) {
7
+ this.container = container;
8
+ this._intersectionManager = entries => {
9
+ const { container } = this;
10
+ if (container.destroyed || !container.actualOptions.pauseOnOutsideViewport) {
11
+ return;
12
+ }
13
+ for (const entry of entries) {
14
+ if (entry.target !== this.interactivityData.element) {
15
+ continue;
16
+ }
17
+ if (entry.isIntersecting) {
18
+ container.play();
19
+ }
20
+ else {
21
+ container.pause();
22
+ }
23
+ }
24
+ };
25
+ this._engine = engine;
26
+ this._interactors = [];
27
+ this._externalInteractors = [];
28
+ this._particleInteractors = [];
29
+ this._clickHandlers = new Map();
30
+ this._eventListeners = new InteractivityEventListeners(container, this);
31
+ this.interactivityData = {
32
+ mouse: {
33
+ clicking: false,
34
+ inside: false,
35
+ },
36
+ };
37
+ this._intersectionObserver = safeIntersectionObserver(entries => {
38
+ this._intersectionManager(entries);
39
+ });
40
+ }
41
+ addClickHandler(callback) {
42
+ const { container, interactivityData } = this;
43
+ if (container.destroyed) {
44
+ return;
45
+ }
46
+ const el = interactivityData.element;
47
+ if (!el) {
48
+ return;
49
+ }
50
+ const clickOrTouchHandler = (e, pos, radius) => {
51
+ if (container.destroyed) {
52
+ return;
53
+ }
54
+ const pxRatio = container.retina.pixelRatio, posRetina = {
55
+ x: pos.x * pxRatio,
56
+ y: pos.y * pxRatio,
57
+ }, particles = container.particles.quadTree.queryCircle(posRetina, radius * pxRatio);
58
+ callback(e, particles);
59
+ }, clickHandler = (e) => {
60
+ if (container.destroyed) {
61
+ return;
62
+ }
63
+ const mouseEvent = e, pos = {
64
+ x: mouseEvent.offsetX,
65
+ y: mouseEvent.offsetY,
66
+ };
67
+ clickOrTouchHandler(e, pos, clickRadius);
68
+ }, touchStartHandler = () => {
69
+ if (container.destroyed) {
70
+ return;
71
+ }
72
+ touched = true;
73
+ touchMoved = false;
74
+ }, touchMoveHandler = () => {
75
+ if (container.destroyed) {
76
+ return;
77
+ }
78
+ touchMoved = true;
79
+ }, touchEndHandler = (e) => {
80
+ if (container.destroyed) {
81
+ return;
82
+ }
83
+ if (touched && !touchMoved) {
84
+ const touchEvent = e, lastTouch = touchEvent.touches[touchEvent.touches.length - touchEndLengthOffset];
85
+ if (!lastTouch) {
86
+ return;
87
+ }
88
+ const element = container.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
89
+ x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
90
+ y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
91
+ };
92
+ clickOrTouchHandler(e, pos, Math.max(lastTouch.radiusX, lastTouch.radiusY));
93
+ }
94
+ touched = false;
95
+ touchMoved = false;
96
+ }, touchCancelHandler = () => {
97
+ if (container.destroyed) {
98
+ return;
99
+ }
100
+ touched = false;
101
+ touchMoved = false;
102
+ };
103
+ let touched = false, touchMoved = false;
104
+ this._clickHandlers.set(clickEvent, clickHandler);
105
+ this._clickHandlers.set(touchStartEvent, touchStartHandler);
106
+ this._clickHandlers.set(touchMoveEvent, touchMoveHandler);
107
+ this._clickHandlers.set(touchEndEvent, touchEndHandler);
108
+ this._clickHandlers.set(touchCancelEvent, touchCancelHandler);
109
+ for (const [key, handler] of this._clickHandlers) {
110
+ el.addEventListener(key, handler);
111
+ }
112
+ }
113
+ addListeners() {
114
+ this._eventListeners.addListeners();
115
+ }
116
+ clearClickHandlers() {
117
+ const { container, interactivityData } = this;
118
+ if (container.destroyed) {
119
+ return;
120
+ }
121
+ for (const [key, handler] of this._clickHandlers) {
122
+ interactivityData.element?.removeEventListener(key, handler);
123
+ }
124
+ this._clickHandlers.clear();
125
+ }
126
+ externalInteract(delta) {
127
+ for (const interactor of this._externalInteractors) {
128
+ const { interactivityData } = this;
129
+ if (interactor.isEnabled(interactivityData)) {
130
+ interactor.interact(interactivityData, delta);
131
+ }
132
+ }
133
+ }
134
+ handleClickMode(mode) {
135
+ if (this.container.destroyed) {
136
+ return;
137
+ }
138
+ const { interactivityData } = this;
139
+ for (const interactor of this._externalInteractors) {
140
+ interactor.handleClickMode?.(mode, interactivityData);
141
+ }
142
+ }
143
+ async init() {
144
+ const interactors = await this._engine.getInteractors?.(this.container, true);
145
+ if (!interactors) {
146
+ return;
147
+ }
148
+ this._interactors = interactors;
149
+ this._externalInteractors = [];
150
+ this._particleInteractors = [];
151
+ for (const interactor of this._interactors) {
152
+ switch (interactor.type) {
153
+ case InteractorType.external:
154
+ this._externalInteractors.push(interactor);
155
+ break;
156
+ case InteractorType.particles:
157
+ this._particleInteractors.push(interactor);
158
+ break;
159
+ }
160
+ interactor.init();
161
+ }
162
+ }
163
+ particlesInteract(particle, delta) {
164
+ const { interactivityData } = this;
165
+ for (const interactor of this._externalInteractors) {
166
+ interactor.clear(particle, delta);
167
+ }
168
+ for (const interactor of this._particleInteractors) {
169
+ if (interactor.isEnabled(particle, interactivityData)) {
170
+ interactor.interact(particle, interactivityData, delta);
171
+ }
172
+ }
173
+ }
174
+ removeListeners() {
175
+ this._eventListeners.removeListeners();
176
+ }
177
+ reset(particle) {
178
+ const { interactivityData } = this;
179
+ for (const interactor of this._externalInteractors) {
180
+ if (interactor.isEnabled(interactivityData)) {
181
+ interactor.reset(interactivityData, particle);
182
+ }
183
+ }
184
+ for (const interactor of this._particleInteractors) {
185
+ if (interactor.isEnabled(particle, interactivityData)) {
186
+ interactor.reset(interactivityData, particle);
187
+ }
188
+ }
189
+ }
190
+ startObserving() {
191
+ const { interactivityData } = this;
192
+ if (interactivityData.element instanceof HTMLElement && this._intersectionObserver) {
193
+ this._intersectionObserver.observe(interactivityData.element);
194
+ }
195
+ }
196
+ stopObserving() {
197
+ const { interactivityData } = this;
198
+ if (interactivityData.element instanceof HTMLElement && this._intersectionObserver) {
199
+ this._intersectionObserver.unobserve(interactivityData.element);
200
+ }
201
+ }
202
+ }
@@ -0,0 +1 @@
1
+ export const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseOutEvent = "pointerout", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
@@ -0,0 +1,6 @@
1
+ export var InteractivityDetect;
2
+ (function (InteractivityDetect) {
3
+ InteractivityDetect["canvas"] = "canvas";
4
+ InteractivityDetect["parent"] = "parent";
5
+ InteractivityDetect["window"] = "window";
6
+ })(InteractivityDetect || (InteractivityDetect = {}));
@@ -0,0 +1,235 @@
1
+ import { double, executeOnSingleOrMultiple, lengthOffset, manageListener, touchDelay, visibilityChangeEvent, } from "@tsparticles/engine";
2
+ import { mouseDownEvent, mouseLeaveEvent, mouseMoveEvent, mouseOutEvent, mouseUpEvent, touchCancelEvent, touchEndEvent, touchMoveEvent, touchStartEvent, } from "./InteractivityConstants.js";
3
+ import { InteractivityDetect } from "./InteractivityDetect.js";
4
+ export class InteractivityEventListeners {
5
+ constructor(container, interactionManager) {
6
+ this._canPush = true;
7
+ this._doMouseTouchClick = e => {
8
+ const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions;
9
+ if (this._canPush) {
10
+ const mouseInteractivity = interactionManager.interactivityData.mouse, mousePos = mouseInteractivity.position;
11
+ if (!mousePos) {
12
+ return;
13
+ }
14
+ mouseInteractivity.clickPosition = { ...mousePos };
15
+ mouseInteractivity.clickTime = Date.now();
16
+ const onClick = options.interactivity?.events.onClick;
17
+ if (!onClick?.mode) {
18
+ return;
19
+ }
20
+ executeOnSingleOrMultiple(onClick.mode, mode => {
21
+ interactionManager.handleClickMode(mode);
22
+ });
23
+ }
24
+ if (e.type === "touchend") {
25
+ setTimeout(() => {
26
+ this._mouseTouchFinish();
27
+ }, touchDelay);
28
+ }
29
+ };
30
+ this._handleVisibilityChange = () => {
31
+ this._mouseTouchFinish();
32
+ };
33
+ this._manageInteractivityListeners = (mouseLeaveTmpEvent, add) => {
34
+ const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivityEl = interactionManager.interactivityData.element;
35
+ if (!interactivityEl) {
36
+ return;
37
+ }
38
+ const html = interactivityEl, canvas = container.canvas;
39
+ canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
40
+ if (!(options.interactivity?.events.onHover.enable || options.interactivity?.events.onClick.enable)) {
41
+ return;
42
+ }
43
+ manageListener(interactivityEl, mouseMoveEvent, handlers.mouseMove, add);
44
+ manageListener(interactivityEl, touchStartEvent, handlers.touchStart, add);
45
+ manageListener(interactivityEl, touchMoveEvent, handlers.touchMove, add);
46
+ if (options.interactivity.events.onClick.enable) {
47
+ manageListener(interactivityEl, touchEndEvent, handlers.touchEndClick, add);
48
+ manageListener(interactivityEl, mouseUpEvent, handlers.mouseUp, add);
49
+ manageListener(interactivityEl, mouseDownEvent, handlers.mouseDown, add);
50
+ }
51
+ else {
52
+ manageListener(interactivityEl, touchEndEvent, handlers.touchEnd, add);
53
+ }
54
+ manageListener(interactivityEl, mouseLeaveTmpEvent, handlers.mouseLeave, add);
55
+ manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
56
+ };
57
+ this._manageListeners = add => {
58
+ const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.element;
59
+ let mouseLeaveTmpEvent = mouseLeaveEvent;
60
+ if (detectType === InteractivityDetect.window) {
61
+ interactionManager.interactivityData.element = globalThis;
62
+ mouseLeaveTmpEvent = mouseOutEvent;
63
+ }
64
+ else if (detectType === InteractivityDetect.parent && canvasEl) {
65
+ interactionManager.interactivityData.element = canvasEl.parentElement ?? canvasEl.parentNode;
66
+ }
67
+ else {
68
+ interactionManager.interactivityData.element = canvasEl;
69
+ }
70
+ this._manageInteractivityListeners(mouseLeaveTmpEvent, add);
71
+ manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
72
+ };
73
+ this._mouseDown = () => {
74
+ const { interactivityData } = this._interactionManager, { mouse } = interactivityData;
75
+ mouse.clicking = true;
76
+ mouse.downPosition = mouse.position;
77
+ };
78
+ this._mouseTouchClick = e => {
79
+ const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, { mouse } = interactionManager.interactivityData;
80
+ mouse.inside = true;
81
+ let handled = false;
82
+ const mousePosition = mouse.position;
83
+ if (!mousePosition || !options.interactivity?.events.onClick.enable) {
84
+ return;
85
+ }
86
+ for (const plugin of container.plugins) {
87
+ if (!plugin.clickPositionValid) {
88
+ continue;
89
+ }
90
+ handled = plugin.clickPositionValid(mousePosition);
91
+ if (handled) {
92
+ break;
93
+ }
94
+ }
95
+ if (!handled) {
96
+ this._doMouseTouchClick(e);
97
+ }
98
+ mouse.clicking = false;
99
+ };
100
+ this._mouseTouchFinish = () => {
101
+ const { interactivityData } = this._interactionManager, { mouse } = interactivityData;
102
+ delete mouse.position;
103
+ delete mouse.clickPosition;
104
+ delete mouse.downPosition;
105
+ interactivityData.status = mouseLeaveEvent;
106
+ mouse.inside = false;
107
+ mouse.clicking = false;
108
+ };
109
+ this._mouseTouchMove = e => {
110
+ const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.element;
111
+ if (!interactivity.element) {
112
+ return;
113
+ }
114
+ interactivity.mouse.inside = true;
115
+ let pos;
116
+ if (e.type.startsWith("pointer")) {
117
+ this._canPush = true;
118
+ const mouseEvent = e;
119
+ if (interactivity.element === globalThis) {
120
+ if (canvasEl) {
121
+ const clientRect = canvasEl.getBoundingClientRect();
122
+ pos = {
123
+ x: mouseEvent.clientX - clientRect.left,
124
+ y: mouseEvent.clientY - clientRect.top,
125
+ };
126
+ }
127
+ }
128
+ else if (options.interactivity?.detectsOn === InteractivityDetect.parent) {
129
+ const source = mouseEvent.target, target = mouseEvent.currentTarget;
130
+ if (canvasEl) {
131
+ const sourceRect = source.getBoundingClientRect(), targetRect = target.getBoundingClientRect(), canvasRect = canvasEl.getBoundingClientRect();
132
+ pos = {
133
+ x: mouseEvent.offsetX + double * sourceRect.left - (targetRect.left + canvasRect.left),
134
+ y: mouseEvent.offsetY + double * sourceRect.top - (targetRect.top + canvasRect.top),
135
+ };
136
+ }
137
+ else {
138
+ pos = {
139
+ x: mouseEvent.offsetX,
140
+ y: mouseEvent.offsetY,
141
+ };
142
+ }
143
+ }
144
+ else if (mouseEvent.target === canvasEl) {
145
+ pos = {
146
+ x: mouseEvent.offsetX,
147
+ y: mouseEvent.offsetY,
148
+ };
149
+ }
150
+ }
151
+ else {
152
+ this._canPush = e.type !== "touchmove";
153
+ if (canvasEl) {
154
+ const touchEvent = e, lastTouch = touchEvent.touches[touchEvent.touches.length - lengthOffset], canvasRect = canvasEl.getBoundingClientRect();
155
+ if (!lastTouch) {
156
+ return;
157
+ }
158
+ pos = {
159
+ x: lastTouch.clientX - canvasRect.left,
160
+ y: lastTouch.clientY - canvasRect.top,
161
+ };
162
+ }
163
+ }
164
+ const pxRatio = container.retina.pixelRatio;
165
+ if (pos) {
166
+ pos.x *= pxRatio;
167
+ pos.y *= pxRatio;
168
+ }
169
+ interactivity.mouse.position = pos;
170
+ interactivity.status = mouseMoveEvent;
171
+ };
172
+ this._touchEnd = e => {
173
+ const evt = e, touches = Array.from(evt.changedTouches);
174
+ for (const touch of touches) {
175
+ this._touches.delete(touch.identifier);
176
+ }
177
+ this._mouseTouchFinish();
178
+ };
179
+ this._touchEndClick = e => {
180
+ const evt = e, touches = Array.from(evt.changedTouches);
181
+ for (const touch of touches) {
182
+ this._touches.delete(touch.identifier);
183
+ }
184
+ this._mouseTouchClick(e);
185
+ };
186
+ this._touchStart = e => {
187
+ const evt = e, touches = Array.from(evt.changedTouches);
188
+ for (const touch of touches) {
189
+ this._touches.set(touch.identifier, performance.now());
190
+ }
191
+ this._mouseTouchMove(e);
192
+ };
193
+ this._container = container;
194
+ this._interactionManager = interactionManager;
195
+ this._touches = new Map();
196
+ this._handlers = {
197
+ mouseDown: () => {
198
+ this._mouseDown();
199
+ },
200
+ mouseLeave: () => {
201
+ this._mouseTouchFinish();
202
+ },
203
+ mouseMove: (e) => {
204
+ this._mouseTouchMove(e);
205
+ },
206
+ mouseUp: (e) => {
207
+ this._mouseTouchClick(e);
208
+ },
209
+ touchStart: (e) => {
210
+ this._touchStart(e);
211
+ },
212
+ touchMove: (e) => {
213
+ this._mouseTouchMove(e);
214
+ },
215
+ touchEnd: (e) => {
216
+ this._touchEnd(e);
217
+ },
218
+ touchCancel: (e) => {
219
+ this._touchEnd(e);
220
+ },
221
+ touchEndClick: (e) => {
222
+ this._touchEndClick(e);
223
+ },
224
+ visibilityChange: () => {
225
+ this._handleVisibilityChange();
226
+ },
227
+ };
228
+ }
229
+ addListeners() {
230
+ this._manageListeners(true);
231
+ }
232
+ removeListeners() {
233
+ this._manageListeners(false);
234
+ }
235
+ }
@@ -0,0 +1,48 @@
1
+ import { deepExtend, } from "@tsparticles/engine";
2
+ import { Interactivity } from "./Options/Classes/Interactivity.js";
3
+ export class InteractivityPlugin {
4
+ constructor(engine) {
5
+ this._engine = engine;
6
+ this.id = "interactivity";
7
+ }
8
+ async getPlugin(container) {
9
+ const { InteractivityPluginInstance } = await import("./InteractivityPluginInstance.js");
10
+ return new InteractivityPluginInstance(this._engine, container);
11
+ }
12
+ loadOptions(container, options, source) {
13
+ if (!this.needsPlugin()) {
14
+ return;
15
+ }
16
+ let interactivityOptions = options.interactivity;
17
+ if (!interactivityOptions?.load) {
18
+ options.interactivity = interactivityOptions = new Interactivity(this._engine, container);
19
+ }
20
+ interactivityOptions.load(source?.interactivity);
21
+ const interactors = this._engine.interactors?.get(container);
22
+ if (!interactors) {
23
+ return;
24
+ }
25
+ for (const interactor of interactors) {
26
+ if (interactor.loadOptions) {
27
+ interactor.loadOptions(options, source);
28
+ }
29
+ }
30
+ }
31
+ loadParticlesOptions(container, options, source) {
32
+ if (source?.interactivity) {
33
+ options.interactivity = deepExtend({}, source.interactivity);
34
+ }
35
+ const interactors = this._engine.interactors?.get(container);
36
+ if (!interactors) {
37
+ return;
38
+ }
39
+ for (const interactor of interactors) {
40
+ if (interactor.loadParticlesOptions) {
41
+ interactor.loadParticlesOptions(options, source);
42
+ }
43
+ }
44
+ }
45
+ needsPlugin() {
46
+ return true;
47
+ }
48
+ }