@tsparticles/plugin-interactivity 4.0.0-alpha.14
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/19.min.js +1 -0
- package/74.min.js +1 -0
- package/LICENSE +21 -0
- package/README.md +74 -0
- package/browser/DivType.js +5 -0
- package/browser/ExternalInteractorBase.js +8 -0
- package/browser/IExternalInteractor.js +1 -0
- package/browser/IInteractivityData.js +1 -0
- package/browser/IInteractor.js +1 -0
- package/browser/IMouseData.js +1 -0
- package/browser/IParticlesInteractor.js +1 -0
- package/browser/InteractionManager.js +212 -0
- package/browser/InteractivityConstants.js +1 -0
- package/browser/InteractivityDetect.js +6 -0
- package/browser/InteractivityEventListeners.js +244 -0
- package/browser/InteractivityPlugin.js +49 -0
- package/browser/InteractivityPluginInstance.js +55 -0
- package/browser/InteractorType.js +5 -0
- package/browser/Options/Classes/Events/ClickEvent.js +20 -0
- package/browser/Options/Classes/Events/DivEvent.js +31 -0
- package/browser/Options/Classes/Events/Events.js +29 -0
- package/browser/Options/Classes/Events/HoverEvent.js +20 -0
- package/browser/Options/Classes/Interactivity.js +25 -0
- package/browser/Options/Classes/Modes/Modes.js +27 -0
- package/browser/Options/Interfaces/Events/IClickEvent.js +1 -0
- package/browser/Options/Interfaces/Events/IDivEvent.js +1 -0
- package/browser/Options/Interfaces/Events/IEvents.js +1 -0
- package/browser/Options/Interfaces/Events/IHoverEvent.js +1 -0
- package/browser/Options/Interfaces/IInteractivity.js +1 -0
- package/browser/Options/Interfaces/Modes/IModeDiv.js +1 -0
- package/browser/Options/Interfaces/Modes/IModes.js +1 -0
- package/browser/ParticlesInteractorBase.js +8 -0
- package/browser/index.js +38 -0
- package/browser/package.json +1 -0
- package/browser/types.js +1 -0
- package/browser/utils.js +32 -0
- package/cjs/DivType.js +5 -0
- package/cjs/ExternalInteractorBase.js +8 -0
- package/cjs/IExternalInteractor.js +1 -0
- package/cjs/IInteractivityData.js +1 -0
- package/cjs/IInteractor.js +1 -0
- package/cjs/IMouseData.js +1 -0
- package/cjs/IParticlesInteractor.js +1 -0
- package/cjs/InteractionManager.js +212 -0
- package/cjs/InteractivityConstants.js +1 -0
- package/cjs/InteractivityDetect.js +6 -0
- package/cjs/InteractivityEventListeners.js +244 -0
- package/cjs/InteractivityPlugin.js +49 -0
- package/cjs/InteractivityPluginInstance.js +55 -0
- package/cjs/InteractorType.js +5 -0
- package/cjs/Options/Classes/Events/ClickEvent.js +20 -0
- package/cjs/Options/Classes/Events/DivEvent.js +31 -0
- package/cjs/Options/Classes/Events/Events.js +29 -0
- package/cjs/Options/Classes/Events/HoverEvent.js +20 -0
- package/cjs/Options/Classes/Interactivity.js +25 -0
- package/cjs/Options/Classes/Modes/Modes.js +27 -0
- package/cjs/Options/Interfaces/Events/IClickEvent.js +1 -0
- package/cjs/Options/Interfaces/Events/IDivEvent.js +1 -0
- package/cjs/Options/Interfaces/Events/IEvents.js +1 -0
- package/cjs/Options/Interfaces/Events/IHoverEvent.js +1 -0
- package/cjs/Options/Interfaces/IInteractivity.js +1 -0
- package/cjs/Options/Interfaces/Modes/IModeDiv.js +1 -0
- package/cjs/Options/Interfaces/Modes/IModes.js +1 -0
- package/cjs/ParticlesInteractorBase.js +8 -0
- package/cjs/index.js +38 -0
- package/cjs/package.json +1 -0
- package/cjs/types.js +1 -0
- package/cjs/utils.js +32 -0
- package/dist_browser_InteractivityPluginInstance_js.js +50 -0
- package/dist_browser_InteractivityPlugin_js.js +70 -0
- package/esm/DivType.js +5 -0
- package/esm/ExternalInteractorBase.js +8 -0
- package/esm/IExternalInteractor.js +1 -0
- package/esm/IInteractivityData.js +1 -0
- package/esm/IInteractor.js +1 -0
- package/esm/IMouseData.js +1 -0
- package/esm/IParticlesInteractor.js +1 -0
- package/esm/InteractionManager.js +212 -0
- package/esm/InteractivityConstants.js +1 -0
- package/esm/InteractivityDetect.js +6 -0
- package/esm/InteractivityEventListeners.js +244 -0
- package/esm/InteractivityPlugin.js +49 -0
- package/esm/InteractivityPluginInstance.js +55 -0
- package/esm/InteractorType.js +5 -0
- package/esm/Options/Classes/Events/ClickEvent.js +20 -0
- package/esm/Options/Classes/Events/DivEvent.js +31 -0
- package/esm/Options/Classes/Events/Events.js +29 -0
- package/esm/Options/Classes/Events/HoverEvent.js +20 -0
- package/esm/Options/Classes/Interactivity.js +25 -0
- package/esm/Options/Classes/Modes/Modes.js +27 -0
- package/esm/Options/Interfaces/Events/IClickEvent.js +1 -0
- package/esm/Options/Interfaces/Events/IDivEvent.js +1 -0
- package/esm/Options/Interfaces/Events/IEvents.js +1 -0
- package/esm/Options/Interfaces/Events/IHoverEvent.js +1 -0
- package/esm/Options/Interfaces/IInteractivity.js +1 -0
- package/esm/Options/Interfaces/Modes/IModeDiv.js +1 -0
- package/esm/Options/Interfaces/Modes/IModes.js +1 -0
- package/esm/ParticlesInteractorBase.js +8 -0
- package/esm/index.js +38 -0
- package/esm/package.json +1 -0
- package/esm/types.js +1 -0
- package/esm/utils.js +32 -0
- package/package.json +95 -0
- package/report.html +40 -0
- package/tsparticles.plugin.interactivity.js +407 -0
- package/tsparticles.plugin.interactivity.min.js +2 -0
- package/types/DivType.d.ts +4 -0
- package/types/ExternalInteractorBase.d.ts +15 -0
- package/types/IExternalInteractor.d.ts +11 -0
- package/types/IInteractivityData.d.ts +6 -0
- package/types/IInteractor.d.ts +12 -0
- package/types/IMouseData.d.ts +9 -0
- package/types/IParticlesInteractor.d.ts +7 -0
- package/types/InteractionManager.d.ts +27 -0
- package/types/InteractivityConstants.d.ts +1 -0
- package/types/InteractivityDetect.d.ts +5 -0
- package/types/InteractivityEventListeners.d.ts +25 -0
- package/types/InteractivityPlugin.d.ts +11 -0
- package/types/InteractivityPluginInstance.d.ts +20 -0
- package/types/InteractorType.d.ts +4 -0
- package/types/Options/Classes/Events/ClickEvent.d.ts +8 -0
- package/types/Options/Classes/Events/DivEvent.d.ts +11 -0
- package/types/Options/Classes/Events/Events.d.ts +12 -0
- package/types/Options/Classes/Events/HoverEvent.d.ts +8 -0
- package/types/Options/Classes/Interactivity.d.ts +14 -0
- package/types/Options/Classes/Modes/Modes.d.ts +10 -0
- package/types/Options/Interfaces/Events/IClickEvent.d.ts +5 -0
- package/types/Options/Interfaces/Events/IDivEvent.d.ts +8 -0
- package/types/Options/Interfaces/Events/IEvents.d.ts +9 -0
- package/types/Options/Interfaces/Events/IHoverEvent.d.ts +5 -0
- package/types/Options/Interfaces/IInteractivity.d.ts +9 -0
- package/types/Options/Interfaces/Modes/IModeDiv.d.ts +4 -0
- package/types/Options/Interfaces/Modes/IModes.d.ts +1 -0
- package/types/ParticlesInteractorBase.d.ts +15 -0
- package/types/index.d.ts +19 -0
- package/types/types.d.ts +34 -0
- package/types/utils.d.ts +7 -0
- package/umd/DivType.js +18 -0
- package/umd/ExternalInteractorBase.js +22 -0
- package/umd/IExternalInteractor.js +12 -0
- package/umd/IInteractivityData.js +12 -0
- package/umd/IInteractor.js +12 -0
- package/umd/IMouseData.js +12 -0
- package/umd/IParticlesInteractor.js +12 -0
- package/umd/InteractionManager.js +226 -0
- package/umd/InteractivityConstants.js +14 -0
- package/umd/InteractivityDetect.js +19 -0
- package/umd/InteractivityEventListeners.js +258 -0
- package/umd/InteractivityPlugin.js +97 -0
- package/umd/InteractivityPluginInstance.js +69 -0
- package/umd/InteractorType.js +18 -0
- package/umd/Options/Classes/Events/ClickEvent.js +34 -0
- package/umd/Options/Classes/Events/DivEvent.js +45 -0
- package/umd/Options/Classes/Events/Events.js +43 -0
- package/umd/Options/Classes/Events/HoverEvent.js +34 -0
- package/umd/Options/Classes/Interactivity.js +39 -0
- package/umd/Options/Classes/Modes/Modes.js +41 -0
- package/umd/Options/Interfaces/Events/IClickEvent.js +12 -0
- package/umd/Options/Interfaces/Events/IDivEvent.js +12 -0
- package/umd/Options/Interfaces/Events/IEvents.js +12 -0
- package/umd/Options/Interfaces/Events/IHoverEvent.js +12 -0
- package/umd/Options/Interfaces/IInteractivity.js +12 -0
- package/umd/Options/Interfaces/Modes/IModeDiv.js +12 -0
- package/umd/Options/Interfaces/Modes/IModes.js +12 -0
- package/umd/ParticlesInteractorBase.js +22 -0
- package/umd/index.js +88 -0
- package/umd/types.js +12 -0
- package/umd/utils.js +48 -0
package/19.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(this.webpackChunk_tsparticles_plugin_interactivity=this.webpackChunk_tsparticles_plugin_interactivity||[]).push([[19],{19(e,t,i){i.d(t,{InteractivityPlugin:()=>o});var n=i(303),s=i(210);class o{id="interactivity";_engine;constructor(e){this._engine=e}async getPlugin(e){let{InteractivityPluginInstance:t}=await i.e(74).then(i.bind(i,74));return new t(this._engine,e)}loadOptions(e,t,i){if(!this.needsPlugin())return;let n=t.interactivity;n?.load||(t.interactivity=n=new s.k(this._engine,e)),n.load(i?.interactivity);let o=this._engine.interactors?.get(e);if(o)for(let e of o)e.loadOptions&&e.loadOptions(t,i)}loadParticlesOptions(e,t,i){i?.interactivity&&(t.interactivity=(0,n.deepExtend)({},i.interactivity));let s=this._engine.interactors?.get(e);if(s)for(let e of s)e.loadParticlesOptions&&e.loadParticlesOptions(t,i)}needsPlugin(){return!0}}},210(e,t,i){i.d(t,{k:()=>c});var n=i(303);class s{enable;mode;constructor(){this.enable=!1,this.mode=[]}load(e){(0,n.isNull)(e)||(void 0!==e.enable&&(this.enable=e.enable),void 0!==e.mode&&(this.mode=e.mode))}}var o=i(570);class l{enable;mode;constructor(){this.enable=!1,this.mode=[]}load(e){(0,n.isNull)(e)||(void 0!==e.enable&&(this.enable=e.enable),void 0!==e.mode&&(this.mode=e.mode))}}class a{onClick;onDiv;onHover;constructor(){this.onClick=new s,this.onDiv=new o.G,this.onHover=new l}load(e){if((0,n.isNull)(e))return;this.onClick.load(e.onClick);let t=e.onDiv;void 0!==t&&(this.onDiv=(0,n.executeOnSingleOrMultiple)(t,e=>{let t=new o.G;return t.load(e),t})),this.onHover.load(e.onHover)}}var r=i(551),d=i(870);class c{detectsOn;events;modes;constructor(e,t){this.detectsOn=r.h.window,this.events=new a,this.modes=new d.d(e,t)}load(e){if((0,n.isNull)(e))return;let t=e.detectsOn;void 0!==t&&(this.detectsOn=t),this.events.load(e.events),this.modes.load(e.modes)}}}}]);
|
package/74.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(this.webpackChunk_tsparticles_plugin_interactivity=this.webpackChunk_tsparticles_plugin_interactivity||[]).push([[74],{74(e,t,i){i.d(t,{InteractivityPluginInstance:()=>h});var n=i(303),s=i(311),a=i(551);class r{_canPush=!0;_clickPositionPlugins;_container;_handlers;_interactionManager;_touches;constructor(e,t){this._container=e,this._clickPositionPlugins=[],this._interactionManager=t,this._touches=new Map,this._handlers={mouseDown:()=>{this._mouseDown()},mouseLeave:()=>{this._mouseTouchFinish()},mouseMove:e=>{this._mouseTouchMove(e)},mouseUp:e=>{this._mouseTouchClick(e)},touchStart:e=>{this._touchStart(e)},touchMove:e=>{this._mouseTouchMove(e)},touchEnd:e=>{this._touchEnd(e)},touchCancel:e=>{this._touchEnd(e)},touchEndClick:e=>{this._touchEndClick(e)},visibilityChange:()=>{this._handleVisibilityChange()}}}addListeners(){this._manageListeners(!0)}init(){for(let e of(this._clickPositionPlugins.length=0,this._container.plugins.filter(e=>!!e.clickPositionValid)))this._clickPositionPlugins.push(e)}removeListeners(){this._manageListeners(!1)}_doMouseTouchClick=e=>{let t=this._container,i=this._interactionManager,s=t.actualOptions;if(this._canPush){let e=i.interactivityData.mouse,t=e.position;if(!t)return;e.clickPosition={...t},e.clickTime=performance.now();let a=s.interactivity?.events.onClick;if(!a?.mode)return;(0,n.executeOnSingleOrMultiple)(a.mode,e=>{i.handleClickMode(e)})}"touchend"===e.type&&setTimeout(()=>{this._mouseTouchFinish()},n.touchDelay)};_handleVisibilityChange=()=>{this._mouseTouchFinish()};_manageInteractivityListeners=(e,t)=>{let i=this._handlers,a=this._container,r=this._interactionManager,o=a.actualOptions,c=r.interactivityData.element;if(!c)return;let l=a.canvas;l.setPointerEvents(c===l.element?"initial":"none"),(o.interactivity?.events.onHover.enable||o.interactivity?.events.onClick.enable)&&((0,n.manageListener)(c,s.Rb,i.mouseMove,t),(0,n.manageListener)(c,s.s7,i.touchStart,t),(0,n.manageListener)(c,s.DG,i.touchMove,t),o.interactivity.events.onClick.enable?((0,n.manageListener)(c,s.Bp,i.touchEndClick,t),(0,n.manageListener)(c,s.vo,i.mouseUp,t),(0,n.manageListener)(c,s.ms,i.mouseDown,t)):(0,n.manageListener)(c,s.Bp,i.touchEnd,t),(0,n.manageListener)(c,e,i.mouseLeave,t),(0,n.manageListener)(c,s.G3,i.touchCancel,t))};_manageListeners=e=>{let t=this._handlers,i=this._container,r=this._interactionManager,o=i.actualOptions,c=o.interactivity?.detectsOn,l=i.canvas.element,h=s.Z0;c===a.h.window?(r.interactivityData.element=globalThis,h=s.sf):c===a.h.parent&&l?r.interactivityData.element=l.parentElement??l.parentNode:r.interactivityData.element=l,this._manageInteractivityListeners(h,e),(0,n.manageListener)(document,n.visibilityChangeEvent,t.visibilityChange,e,!1)};_mouseDown=()=>{let{interactivityData:e}=this._interactionManager,{mouse:t}=e;t.clicking=!0,t.downPosition=t.position};_mouseTouchClick=e=>{let t=this._container,i=this._interactionManager,n=t.actualOptions,{mouse:s}=i.interactivityData;s.inside=!0;let a=!1,r=s.position;if(r&&n.interactivity?.events.onClick.enable){for(let e of this._clickPositionPlugins)if(a=e.clickPositionValid?.(r)??!1)break;a||this._doMouseTouchClick(e),s.clicking=!1}};_mouseTouchFinish=()=>{let{interactivityData:e}=this._interactionManager,{mouse:t}=e;delete t.position,delete t.clickPosition,delete t.downPosition,e.status=s.Z0,t.inside=!1,t.clicking=!1};_mouseTouchMove=e=>{let t,i=this._container,r=this._interactionManager,o=i.actualOptions,c=r.interactivityData,l=i.canvas.element;if(!c.element)return;if(c.mouse.inside=!0,e.type.startsWith("pointer"))if(this._canPush=!0,c.element===globalThis){if(l){let i=l.getBoundingClientRect();t={x:e.clientX-i.left,y:e.clientY-i.top}}}else if(o.interactivity?.detectsOn===a.h.parent){let i=e.target,s=e.currentTarget;if(l){let a=i.getBoundingClientRect(),r=s.getBoundingClientRect(),o=l.getBoundingClientRect();t={x:e.offsetX+n.double*a.left-(r.left+o.left),y:e.offsetY+n.double*a.top-(r.top+o.top)}}else t={x:e.offsetX,y:e.offsetY}}else e.target===l&&(t={x:e.offsetX,y:e.offsetY});else if(this._canPush="touchmove"!==e.type,l){let i=e.touches[e.touches.length-n.lengthOffset],s=l.getBoundingClientRect();if(!i)return;t={x:i.clientX-s.left,y:i.clientY-s.top}}let h=i.retina.pixelRatio;t&&(t.x*=h,t.y*=h),c.mouse.position=t,c.status=s.Rb};_touchEnd=e=>{for(let t of Array.from(e.changedTouches))this._touches.delete(t.identifier);this._mouseTouchFinish()};_touchEndClick=e=>{for(let t of Array.from(e.changedTouches))this._touches.delete(t.identifier);this._mouseTouchClick(e)};_touchStart=e=>{for(let t of Array.from(e.changedTouches))this._touches.set(t.identifier,performance.now());this._mouseTouchMove(e)}}var o=i(520);class c{container;interactivityData;_clickHandlers;_engine;_eventListeners;_externalInteractors;_interactors;_intersectionObserver;_particleInteractors;constructor(e,t){this.container=t,this._engine=e,this._interactors=[],this._externalInteractors=[],this._particleInteractors=[],this._clickHandlers=new Map,this._eventListeners=new r(t,this),this.interactivityData={mouse:{clicking:!1,inside:!1}},this._intersectionObserver=(0,n.safeIntersectionObserver)(e=>{this._intersectionManager(e)})}addClickHandler(e){let{container:t,interactivityData:i}=this;if(t.destroyed)return;let a=i.element;if(!a)return;let r=(i,n,s)=>{if(t.destroyed)return;let a=t.retina.pixelRatio,r={x:n.x*a,y:n.y*a};e(i,t.particles.quadTree.queryCircle(r,s*a))},o=!1,c=!1;for(let[e,i]of(this._clickHandlers.set(s.xO,e=>{if(t.destroyed)return;let i={x:e.offsetX,y:e.offsetY};r(e,i,n.clickRadius)}),this._clickHandlers.set(s.s7,()=>{t.destroyed||(o=!0,c=!1)}),this._clickHandlers.set(s.DG,()=>{t.destroyed||(c=!0)}),this._clickHandlers.set(s.Bp,e=>{if(!t.destroyed){if(o&&!c){let i=e.touches[e.touches.length-n.touchEndLengthOffset];if(!i)return;let s=t.canvas.element,a=s?s.getBoundingClientRect():void 0;r(e,{x:i.clientX-(a?a.left:n.minCoordinate),y:i.clientY-(a?a.top:n.minCoordinate)},Math.max(i.radiusX,i.radiusY))}o=!1,c=!1}}),this._clickHandlers.set(s.G3,()=>{t.destroyed||(o=!1,c=!1)}),this._clickHandlers))a.addEventListener(e,i)}addListeners(){this._eventListeners.addListeners()}clearClickHandlers(){let{container:e,interactivityData:t}=this;if(!e.destroyed){for(let[e,i]of this._clickHandlers)t.element?.removeEventListener(e,i);this._clickHandlers.clear()}}externalInteract(e){for(let t of this._externalInteractors){let{interactivityData:i}=this;t.isEnabled(i)&&t.interact(i,e)}}handleClickMode(e){if(this.container.destroyed)return;let{interactivityData:t}=this;for(let i of this._externalInteractors)i.handleClickMode?.(e,t)}async init(){let e=await this._engine.getInteractors?.(this.container,!0);if(e)for(let t of(this._interactors=e,this._externalInteractors=[],this._particleInteractors=[],this._eventListeners.init(),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(e,t){let{interactivityData:i}=this;for(let i of this._externalInteractors)i.clear(e,t);for(let n of this._particleInteractors)n.isEnabled(e,i)&&n.interact(e,i,t)}removeListeners(){this._eventListeners.removeListeners()}reset(e){let{interactivityData:t}=this;for(let i of this._externalInteractors)i.isEnabled(t)&&i.reset(t,e);for(let i of this._particleInteractors)i.isEnabled(e,t)&&i.reset(t,e)}startObserving(){let{interactivityData:e}=this;e.element instanceof HTMLElement&&this._intersectionObserver&&this._intersectionObserver.observe(e.element)}stopObserving(){let{interactivityData:e}=this;e.element instanceof HTMLElement&&this._intersectionObserver&&this._intersectionObserver.unobserve(e.element)}_intersectionManager=e=>{let{container:t}=this;if(!t.destroyed&&t.actualOptions.pauseOnOutsideViewport)for(let i of e)i.target===this.interactivityData.element&&(i.isIntersecting?t.play():t.pause())}}var l=i(210);class h{interactionManager;_container;_engine;constructor(e,t){this._container=t,this._engine=e,this.interactionManager=new c(e,t),this._container.addClickHandler=e=>{this.interactionManager.addClickHandler(e)}}addClickHandler(e){this.interactionManager.addClickHandler(e)}clearClickHandlers(){this.interactionManager.clearClickHandlers()}destroy(){this.clearClickHandlers(),this._engine.interactors?.delete(this._container)}particleCreated(e){let t=new l.k(this._engine,this._container);t.load(this._container.actualOptions.interactivity),t.load(e.options.interactivity),e.interactivity=t}particleReset(e){this.interactionManager.reset(e)}postParticleUpdate(e,t){this.interactionManager.particlesInteract(e,t)}postUpdate(e){this.interactionManager.externalInteract(e)}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()}}}}]);
|
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
|
+
[](https://particles.js.org)
|
|
2
|
+
|
|
3
|
+
# tsParticles Interactivity Plugin
|
|
4
|
+
|
|
5
|
+
[](https://www.jsdelivr.com/package/npm/@tsparticles/plugin-interactivity)
|
|
6
|
+
[](https://www.npmjs.com/package/@tsparticles/plugin-interactivity)
|
|
7
|
+
[](https://www.npmjs.com/package/@tsparticles/plugin-interactivity) [](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 @@
|
|
|
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,212 @@
|
|
|
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
|
+
container;
|
|
7
|
+
interactivityData;
|
|
8
|
+
_clickHandlers;
|
|
9
|
+
_engine;
|
|
10
|
+
_eventListeners;
|
|
11
|
+
_externalInteractors;
|
|
12
|
+
_interactors;
|
|
13
|
+
_intersectionObserver;
|
|
14
|
+
_particleInteractors;
|
|
15
|
+
constructor(engine, container) {
|
|
16
|
+
this.container = container;
|
|
17
|
+
this._engine = engine;
|
|
18
|
+
this._interactors = [];
|
|
19
|
+
this._externalInteractors = [];
|
|
20
|
+
this._particleInteractors = [];
|
|
21
|
+
this._clickHandlers = new Map();
|
|
22
|
+
this._eventListeners = new InteractivityEventListeners(container, this);
|
|
23
|
+
this.interactivityData = {
|
|
24
|
+
mouse: {
|
|
25
|
+
clicking: false,
|
|
26
|
+
inside: false,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
this._intersectionObserver = safeIntersectionObserver(entries => {
|
|
30
|
+
this._intersectionManager(entries);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
addClickHandler(callback) {
|
|
34
|
+
const { container, interactivityData } = this;
|
|
35
|
+
if (container.destroyed) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const el = interactivityData.element;
|
|
39
|
+
if (!el) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const clickOrTouchHandler = (e, pos, radius) => {
|
|
43
|
+
if (container.destroyed) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const pxRatio = container.retina.pixelRatio, posRetina = {
|
|
47
|
+
x: pos.x * pxRatio,
|
|
48
|
+
y: pos.y * pxRatio,
|
|
49
|
+
}, particles = container.particles.quadTree.queryCircle(posRetina, radius * pxRatio);
|
|
50
|
+
callback(e, particles);
|
|
51
|
+
}, clickHandler = (e) => {
|
|
52
|
+
if (container.destroyed) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const mouseEvent = e, pos = {
|
|
56
|
+
x: mouseEvent.offsetX,
|
|
57
|
+
y: mouseEvent.offsetY,
|
|
58
|
+
};
|
|
59
|
+
clickOrTouchHandler(e, pos, clickRadius);
|
|
60
|
+
}, touchStartHandler = () => {
|
|
61
|
+
if (container.destroyed) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
touched = true;
|
|
65
|
+
touchMoved = false;
|
|
66
|
+
}, touchMoveHandler = () => {
|
|
67
|
+
if (container.destroyed) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
touchMoved = true;
|
|
71
|
+
}, touchEndHandler = (e) => {
|
|
72
|
+
if (container.destroyed) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (touched && !touchMoved) {
|
|
76
|
+
const touchEvent = e, lastTouch = touchEvent.touches[touchEvent.touches.length - touchEndLengthOffset];
|
|
77
|
+
if (!lastTouch) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const element = container.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
|
|
81
|
+
x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
|
|
82
|
+
y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
|
|
83
|
+
};
|
|
84
|
+
clickOrTouchHandler(e, pos, Math.max(lastTouch.radiusX, lastTouch.radiusY));
|
|
85
|
+
}
|
|
86
|
+
touched = false;
|
|
87
|
+
touchMoved = false;
|
|
88
|
+
}, touchCancelHandler = () => {
|
|
89
|
+
if (container.destroyed) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
touched = false;
|
|
93
|
+
touchMoved = false;
|
|
94
|
+
};
|
|
95
|
+
let touched = false, touchMoved = false;
|
|
96
|
+
this._clickHandlers.set(clickEvent, clickHandler);
|
|
97
|
+
this._clickHandlers.set(touchStartEvent, touchStartHandler);
|
|
98
|
+
this._clickHandlers.set(touchMoveEvent, touchMoveHandler);
|
|
99
|
+
this._clickHandlers.set(touchEndEvent, touchEndHandler);
|
|
100
|
+
this._clickHandlers.set(touchCancelEvent, touchCancelHandler);
|
|
101
|
+
for (const [key, handler] of this._clickHandlers) {
|
|
102
|
+
el.addEventListener(key, handler);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
addListeners() {
|
|
106
|
+
this._eventListeners.addListeners();
|
|
107
|
+
}
|
|
108
|
+
clearClickHandlers() {
|
|
109
|
+
const { container, interactivityData } = this;
|
|
110
|
+
if (container.destroyed) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
for (const [key, handler] of this._clickHandlers) {
|
|
114
|
+
interactivityData.element?.removeEventListener(key, handler);
|
|
115
|
+
}
|
|
116
|
+
this._clickHandlers.clear();
|
|
117
|
+
}
|
|
118
|
+
externalInteract(delta) {
|
|
119
|
+
for (const interactor of this._externalInteractors) {
|
|
120
|
+
const { interactivityData } = this;
|
|
121
|
+
if (interactor.isEnabled(interactivityData)) {
|
|
122
|
+
interactor.interact(interactivityData, delta);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
handleClickMode(mode) {
|
|
127
|
+
if (this.container.destroyed) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const { interactivityData } = this;
|
|
131
|
+
for (const interactor of this._externalInteractors) {
|
|
132
|
+
interactor.handleClickMode?.(mode, interactivityData);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async init() {
|
|
136
|
+
const interactors = await this._engine.getInteractors?.(this.container, true);
|
|
137
|
+
if (!interactors) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this._interactors = interactors;
|
|
141
|
+
this._externalInteractors = [];
|
|
142
|
+
this._particleInteractors = [];
|
|
143
|
+
this._eventListeners.init();
|
|
144
|
+
for (const interactor of this._interactors) {
|
|
145
|
+
switch (interactor.type) {
|
|
146
|
+
case InteractorType.external:
|
|
147
|
+
this._externalInteractors.push(interactor);
|
|
148
|
+
break;
|
|
149
|
+
case InteractorType.particles:
|
|
150
|
+
this._particleInteractors.push(interactor);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
interactor.init();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
particlesInteract(particle, delta) {
|
|
157
|
+
const { interactivityData } = this;
|
|
158
|
+
for (const interactor of this._externalInteractors) {
|
|
159
|
+
interactor.clear(particle, delta);
|
|
160
|
+
}
|
|
161
|
+
for (const interactor of this._particleInteractors) {
|
|
162
|
+
if (interactor.isEnabled(particle, interactivityData)) {
|
|
163
|
+
interactor.interact(particle, interactivityData, delta);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
removeListeners() {
|
|
168
|
+
this._eventListeners.removeListeners();
|
|
169
|
+
}
|
|
170
|
+
reset(particle) {
|
|
171
|
+
const { interactivityData } = this;
|
|
172
|
+
for (const interactor of this._externalInteractors) {
|
|
173
|
+
if (interactor.isEnabled(interactivityData)) {
|
|
174
|
+
interactor.reset(interactivityData, particle);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const interactor of this._particleInteractors) {
|
|
178
|
+
if (interactor.isEnabled(particle, interactivityData)) {
|
|
179
|
+
interactor.reset(interactivityData, particle);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
startObserving() {
|
|
184
|
+
const { interactivityData } = this;
|
|
185
|
+
if (interactivityData.element instanceof HTMLElement && this._intersectionObserver) {
|
|
186
|
+
this._intersectionObserver.observe(interactivityData.element);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
stopObserving() {
|
|
190
|
+
const { interactivityData } = this;
|
|
191
|
+
if (interactivityData.element instanceof HTMLElement && this._intersectionObserver) {
|
|
192
|
+
this._intersectionObserver.unobserve(interactivityData.element);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
_intersectionManager = entries => {
|
|
196
|
+
const { container } = this;
|
|
197
|
+
if (container.destroyed || !container.actualOptions.pauseOnOutsideViewport) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
for (const entry of entries) {
|
|
201
|
+
if (entry.target !== this.interactivityData.element) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (entry.isIntersecting) {
|
|
205
|
+
container.play();
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
container.pause();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
@@ -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,244 @@
|
|
|
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
|
+
_canPush = true;
|
|
6
|
+
_clickPositionPlugins;
|
|
7
|
+
_container;
|
|
8
|
+
_handlers;
|
|
9
|
+
_interactionManager;
|
|
10
|
+
_touches;
|
|
11
|
+
constructor(container, interactionManager) {
|
|
12
|
+
this._container = container;
|
|
13
|
+
this._clickPositionPlugins = [];
|
|
14
|
+
this._interactionManager = interactionManager;
|
|
15
|
+
this._touches = new Map();
|
|
16
|
+
this._handlers = {
|
|
17
|
+
mouseDown: () => {
|
|
18
|
+
this._mouseDown();
|
|
19
|
+
},
|
|
20
|
+
mouseLeave: () => {
|
|
21
|
+
this._mouseTouchFinish();
|
|
22
|
+
},
|
|
23
|
+
mouseMove: (e) => {
|
|
24
|
+
this._mouseTouchMove(e);
|
|
25
|
+
},
|
|
26
|
+
mouseUp: (e) => {
|
|
27
|
+
this._mouseTouchClick(e);
|
|
28
|
+
},
|
|
29
|
+
touchStart: (e) => {
|
|
30
|
+
this._touchStart(e);
|
|
31
|
+
},
|
|
32
|
+
touchMove: (e) => {
|
|
33
|
+
this._mouseTouchMove(e);
|
|
34
|
+
},
|
|
35
|
+
touchEnd: (e) => {
|
|
36
|
+
this._touchEnd(e);
|
|
37
|
+
},
|
|
38
|
+
touchCancel: (e) => {
|
|
39
|
+
this._touchEnd(e);
|
|
40
|
+
},
|
|
41
|
+
touchEndClick: (e) => {
|
|
42
|
+
this._touchEndClick(e);
|
|
43
|
+
},
|
|
44
|
+
visibilityChange: () => {
|
|
45
|
+
this._handleVisibilityChange();
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
addListeners() {
|
|
50
|
+
this._manageListeners(true);
|
|
51
|
+
}
|
|
52
|
+
init() {
|
|
53
|
+
this._clickPositionPlugins.length = 0;
|
|
54
|
+
for (const plugin of this._container.plugins.filter(p => !!p.clickPositionValid)) {
|
|
55
|
+
this._clickPositionPlugins.push(plugin);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
removeListeners() {
|
|
59
|
+
this._manageListeners(false);
|
|
60
|
+
}
|
|
61
|
+
_doMouseTouchClick = e => {
|
|
62
|
+
const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions;
|
|
63
|
+
if (this._canPush) {
|
|
64
|
+
const mouseInteractivity = interactionManager.interactivityData.mouse, mousePos = mouseInteractivity.position;
|
|
65
|
+
if (!mousePos) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
mouseInteractivity.clickPosition = { ...mousePos };
|
|
69
|
+
mouseInteractivity.clickTime = performance.now();
|
|
70
|
+
const onClick = options.interactivity?.events.onClick;
|
|
71
|
+
if (!onClick?.mode) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
executeOnSingleOrMultiple(onClick.mode, mode => {
|
|
75
|
+
interactionManager.handleClickMode(mode);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (e.type === "touchend") {
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
this._mouseTouchFinish();
|
|
81
|
+
}, touchDelay);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
_handleVisibilityChange = () => {
|
|
85
|
+
this._mouseTouchFinish();
|
|
86
|
+
};
|
|
87
|
+
_manageInteractivityListeners = (mouseLeaveTmpEvent, add) => {
|
|
88
|
+
const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivityEl = interactionManager.interactivityData.element;
|
|
89
|
+
if (!interactivityEl) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const html = interactivityEl, canvas = container.canvas;
|
|
93
|
+
canvas.setPointerEvents(html === canvas.element ? "initial" : "none");
|
|
94
|
+
if (!(options.interactivity?.events.onHover.enable || options.interactivity?.events.onClick.enable)) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
manageListener(interactivityEl, mouseMoveEvent, handlers.mouseMove, add);
|
|
98
|
+
manageListener(interactivityEl, touchStartEvent, handlers.touchStart, add);
|
|
99
|
+
manageListener(interactivityEl, touchMoveEvent, handlers.touchMove, add);
|
|
100
|
+
if (options.interactivity.events.onClick.enable) {
|
|
101
|
+
manageListener(interactivityEl, touchEndEvent, handlers.touchEndClick, add);
|
|
102
|
+
manageListener(interactivityEl, mouseUpEvent, handlers.mouseUp, add);
|
|
103
|
+
manageListener(interactivityEl, mouseDownEvent, handlers.mouseDown, add);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
manageListener(interactivityEl, touchEndEvent, handlers.touchEnd, add);
|
|
107
|
+
}
|
|
108
|
+
manageListener(interactivityEl, mouseLeaveTmpEvent, handlers.mouseLeave, add);
|
|
109
|
+
manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
|
|
110
|
+
};
|
|
111
|
+
_manageListeners = add => {
|
|
112
|
+
const handlers = this._handlers, container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, detectType = options.interactivity?.detectsOn, canvasEl = container.canvas.element;
|
|
113
|
+
let mouseLeaveTmpEvent = mouseLeaveEvent;
|
|
114
|
+
if (detectType === InteractivityDetect.window) {
|
|
115
|
+
interactionManager.interactivityData.element = globalThis;
|
|
116
|
+
mouseLeaveTmpEvent = mouseOutEvent;
|
|
117
|
+
}
|
|
118
|
+
else if (detectType === InteractivityDetect.parent && canvasEl) {
|
|
119
|
+
interactionManager.interactivityData.element = canvasEl.parentElement ?? canvasEl.parentNode;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
interactionManager.interactivityData.element = canvasEl;
|
|
123
|
+
}
|
|
124
|
+
this._manageInteractivityListeners(mouseLeaveTmpEvent, add);
|
|
125
|
+
manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
|
|
126
|
+
};
|
|
127
|
+
_mouseDown = () => {
|
|
128
|
+
const { interactivityData } = this._interactionManager, { mouse } = interactivityData;
|
|
129
|
+
mouse.clicking = true;
|
|
130
|
+
mouse.downPosition = mouse.position;
|
|
131
|
+
};
|
|
132
|
+
_mouseTouchClick = e => {
|
|
133
|
+
const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, { mouse } = interactionManager.interactivityData;
|
|
134
|
+
mouse.inside = true;
|
|
135
|
+
let handled = false;
|
|
136
|
+
const mousePosition = mouse.position;
|
|
137
|
+
if (!mousePosition || !options.interactivity?.events.onClick.enable) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
for (const plugin of this._clickPositionPlugins) {
|
|
141
|
+
handled = plugin.clickPositionValid?.(mousePosition) ?? false;
|
|
142
|
+
if (handled) {
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!handled) {
|
|
147
|
+
this._doMouseTouchClick(e);
|
|
148
|
+
}
|
|
149
|
+
mouse.clicking = false;
|
|
150
|
+
};
|
|
151
|
+
_mouseTouchFinish = () => {
|
|
152
|
+
const { interactivityData } = this._interactionManager, { mouse } = interactivityData;
|
|
153
|
+
delete mouse.position;
|
|
154
|
+
delete mouse.clickPosition;
|
|
155
|
+
delete mouse.downPosition;
|
|
156
|
+
interactivityData.status = mouseLeaveEvent;
|
|
157
|
+
mouse.inside = false;
|
|
158
|
+
mouse.clicking = false;
|
|
159
|
+
};
|
|
160
|
+
_mouseTouchMove = e => {
|
|
161
|
+
const container = this._container, interactionManager = this._interactionManager, options = container.actualOptions, interactivity = interactionManager.interactivityData, canvasEl = container.canvas.element;
|
|
162
|
+
if (!interactivity.element) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
interactivity.mouse.inside = true;
|
|
166
|
+
let pos;
|
|
167
|
+
if (e.type.startsWith("pointer")) {
|
|
168
|
+
this._canPush = true;
|
|
169
|
+
const mouseEvent = e;
|
|
170
|
+
if (interactivity.element === globalThis) {
|
|
171
|
+
if (canvasEl) {
|
|
172
|
+
const clientRect = canvasEl.getBoundingClientRect();
|
|
173
|
+
pos = {
|
|
174
|
+
x: mouseEvent.clientX - clientRect.left,
|
|
175
|
+
y: mouseEvent.clientY - clientRect.top,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (options.interactivity?.detectsOn === InteractivityDetect.parent) {
|
|
180
|
+
const source = mouseEvent.target, target = mouseEvent.currentTarget;
|
|
181
|
+
if (canvasEl) {
|
|
182
|
+
const sourceRect = source.getBoundingClientRect(), targetRect = target.getBoundingClientRect(), canvasRect = canvasEl.getBoundingClientRect();
|
|
183
|
+
pos = {
|
|
184
|
+
x: mouseEvent.offsetX + double * sourceRect.left - (targetRect.left + canvasRect.left),
|
|
185
|
+
y: mouseEvent.offsetY + double * sourceRect.top - (targetRect.top + canvasRect.top),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
pos = {
|
|
190
|
+
x: mouseEvent.offsetX,
|
|
191
|
+
y: mouseEvent.offsetY,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else if (mouseEvent.target === canvasEl) {
|
|
196
|
+
pos = {
|
|
197
|
+
x: mouseEvent.offsetX,
|
|
198
|
+
y: mouseEvent.offsetY,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
this._canPush = e.type !== "touchmove";
|
|
204
|
+
if (canvasEl) {
|
|
205
|
+
const touchEvent = e, lastTouch = touchEvent.touches[touchEvent.touches.length - lengthOffset], canvasRect = canvasEl.getBoundingClientRect();
|
|
206
|
+
if (!lastTouch) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
pos = {
|
|
210
|
+
x: lastTouch.clientX - canvasRect.left,
|
|
211
|
+
y: lastTouch.clientY - canvasRect.top,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const pxRatio = container.retina.pixelRatio;
|
|
216
|
+
if (pos) {
|
|
217
|
+
pos.x *= pxRatio;
|
|
218
|
+
pos.y *= pxRatio;
|
|
219
|
+
}
|
|
220
|
+
interactivity.mouse.position = pos;
|
|
221
|
+
interactivity.status = mouseMoveEvent;
|
|
222
|
+
};
|
|
223
|
+
_touchEnd = e => {
|
|
224
|
+
const evt = e, touches = Array.from(evt.changedTouches);
|
|
225
|
+
for (const touch of touches) {
|
|
226
|
+
this._touches.delete(touch.identifier);
|
|
227
|
+
}
|
|
228
|
+
this._mouseTouchFinish();
|
|
229
|
+
};
|
|
230
|
+
_touchEndClick = e => {
|
|
231
|
+
const evt = e, touches = Array.from(evt.changedTouches);
|
|
232
|
+
for (const touch of touches) {
|
|
233
|
+
this._touches.delete(touch.identifier);
|
|
234
|
+
}
|
|
235
|
+
this._mouseTouchClick(e);
|
|
236
|
+
};
|
|
237
|
+
_touchStart = e => {
|
|
238
|
+
const evt = e, touches = Array.from(evt.changedTouches);
|
|
239
|
+
for (const touch of touches) {
|
|
240
|
+
this._touches.set(touch.identifier, performance.now());
|
|
241
|
+
}
|
|
242
|
+
this._mouseTouchMove(e);
|
|
243
|
+
};
|
|
244
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { deepExtend, } from "@tsparticles/engine";
|
|
2
|
+
import { Interactivity } from "./Options/Classes/Interactivity.js";
|
|
3
|
+
export class InteractivityPlugin {
|
|
4
|
+
id = "interactivity";
|
|
5
|
+
_engine;
|
|
6
|
+
constructor(engine) {
|
|
7
|
+
this._engine = engine;
|
|
8
|
+
}
|
|
9
|
+
async getPlugin(container) {
|
|
10
|
+
const { InteractivityPluginInstance } = await import("./InteractivityPluginInstance.js");
|
|
11
|
+
return new InteractivityPluginInstance(this._engine, container);
|
|
12
|
+
}
|
|
13
|
+
loadOptions(container, options, source) {
|
|
14
|
+
if (!this.needsPlugin()) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let interactivityOptions = options.interactivity;
|
|
18
|
+
if (!interactivityOptions?.load) {
|
|
19
|
+
options.interactivity = interactivityOptions = new Interactivity(this._engine, container);
|
|
20
|
+
}
|
|
21
|
+
interactivityOptions.load(source?.interactivity);
|
|
22
|
+
const interactors = this._engine.interactors?.get(container);
|
|
23
|
+
if (!interactors) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
for (const interactor of interactors) {
|
|
27
|
+
if (interactor.loadOptions) {
|
|
28
|
+
interactor.loadOptions(options, source);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
loadParticlesOptions(container, options, source) {
|
|
33
|
+
if (source?.interactivity) {
|
|
34
|
+
options.interactivity = deepExtend({}, source.interactivity);
|
|
35
|
+
}
|
|
36
|
+
const interactors = this._engine.interactors?.get(container);
|
|
37
|
+
if (!interactors) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
for (const interactor of interactors) {
|
|
41
|
+
if (interactor.loadParticlesOptions) {
|
|
42
|
+
interactor.loadParticlesOptions(options, source);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
needsPlugin() {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|