coherent-gameface-interaction-manager
Version:
Library for the most common UI interactions
7 lines (6 loc) • 12.2 kB
JavaScript
(function(E,l){typeof exports=="object"&&typeof module<"u"?module.exports=l():typeof define=="function"&&define.amd?define(l):(E=typeof globalThis<"u"?globalThis:E||self,E.resize=l())})(this,(function(){"use strict";function E(r){return r*180/Math.PI}function l(r,e,t){return Math.min(Math.max(r,e),t)}function w(){return(Math.random()+1).toString(36).substring(7)}function M(r,e,t,i){const n=r-t,c=e-i;return Math.hypot(n,c)}function y(r,e,t,i){return{x:(r+t)/2,y:(e+i)/2}}class b{constructor(){this.actions=[],this.keyboardFunctions=[],this.gamepadFunctions=[]}init(){window._IM||(window._IM=new b)}getKeys(e){return _IM.keyboardFunctions.filter(t=>t.keys.every(i=>e.includes(i)))}getKeysIndex(e){return _IM.keyboardFunctions.findIndex(t=>t.keys.every(i=>e.includes(i)))}getGamepadAction({actions:e,type:t}){return _IM.gamepadFunctions.find(i=>i.actions.every(n=>e.includes(n))&&i.type===t&&i.actions.length===e.length)}getGamepadActions(e,t=!0){return _IM.gamepadFunctions.filter(i=>i.actions.every(n=>e.includes(n))&&(t?i.actions.length===e.length:!0))}getGamepadActionIndex(e){return _IM.gamepadFunctions.findIndex(t=>t.actions.every(i=>e.includes(i)))}getAction(e){return _IM.actions.find(t=>t.name===e)}getActionIndex(e){return _IM.actions.findIndex(t=>t.name===e)}hasDuplicateCallback(e,t){return e.callbacks.some(i=>i===t)}addCallbackToEntry(e,t,i){if(this.hasDuplicateCallback(e,t)){const n=typeof t=="string"?"action":"function",c=typeof t=="string"?t:"(anonymous function)";return console.error(`Duplicate callback detected!
${i.identifier}
Type: '${i.type}'
Callback: ${c}
This ${n} is already registered for this combination and type. To update it, first remove with the .off() method.`)}return e.callbacks.push(t)}removeKeyboardFunction(e){const t=_IM.keyboardFunctions.indexOf(e);t!==-1&&_IM.keyboardFunctions.splice(t,1)}removeGamepadFunction(e){const t=_IM.gamepadFunctions.indexOf(e);t!==-1&&_IM.gamepadFunctions.splice(t,1)}}const f=new b;class S{register(e,t){if(f.getAction(e))return console.error(`The following action "${e}" is already registered!`);_IM.actions.push({name:e,callback:t})}remove(e){const t=f.getActionIndex(e);if(t===-1)return console.error(`${e} is not a registered action!`);_IM.actions.splice(t,1)}execute(e,t){const i=f.getAction(e);if(!i)return console.error(`${e} is not a registered action!`);i.callback(t)}}const m=new S;function x(r,e){if(e<0&&r>-200&&r<200)return"top";if(e>0&&r>-200&&r<200)return"bottom";if(r<0&&e>-200&&e<200)return"left";if(r>0&&e>-200&&e<200)return"right";if(r<=-200&&e<=-200)return"top-left";if(r>=200&&e<=-200)return"top-right";if(r<=-200&&e>=200)return"bottom-left";if(r>=200&&e>=200)return"bottom-right"}function v(r){return r instanceof HTMLElement?r:document.querySelector(r)}const p=2;class F{constructor(){this.activeTouches=new Map}hold(e){if(!e)return console.error("Options not provided for hold!");let t;const i=v(e.element);if(!i)return console.error("Element not found!");const n=({touches:o})=>{this.activeTouches.set(o[0].identifier,o[0]),t=setTimeout(()=>{e.callback&&e.callback()},e.time||1e3)},c=({touches:o})=>{this.activeTouches.delete(o[0].identifier),clearTimeout(t)};return i.addEventListener("touchstart",n),i.addEventListener("touchend",c),{remove(){i.removeEventListener("touchstart",n),i.removeEventListener("touchend",c)}}}tap(e){if(!e)return console.error("Options not provided for tap!");let t,i,n=!0,c=e.tapsNumber||1;const o=v(e.element);if(!o)return console.error("Element not found!");const u=({touches:s})=>{this.activeTouches.set(s[0].identifier,s[0]),clearTimeout(i),n=!0,t=setTimeout(()=>{n=!1},e.tapTime||200)},h=({touches:s})=>{this.activeTouches.delete(s[0].identifier),clearTimeout(t),n&&(c--,i=setTimeout(()=>{c=e.tapsNumber||1,clearTimeout(i)},e.betweenTapsTime||500),!(c!==0||!e.callback)&&(e.callback(),n=!0,clearTimeout(t),c=e.tapsNumber||1))};return o.addEventListener("touchstart",u),o.addEventListener("touchend",h),{remove(){o.removeEventListener("touchstart",u),o.removeEventListener("touchend",h)}}}drag(e){if(!e)return console.error("Options not provided for drag!");const t=v(e.element);if(!t)return console.error("Element not found!");const i=({touches:o,target:u,currentTarget:h})=>{this.activeTouches.set(o[0].identifier,o[0]),document.addEventListener("touchmove",n),document.addEventListener("touchend",c),e.onDragStart&&e.onDragStart({x:o[0].clientX,y:o[0].clientY,target:u,currentTarget:h})},n=({touches:o})=>{this.activeTouches.has(o[0].identifier)&&e.onDrag&&e.onDrag({x:o[0].clientX,y:o[0].clientY})},c=({touches:o})=>{this.activeTouches.delete(o[0].identifier),document.removeEventListener("touchmove",n),document.removeEventListener("touchend",c),e.onDragEnd&&e.onDragEnd({x:o[0].clientX,y:o[0].clientY})};return t.addEventListener("touchstart",i),{remove(){t.removeEventListener("touchstart",i)}}}swipe(e){if(!e)return console.error("Options not provided for swipe!");let t,i,n,c=!0;const o=100;e.touchNumber||=1;const u=v(e.element);if(!u)return console.error("Element not found!");const h=({touches:a})=>{this.activeTouches.set(a[0].identifier,a[0]),this.activeTouches.size>e.touchNumber&&(document.removeEventListener("touchmove",s),document.removeEventListener("touchend",d)),this.activeTouches.size===e.touchNumber&&(t=setTimeout(()=>{c=!1,clearTimeout(t),t=null},1e3),document.addEventListener("touchmove",s),document.addEventListener("touchend",d))},s=({touches:a})=>{if(!this.activeTouches.has(a[0].identifier))return;const T=this.activeTouches.get(a[0].identifier);if(!T)return;const{clientX:I,clientY:_}=T,O=a[0].clientX-I,k=a[0].clientY-_;i=x(O,k),n=M(I,_,a[0].clientX,a[0].clientY)},d=({touches:a})=>{this.activeTouches.delete(a[0].identifier),this.activeTouches.size===0&&(document.removeEventListener("touchmove",s),document.removeEventListener("touchend",d),g()&&e.callback(i),clearTimeout(t),c=!0,t=null)},g=()=>c&&i&&n&&n>o;return u.addEventListener("touchstart",h),{remove(){u.removeEventListener("touchstart",h)}}}pinch(e){if(!e)return console.error("Options not provided for pinch!");let t;const i=40,n=v(e.element);if(!n)return console.error("Element not found!");const c=({touches:h})=>{if(this.activeTouches.set(h[0].identifier,h[0]),this.activeTouches.size<p)return;const s=this.activeTouches.get(0),d=this.activeTouches.get(1);!s||!d||(document.addEventListener("touchmove",o),document.addEventListener("touchend",u),t=M(s.clientX,s.clientY,d.clientX,d.clientY))},o=({touches:h})=>{if(this.activeTouches.size!==p)return;this.activeTouches.set(h[0].identifier,h[0]);const s=this.activeTouches.get(0),d=this.activeTouches.get(1);if(!s||!d)return;const g=M(s.clientX,s.clientY,d.clientX,d.clientY),a=Math.sign(g-t)*i;t=g;const T=y(s.clientX,s.clientY,d.clientX,d.clientY);e.callback&&e.callback({pinchDelta:a,midpoint:T})},u=({touches:h})=>{this.activeTouches.delete(h[0].identifier),this.activeTouches.size===0&&(document.removeEventListener("touchmove",o),document.removeEventListener("touchend",u))};return n.addEventListener("touchstart",c),{remove(){n.removeEventListener("touchstart",c)}}}rotate(e){if(!e)return console.error("Options not provided for rotate!");let t=0,i=0;const n=v(e.element);if(!n)return console.error("Element not found!");const c=({touches:s})=>{this.activeTouches.size<p||(this.activeTouches.set(s[0].identifier,s[0]),t=h()-i,e.callback&&e.callback(t))},o=({touches:s})=>{this.activeTouches.set(s[0].identifier,s[0]),this.activeTouches.size===p&&(i=h()-t,document.addEventListener("touchmove",c),document.addEventListener("touchend",u))},u=({touches:s})=>{this.activeTouches.delete(s[0].identifier),document.removeEventListener("touchmove",c),document.removeEventListener("touchend",u)};n.addEventListener("touchstart",o);const h=()=>{const g=this.activeTouches.get(0).clientY-this.activeTouches.get(1).clientY,a=this.activeTouches.get(0).clientX-this.activeTouches.get(1).clientX;return(E(Math.atan2(g,a))+360+90)%360};return{remove(){n.removeEventListener("touchstart",o)}}}}const L=new F;class W{constructor(e){this.enabled=!1,this.activeEdge=null,this.edges={bottom:null,right:null,bottomRight:null},this.elementRect={x:0,y:0},this.touchEvents=null,this._touchEnabled=!1;const t=w();this.heightAction=`resize-height-${t}`,this.widthAction=`resize-width-${t}`,this.options=e,this.options.edgeWidth=e.edgeWidth??5,this.options.heightMin=this.options.heightMin??50,this.options.heightMax=this.options.heightMax??window.innerHeight,this.options.widthMin=this.options.widthMin??50,this.options.widthMax=this.options.widthMax??window.innerWidth,this.onMouseDown=this.onMouseDown.bind(this),this.onMouseMove=this.onMouseMove.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.init()}set touchEnabled(e){this._touchEnabled!==e&&(this._touchEnabled=e,this._touchEnabled?this.addTouchEvents():this.removeTouchEvents())}init(){if(!this.enabled){if(this.resizableElement=document.querySelector(this.options.element),!this.resizableElement)return console.error(`${this.options.element} is not a correct selector`);this.resizableElement.addEventListener("mousedown",this.onMouseDown),this.addEdges(),this.registerActions(),this.enabled=!0}}deinit(){this.enabled&&(this.resizableElement.removeEventListener("mousedown",this.onMouseDown),this.removeEdges(),this.removeActions(),this.enabled=!1)}onMouseDown(e){if(this.activeEdge=this.setEdge(e.target),!this.activeEdge)return;const{x:t,y:i}=this.resizableElement.getBoundingClientRect();this.elementRect={x:t,y:i},document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mouseup",this.onMouseUp)}onMouseMove(e){const t=e.clientX-this.elementRect.x,i=e.clientY-this.elementRect.y;switch(this.activeEdge){case"bottom":m.execute(this.heightAction,i),this.options.onHeightChange&&this.options.onHeightChange(i);break;case"right":m.execute(this.widthAction,t),this.options.onWidthChange&&this.options.onWidthChange(t);break;case"bottomRight":m.execute(this.heightAction,i),m.execute(this.widthAction,t),this.options.onWidthChange&&this.options.onWidthChange(t),this.options.onHeightChange&&this.options.onHeightChange(i);break}}onMouseUp(){this.activeEdge=null,document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp)}addTouchEvents(){this.touchEvents=L.drag({element:this.resizableElement,onDragStart:e=>{this.onMouseDown(e)},onDrag:({x:e,y:t})=>{this.onMouseMove({clientX:e,clientY:t})},onDragEnd:()=>{this.onMouseUp()}})}removeTouchEvents(){this.touchEvents?.remove(),this.touchEvents=null}setEdge(e){return e.dataset.edge?e.dataset.edge:null}checkPosition(){const{position:e}=getComputedStyle(this.resizableElement);e==="absolute"||e==="relative"||(this.resizableElement.style.position="relative")}addEdges(){this.checkPosition();const{width:e,height:t}=this.resizableElement.getBoundingClientRect();Object.entries(this.edges).forEach(([i,n])=>{switch(n=document.createElement("DIV"),n.dataset.edge=i,n.style.position="absolute",i){case"bottom":n.style.width=`${e-this.options.edgeWidth}px`,n.style.height=`${this.options.edgeWidth}px`,n.style.bottom=`-${this.options.edgeWidth}px`;break;case"bottomRight":n.style.width=`${this.options.edgeWidth}px`,n.style.height=`${this.options.edgeWidth}px`,n.style.bottom=`-${this.options.edgeWidth}px`,n.style.right=`-${this.options.edgeWidth}px`;break;case"right":n.style.width=`${this.options.edgeWidth}px`,n.style.height=`${t-this.options.edgeWidth}px`,n.style.right=`-${this.options.edgeWidth}px`;break}this.edges[i]=n,this.resizableElement.appendChild(n)})}removeEdges(){Object.values(this.edges).forEach(e=>{this.resizableElement.removeChild(e)})}registerActions(){m.register(this.heightAction,e=>{this.resizableElement.style.height=`${l(e,this.options.heightMin,this.options.heightMax)}px`,this.edges.right.style.height=`${l(e,this.options.heightMin,this.options.heightMax)-this.options.edgeWidth}px`}),m.register(this.widthAction,e=>{this.resizableElement.style.width=`${l(e,this.options.widthMin,this.options.widthMax)}px`,this.edges.bottom.style.width=`${l(e,this.options.widthMin,this.options.widthMax)-this.options.edgeWidth}px`})}removeActions(){m.remove(this.heightAction),m.remove(this.widthAction)}}return f.init(),W}));
//# sourceMappingURL=resize.min.js.map