UNPKG

coherent-gameface-interaction-manager

Version:
7 lines (6 loc) 10.2 kB
(function(d,E){typeof exports=="object"&&typeof module<"u"?module.exports=E():typeof define=="function"&&define.amd?define(E):(d=typeof globalThis<"u"?globalThis:d||self,d.rotate=E())})(this,(function(){"use strict";function d(c){return c*180/Math.PI}function E(){return(Math.random()+1).toString(36).substring(7)}function M(c,e,t,n){const i=c-t,s=e-n;return Math.hypot(i,s)}function F(c,e,t,n){return{x:(c+t)/2,y:(e+n)/2}}class I{constructor(){this.actions=[],this.keyboardFunctions=[],this.gamepadFunctions=[]}init(){window._IM||(window._IM=new I)}getKeys(e){return _IM.keyboardFunctions.filter(t=>t.keys.every(n=>e.includes(n)))}getKeysIndex(e){return _IM.keyboardFunctions.findIndex(t=>t.keys.every(n=>e.includes(n)))}getGamepadAction({actions:e,type:t}){return _IM.gamepadFunctions.find(n=>n.actions.every(i=>e.includes(i))&&n.type===t&&n.actions.length===e.length)}getGamepadActions(e,t=!0){return _IM.gamepadFunctions.filter(n=>n.actions.every(i=>e.includes(i))&&(t?n.actions.length===e.length:!0))}getGamepadActionIndex(e){return _IM.gamepadFunctions.findIndex(t=>t.actions.every(n=>e.includes(n)))}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(n=>n===t)}addCallbackToEntry(e,t,n){if(this.hasDuplicateCallback(e,t)){const i=typeof t=="string"?"action":"function",s=typeof t=="string"?t:"(anonymous function)";return console.error(`Duplicate callback detected! ${n.identifier} Type: '${n.type}' Callback: ${s} This ${i} 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 I;class L{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 n=f.getAction(e);if(!n)return console.error(`${e} is not a registered action!`);n.callback(t)}}const p=new L;function y(c,e){if(e<0&&c>-200&&c<200)return"top";if(e>0&&c>-200&&c<200)return"bottom";if(c<0&&e>-200&&e<200)return"left";if(c>0&&e>-200&&e<200)return"right";if(c<=-200&&e<=-200)return"top-left";if(c>=200&&e<=-200)return"top-right";if(c<=-200&&e>=200)return"bottom-left";if(c>=200&&e>=200)return"bottom-right"}function m(c){return c instanceof HTMLElement?c:document.querySelector(c)}const g=2;class N{constructor(){this.activeTouches=new Map}hold(e){if(!e)return console.error("Options not provided for hold!");let t;const n=m(e.element);if(!n)return console.error("Element not found!");const i=({touches:o})=>{this.activeTouches.set(o[0].identifier,o[0]),t=setTimeout(()=>{e.callback&&e.callback()},e.time||1e3)},s=({touches:o})=>{this.activeTouches.delete(o[0].identifier),clearTimeout(t)};return n.addEventListener("touchstart",i),n.addEventListener("touchend",s),{remove(){n.removeEventListener("touchstart",i),n.removeEventListener("touchend",s)}}}tap(e){if(!e)return console.error("Options not provided for tap!");let t,n,i=!0,s=e.tapsNumber||1;const o=m(e.element);if(!o)return console.error("Element not found!");const l=({touches:r})=>{this.activeTouches.set(r[0].identifier,r[0]),clearTimeout(n),i=!0,t=setTimeout(()=>{i=!1},e.tapTime||200)},a=({touches:r})=>{this.activeTouches.delete(r[0].identifier),clearTimeout(t),i&&(s--,n=setTimeout(()=>{s=e.tapsNumber||1,clearTimeout(n)},e.betweenTapsTime||500),!(s!==0||!e.callback)&&(e.callback(),i=!0,clearTimeout(t),s=e.tapsNumber||1))};return o.addEventListener("touchstart",l),o.addEventListener("touchend",a),{remove(){o.removeEventListener("touchstart",l),o.removeEventListener("touchend",a)}}}drag(e){if(!e)return console.error("Options not provided for drag!");const t=m(e.element);if(!t)return console.error("Element not found!");const n=({touches:o,target:l,currentTarget:a})=>{this.activeTouches.set(o[0].identifier,o[0]),document.addEventListener("touchmove",i),document.addEventListener("touchend",s),e.onDragStart&&e.onDragStart({x:o[0].clientX,y:o[0].clientY,target:l,currentTarget:a})},i=({touches:o})=>{this.activeTouches.has(o[0].identifier)&&e.onDrag&&e.onDrag({x:o[0].clientX,y:o[0].clientY})},s=({touches:o})=>{this.activeTouches.delete(o[0].identifier),document.removeEventListener("touchmove",i),document.removeEventListener("touchend",s),e.onDragEnd&&e.onDragEnd({x:o[0].clientX,y:o[0].clientY})};return t.addEventListener("touchstart",n),{remove(){t.removeEventListener("touchstart",n)}}}swipe(e){if(!e)return console.error("Options not provided for swipe!");let t,n,i,s=!0;const o=100;e.touchNumber||=1;const l=m(e.element);if(!l)return console.error("Element not found!");const a=({touches:u})=>{this.activeTouches.set(u[0].identifier,u[0]),this.activeTouches.size>e.touchNumber&&(document.removeEventListener("touchmove",r),document.removeEventListener("touchend",h)),this.activeTouches.size===e.touchNumber&&(t=setTimeout(()=>{s=!1,clearTimeout(t),t=null},1e3),document.addEventListener("touchmove",r),document.addEventListener("touchend",h))},r=({touches:u})=>{if(!this.activeTouches.has(u[0].identifier))return;const T=this.activeTouches.get(u[0].identifier);if(!T)return;const{clientX:S,clientY:b}=T,D=u[0].clientX-S,A=u[0].clientY-b;n=y(D,A),i=M(S,b,u[0].clientX,u[0].clientY)},h=({touches:u})=>{this.activeTouches.delete(u[0].identifier),this.activeTouches.size===0&&(document.removeEventListener("touchmove",r),document.removeEventListener("touchend",h),v()&&e.callback(n),clearTimeout(t),s=!0,t=null)},v=()=>s&&n&&i&&i>o;return l.addEventListener("touchstart",a),{remove(){l.removeEventListener("touchstart",a)}}}pinch(e){if(!e)return console.error("Options not provided for pinch!");let t;const n=40,i=m(e.element);if(!i)return console.error("Element not found!");const s=({touches:a})=>{if(this.activeTouches.set(a[0].identifier,a[0]),this.activeTouches.size<g)return;const r=this.activeTouches.get(0),h=this.activeTouches.get(1);!r||!h||(document.addEventListener("touchmove",o),document.addEventListener("touchend",l),t=M(r.clientX,r.clientY,h.clientX,h.clientY))},o=({touches:a})=>{if(this.activeTouches.size!==g)return;this.activeTouches.set(a[0].identifier,a[0]);const r=this.activeTouches.get(0),h=this.activeTouches.get(1);if(!r||!h)return;const v=M(r.clientX,r.clientY,h.clientX,h.clientY),u=Math.sign(v-t)*n;t=v;const T=F(r.clientX,r.clientY,h.clientX,h.clientY);e.callback&&e.callback({pinchDelta:u,midpoint:T})},l=({touches:a})=>{this.activeTouches.delete(a[0].identifier),this.activeTouches.size===0&&(document.removeEventListener("touchmove",o),document.removeEventListener("touchend",l))};return i.addEventListener("touchstart",s),{remove(){i.removeEventListener("touchstart",s)}}}rotate(e){if(!e)return console.error("Options not provided for rotate!");let t=0,n=0;const i=m(e.element);if(!i)return console.error("Element not found!");const s=({touches:r})=>{this.activeTouches.size<g||(this.activeTouches.set(r[0].identifier,r[0]),t=a()-n,e.callback&&e.callback(t))},o=({touches:r})=>{this.activeTouches.set(r[0].identifier,r[0]),this.activeTouches.size===g&&(n=a()-t,document.addEventListener("touchmove",s),document.addEventListener("touchend",l))},l=({touches:r})=>{this.activeTouches.delete(r[0].identifier),document.removeEventListener("touchmove",s),document.removeEventListener("touchend",l)};i.addEventListener("touchstart",o);const a=()=>{const v=this.activeTouches.get(0).clientY-this.activeTouches.get(1).clientY,u=this.activeTouches.get(0).clientX-this.activeTouches.get(1).clientX;return(d(Math.atan2(v,u))+360+90)%360};return{remove(){i.removeEventListener("touchstart",o)}}}}const w=new N,_=360,O=90;class P{constructor(e){this.rotatingElement=null,this.elementPosition={x:0,y:0},this.angle=0,this.enabled=!1,this.initalAngle=0,this.actionName=`rotate-${E()}`,this.touchEvents=null,this._touchEnabled=!1,this.options=e,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.rotatingElement=this.rotatingElement||document.querySelector(this.options.element),!this.rotatingElement)return console.error(`${this.options.element} is not a valid element selector`);this.rotatingElement.addEventListener("mousedown",this.onMouseDown),this.registerAction(),this.enabled=!0}}deinit(){this.enabled&&(this.rotatingElement.removeEventListener("mousedown",this.onMouseDown),this.removeActions(),this.enabled=!1)}onMouseDown(e){document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mouseup",this.onMouseUp);const{x:t,y:n,height:i,width:s}=this.rotatingElement.getBoundingClientRect();this.elementPosition={x:t+s/2,y:n+i/2};const o=this.getAngle(e.clientX,e.clientY);this.initalAngle=o-this.angle}onMouseMove(e){this.angle=this.getAngle(e.clientX,e.clientY)-this.initalAngle,this.options.snapAngle&&(this.angle=Math.floor(this.angle/this.options.snapAngle)*this.options.snapAngle),p.execute(this.actionName,this.angle)}onMouseUp(){document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp)}registerAction(){p.register(this.actionName,e=>{this.rotatingElement.style.transform=`rotate(${e}deg)`,this.options.onRotation&&this.options.onRotation(e<0?_+e:e)})}removeActions(){p.remove(this.actionName)}addTouchEvents(){this.touchEvents=w.drag({element:this.rotatingElement,onDragStart:({x:e,y:t})=>{this.onMouseDown({clientX:e,clientY:t})},onDrag:({x:e,y:t})=>{this.onMouseMove({clientX:e,clientY:t})},onDragEnd:()=>{this.onMouseUp()}})}removeTouchEvents(){this.touchEvents?.remove(),this.touchEvents=null}getAngle(e,t){const n=e-this.elementPosition.x,i=t-this.elementPosition.y;return(d(Math.atan2(i,n))+_+O)%_}}return f.init(),P})); //# sourceMappingURL=rotate.min.js.map