UNPKG

fidget-pincher

Version:

- [jsDelivr CDN](https://cdn.jsdelivr.net/npm/fidget-pincher/): `<script src="https://cdn.jsdelivr.net/npm/fidget-pincher/dist/bundle.min.js"></script>` - [unpkg CDN](https://unpkg.com/fidget-pincher/): `<script src="https://unpkg.com/fidget-pincher/dist

2 lines (1 loc) 12.2 kB
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t="undefined"!=typeof globalThis?globalThis:t||self).FidgetPincher=n()}(this,(function(){"use strict";class t{static identity(){return new t(1,0,0,1,0,0)}static translation(n,e){return new t(1,0,0,1,n,e)}static rotation(n){const e=Math.cos(n),i=Math.sin(n);return new t(e,i,-i,e,0,0)}static scale(n,e){return new t(n,0,0,e,0,0)}constructor(t,n,e,i,s,o){this.a=t,this.b=n,this.c=e,this.d=i,this.e=s,this.f=o}multiplyMatrix(n){const e=[this.a,this.c,this.e,this.b,this.d,this.f,0,0,1],i=[n.a,n.c,n.e,n.b,n.d,n.f,0,0,1],[s,o,r,a,l,h,c,p,u]=function(t,n){const[e,i,s,o,r,a,l,h,c]=t,[p,u,m,d,f,g,y,v,w]=n;return[e*p+i*d+s*y,e*u+i*f+s*v,e*m+i*g+s*w,o*p+r*d+a*y,o*u+r*f+a*v,o*m+r*g+a*w,l*p+h*d+c*y,l*u+h*f+c*v,l*m+h*g+c*w]}(e,i);return new t(s,a,o,l,r,h)}toCSSMatrix(){const{a:t,b:n,c:e,d:i,e:s,f:o}=this;return`matrix(${t}, ${n}, ${e}, ${i}, ${s}, ${o})`}decompose(){const{a:t,b:n,c:e,d:i,e:s,f:o}=this;return{translateX:s,translateY:o,scale:Math.hypot(t,n),rotate:Math.atan2(n,t)}}toCSSDecomposed(){const{translateX:t,translateY:n,scale:e,rotate:i}=this.decompose();return`translate(${t}px, ${n}px) rotate(${i}rad) scale(${e})`}calculateTransformOrigin(){const{a:t,b:n,c:e,d:i,e:s,f:o}=this,r=function(t,n,e,i,s,o){const r=t*s-n*i;return 0===r?null:[(e*s-n*o)/r,(t*o-e*i)/r]}(t-1,e,-s,n,i-1,-o);if(null===r)return null;const[a,l]=r;return{x:a,y:l}}}function n(t){return Object.assign(Object.assign({},{minimumTime:100,minimumSnapshots:3,brakingTime:1e3,maximumPinchReleaseTime:300}),t)}function e(t,n){if(t.length<n.minimumSnapshots)throw new Error("Not enough snapshots");let e=0,i=Array(t[0].deltas.length).fill(0),s=0;for(let o=t.length-1;o>=0;o--){const r=t[o];e+=r.dt;for(let t=0;t<r.deltas.length;t++)i[t]+=r.deltas[t];if(s++,e>=n.minimumTime&&s>=n.minimumSnapshots)break}return{velocities:i.map((t=>t/e)),time:e,count:s}}function i(t,n){const{brakingTime:e}=t,i=performance.now();let s=!0,o=requestAnimationFrame((function t(r){if(!s)return;const a=r-i,l=Math.min(a,e);n({mappedTime:l*(1-l/(2*e))}),a<e?o=requestAnimationFrame(t):s=!1}));return{isRunning:()=>s,stop:()=>{s=!1,cancelAnimationFrame(o)}}}function s(t,e,s){s=n(s);let o=0,r=0;return i(s,(({mappedTime:n})=>{const i=t.vx*n-o,s=t.vy*n-r;o+=i,r+=s,e(i,s)}))}function o(t){let[n,e]=[0,0];for(const i of t)n+=i.x,e+=i.y;return{x:n/t.length,y:e/t.length}}function r(t){const{x:n,y:e}=o(t);let i=0;for(const s of t)i+=Math.hypot(s.x-n,s.y-e);return i/t.length}function a(t,n){const e=o(t),i=o(n),s=r(t),a=r(n),l=function(t,n){if(t.length!==n.length)throw new Error("prevPoints and nextPoints must have the same length");const e=o(t),i=o(n);let s=0;for(let o=0;o<t.length;o++){const a=t[o],l=n[o],h=Math.atan2(a.y-e.y,a.x-e.x);s+=(void 0,r=void 0,((Math.atan2(l.y-i.y,l.x-i.x)-h+Math.PI)%(r=2*Math.PI)+r)%r-Math.PI)}var r;return s/t.length}(t,n),h=a/s;return{dx:i.x-e.x,dy:i.y-e.y,scale:h,rotation:l,prevCentroid:e,nextCentroid:i}}class l{get options(){return this.optionsGetter.get()}constructor(t,n,e){this.optionsGetter=t,this.transform=n,this.__owner=e,this.t=0,this.translations=[],this.translationApplyResult=null,this.pinches=[],this.fidgetSpinApplyResult=null,this.fidgetSpinPivot={x:0,y:0},this.pinchApplyResult=null,this.pinchReleaseTimestamp=0}onStart(t,n){var e,i,s,o,r;this.translations=[],1===t?(this.options.stopTranslateInertiaOnTouch&&(null===(e=this.translationApplyResult)||void 0===e||e.stop(),this.translationApplyResult=null),this.options.stopFidgetSpinInertiaOnTouch&&(null===(i=this.fidgetSpinApplyResult)||void 0===i||i.stop(),this.fidgetSpinApplyResult=null),this.options.stopPinchInertiaOnTouch&&(null===(s=this.pinchApplyResult)||void 0===s||s.stop(),this.pinchApplyResult=null)):2===t&&(this.pinches=[],this.options.stopFidgetSpinInertiaOnPinch&&(null===(o=this.fidgetSpinApplyResult)||void 0===o||o.stop(),this.fidgetSpinApplyResult=null),this.options.stopPinchInertiaOnPinch&&(null===(r=this.pinchApplyResult)||void 0===r||r.stop(),this.pinchApplyResult=null)),this.t=n}onTranslate(t,n,e){this.fidgetSpinPivot.x=this.__owner.pointers[0].x,this.fidgetSpinPivot.y=this.__owner.pointers[0].y;const i=e-this.t;this.translations.push({dx:t,dy:n,dt:i}),this.t=e}onPinch(t,n){const e=n-this.t;this.pinches.push({pinch:t,dt:e}),this.t=n}onEnd(o){var r;if(this.options.enableInertia)if(1===o&&(this.pinchReleaseTimestamp=this.t),0===o&&this.options.enablePinchInertia&&this.t-this.pinchReleaseTimestamp<(a=n(a)).maximumPinchReleaseTime){this.pinchReleaseTimestamp=0,this.options.stopFidgetSpinInertiaOnPinchInertia&&(null===(r=this.fidgetSpinApplyResult)||void 0===r||r.stop(),this.fidgetSpinApplyResult=null);const o=function(i,s){if(s=n(s),i.length<s.minimumSnapshots)return null;const o=e(i.map((t=>({deltas:[],dt:t.dt}))),s);let r=t.identity();for(const n of i.slice(-o.count)){const{dx:e,dy:i,scale:s,rotation:o,prevCentroid:a}=n.pinch,l=[t.translation(-a.x,-a.y),t.rotation(o),t.scale(s,s),t.translation(e,i),t.translation(a.x,a.y)];for(const t of l)r=t.multiplyMatrix(r)}const{translateX:a,translateY:l,scale:h,rotate:c}=r.decompose();return{angularVelocity:c/o.time,scalingConstant:Math.pow(h,1/o.time),transformOrigin:r.calculateTransformOrigin(),velocityX:a/o.time,velocityY:l/o.time}}(this.pinches);if(o){const e=function(e,o,r){if(null===e.transformOrigin)return s({vx:e.velocityX,vy:e.velocityY},((n,e)=>{o(t.translation(n,e))}),r);r=n(r);const{x:a,y:l}=e.transformOrigin;let h=0,c=1;return i(r,(({mappedTime:n})=>{const i=e.angularVelocity*n-h,s=Math.pow(e.scalingConstant,n)/c;h+=i,c*=s;const r=[t.translation(-a,-l),t.rotation(i),t.scale(s,s),t.translation(a,l)];let p=t.identity();for(const t of r)p=t.multiplyMatrix(p);o(p)}))}(o,(t=>{let n=this.transform.get();n=t.multiplyMatrix(n),this.transform.set(n)}));this.pinchApplyResult=e}}else{var a;if(0===o&&this.options.enableTranslateInertia){const i=function(t,i){if(i=n(i),t.length<i.minimumSnapshots)return null;const s=e(t.map((t=>({deltas:[t.dx,t.dy],dt:t.dt}))),i),[o,r]=s.velocities;return{vx:o,vy:r}}(this.translations);if(i){const n=s(i,((n,e)=>{this.fidgetSpinPivot.x+=n,this.fidgetSpinPivot.y+=e;let i=this.transform.get();i=t.translation(n,e).multiplyMatrix(i),this.transform.set(i)}));this.translationApplyResult=n}}if(1===o&&this.options.enableFidgetSpinInertia){const s=function(t,i){if(i=n(i),t.length<i.minimumSnapshots)return null;const s=e(t.map((t=>({deltas:[t.pinch.rotation],dt:t.dt}))),i),[o]=s.velocities,r=t.slice(-s.count).map((t=>t.pinch.scale)).reduce(((t,n)=>t*n),1);return{angularVelocity:o,scalingConstant:Math.pow(r,1/s.time)}}(this.pinches);if(s){const e=function(t,e,s){s=n(s);let o=0,r=1;return i(s,(({mappedTime:n})=>{const i=t.angularVelocity*n-o,s=Math.pow(t.scalingConstant,n)/r;o+=i,r*=s,e(i,s)}))}(s,((n,e)=>{const{x:i,y:s}=this.fidgetSpinPivot;let o=this.transform.get();const r=[t.translation(-i,-s),t.rotation(n),t.scale(e,e),t.translation(i,s)];for(const t of r)o=t.multiplyMatrix(o);this.transform.set(o)}));this.fidgetSpinApplyResult=e}}}}}class h{constructor(t,n,e){this.owner=t,this.x=n,this.y=e}move(n,e,i){if(1===this.owner.pointers.length){const s=n-this.x,o=e-this.y;this.owner.transform=t.translation(s,o).multiplyMatrix(this.owner.transform),this.x=n,this.y=e,this.owner.inertia.onTranslate(s,o,i),this.owner.notifyTransformed()}else if(this.owner.pointers.length>=2){const s=this.owner.pointers.map((t=>({x:t.x,y:t.y})));this.x=n,this.y=e;const o=a(s,this.owner.pointers.map((t=>({x:t.x,y:t.y})))),{dx:r,dy:l,scale:h,rotation:c,prevCentroid:p}=o,u=[t.translation(-p.x,-p.y),t.rotation(c),t.scale(h,h),t.translation(r,l),t.translation(p.x,p.y)];for(const t of u)this.owner.transform=t.multiplyMatrix(this.owner.transform);this.owner.inertia.onPinch(o,i),this.owner.notifyTransformed()}}remove(){const t=this.owner.pointers.indexOf(this);t>=0&&this.owner.pointers.splice(t,1),this.owner.inertia.onEnd(this.owner.pointers.length)}}class c{constructor(n){this.options=n,this.transformedCallbacks=[],this.pointers=[],this.transform=t.identity(),this.inertia=new l({get:()=>this.options},{get:()=>this.transform,set:t=>{this.transform=t,this.notifyTransformed()}},this)}setOptions(t){this.options=t}addPointer(t,n,e){const i=new h(this,t,n);return this.pointers.push(i),this.inertia.onStart(this.pointers.length,e),i}addTransformedCallback(t){this.transformedCallbacks.push(t)}removeTransformedCallback(t){const n=this.transformedCallbacks.indexOf(t);n>=0&&this.transformedCallbacks.splice(n,1)}notifyTransformed(){for(const t of this.transformedCallbacks)try{t(this.transform)}catch(t){console.error(t)}}}class p{constructor(t){this.impl=new c(Object.assign(Object.assign({},{enableInertia:!0,enableTranslateInertia:!0,enableFidgetSpinInertia:!0,enablePinchInertia:!0,stopTranslateInertiaOnTouch:!0,stopFidgetSpinInertiaOnPinch:!0,stopFidgetSpinInertiaOnTouch:!0,stopPinchInertiaOnPinch:!0,stopPinchInertiaOnTouch:!0,stopFidgetSpinInertiaOnPinchInertia:!0}),t)),this.pointerMap=new Map}setOptions(t){this.impl.setOptions(Object.assign(Object.assign({},{enableInertia:!0,enableTranslateInertia:!0,enableFidgetSpinInertia:!0,enablePinchInertia:!0,stopTranslateInertiaOnTouch:!0,stopFidgetSpinInertiaOnPinch:!0,stopFidgetSpinInertiaOnTouch:!0,stopPinchInertiaOnPinch:!0,stopPinchInertiaOnTouch:!0,stopFidgetSpinInertiaOnPinchInertia:!0}),t))}addPointer(t,n,e,i){const s=this.impl.addPointer(n,e,i);this.pointerMap.set(t,s)}movePointer(t,n,e,i){const s=this.pointerMap.get(t);s&&s.move(n,e,i)}removePointer(t){const n=this.pointerMap.get(t);n&&n.remove()}setTouchElement(t,n){const e=this.createEvents(t);t.addEventListener("mousedown",e.mousedown),t.addEventListener("touchstart",e.touchstart),t.addEventListener("touchmove",e.touchmove),t.addEventListener("touchend",e.touchend);const{onTransformed:i}=n;return void 0!==i&&this.impl.addTransformedCallback(i),()=>{t.removeEventListener("mousedown",e.mousedown),t.removeEventListener("touchstart",e.touchstart),t.removeEventListener("touchmove",e.touchmove),t.removeEventListener("touchend",e.touchend),void 0!==i&&this.impl.removeTransformedCallback(i)}}getTransform(){return this.impl.transform}static parseTransform(n){if(n instanceof t)return n;if(Array.isArray(n)){const[e,i,s,o,r,a]=n;return new t(e,i,s,o,r,a)}if("string"==typeof n){const e=n.match(/^matrix\((.+)\)$/);if(e){const[n,i,s,o,r,a]=e[1].split(",").map(parseFloat);return new t(n,i,s,o,r,a)}}if("object"==typeof n){const{a:e,b:i,c:s,d:o,e:r,f:a}=n;return new t(e,i,s,o,r,a)}throw new Error(`Invalid transform: ${n}`)}setTransform(n){n instanceof t||(n=p.parseTransform(n)),this.impl.transform=n}clearTouchPointers(){this.pointerMap.clear(),this.impl.pointers=[]}createEvents(t){const n={mousedown:e=>{window.addEventListener("mousemove",n.mousemove),window.addEventListener("mouseup",n.mouseup);const{clientX:i,clientY:s}=e,{left:o,top:r,width:a,height:l}=t.getBoundingClientRect(),h=i-(o+a/2),c=s-(r+l/2),p=performance.now();this.addPointer("mouse",h,c,p)},mousemove:n=>{const{clientX:e,clientY:i}=n,{left:s,top:o,width:r,height:a}=t.getBoundingClientRect(),l=e-(s+r/2),h=i-(o+a/2),c=performance.now();this.movePointer("mouse",l,h,c)},mouseup:e=>{window.removeEventListener("mousemove",n.mousemove),window.removeEventListener("mouseup",n.mouseup);const{clientX:i,clientY:s}=e,{left:o,top:r,width:a,height:l}=t.getBoundingClientRect(),h=i-(o+a/2),c=s-(r+l/2),p=performance.now();this.movePointer("mouse",h,c,p),this.removePointer("mouse")},touchstart:n=>{const{left:e,top:i,width:s,height:o}=t.getBoundingClientRect(),r=e+s/2,a=i+o/2,l=performance.now();for(const t of n.changedTouches){const{identifier:n,clientX:e,clientY:i}=t,s=e-r,o=i-a;this.addPointer(n,s,o,l)}},touchmove:n=>{const{left:e,top:i,width:s,height:o}=t.getBoundingClientRect(),r=e+s/2,a=i+o/2,l=performance.now();for(const t of n.changedTouches){const{identifier:n,clientX:e,clientY:i}=t,s=e-r,o=i-a;this.movePointer(n,s,o,l)}},touchend:n=>{const{left:e,top:i,width:s,height:o}=t.getBoundingClientRect(),r=e+s/2,a=i+o/2,l=performance.now();for(const t of n.changedTouches){const{identifier:n,clientX:e,clientY:i}=t,s=e-r,o=i-a;this.movePointer(n,s,o,l),this.removePointer(n)}}};return n}}return p.TransformationMatrix=t,p}));