vue-data-ui
Version:
A user-empowering data visualization Vue 3 components library for eloquent data storytelling
2 lines (1 loc) • 3.44 kB
JavaScript
;const c=require("vue");function O(f,s={x:0,y:0,width:100,height:100},b=1,z){const o=c.ref({...s}),r=c.ref(1),E=c.ref(!1),y=c.ref({x:0,y:0}),x=c.ref(0),D=c.ref(null),L=c.ref(!1),k=c.computed(()=>o.value.x!==s.x||o.value.y!==s.y||o.value.width!==s.width||o.value.height!==s.height);let h={x:0,y:0},P=null,g=null;function M(e){if(e.length<2)return 0;const t=e[0].clientX-e[1].clientX,n=e[0].clientY-e[1].clientY;return Math.sqrt(t*t+n*n)}function d(e){var a;const t=f.value;if(!t)return{x:0,y:0};const n=t.createSVGPoint();n.x=e.clientX,n.y=e.clientY;const u=(a=t.getScreenCTM())==null?void 0:a.inverse();return u?n.matrixTransform(u):{x:0,y:0}}function F(e){E.value=!0;const t=d(e.touches?e.touches[0]:e);y.value={x:t.x,y:t.y},h={x:0,y:0}}function S(e){if(!E.value)return;const t=d(e.touches?e.touches[0]:e);let n=t.x-y.value.x,u=t.y-y.value.y;Math.abs(n)<.3&&Math.abs(u)<.3||(h.x=n*.8+h.x*.2,h.y=u*.8+h.y*.2,y.value=t,P||(P=requestAnimationFrame(C)))}function C(){o.value.x-=h.x,o.value.y-=h.y,P=null}function m(){E.value=!1}function G(e=!1){if(!e){o.value={...s},r.value=1;return}const t={...o.value},n=r.value,u=300;let a=null;function i(v){a||(a=v);const l=Math.min((v-a)/u,1);o.value={x:t.x+(s.x-t.x)*l,y:t.y+(s.y-t.y)*l,width:t.width+(s.width-t.width)*l,height:t.height+(s.height-t.height)*l},r.value=n+(1-n)*l,l<1?requestAnimationFrame(i):(o.value={...s},r.value=1)}requestAnimationFrame(i)}function X(e){e.preventDefault();const t=e.deltaY>0?.9:1.1;w(t,d(e))}function Z(e){e.preventDefault();const t=d(e),n=1.02*(1+b/100);H(n,t)}function H(e,t){g&&cancelAnimationFrame(g);let n=r.value,u=n*e,a=0;const i=()=>{a+=.02;let v=n+(u-n)*I(a);if(a>=1){r.value=u,g=null;return}w(v/n,t),g=requestAnimationFrame(i)};i()}const I=e=>e<.5?2*e*e:-1+(4-2*e)*e;function w(e,t){const n=r.value*e,u=n/r.value,a=o.value.width/u,i=o.value.height/u,v=(t.x-o.value.x)*(1-1/u),l=(t.y-o.value.y)*(1-1/u);o.value.x+=v,o.value.y+=l,o.value.width=a,o.value.height=i,r.value=n}function q(e){e.touches.length===2?(L.value=!0,x.value=M(e.touches),D.value={...o.value}):(e.preventDefault(),F(e))}function A(e){if(L.value&&e.touches.length===2){e.preventDefault();const t=M(e.touches);if(x.value){const n=t/x.value,a=f.value.getBoundingClientRect(),i=(e.touches[0].clientX+e.touches[1].clientX)/2-a.left,v=(e.touches[0].clientY+e.touches[1].clientY)/2-a.top,l=d({clientX:i+a.left,clientY:v+a.top});o.value={...D.value},w(n,l)}}else e.preventDefault(),S(e)}function p(e){e.touches.length<2&&(L.value=!1),m()}c.onMounted(T),c.onUnmounted(Y);function T(){const e=f.value;e&&(e.addEventListener("mousedown",F),e.addEventListener("mousemove",S),e.addEventListener("mouseup",m),e.addEventListener("mouseleave",m),e.addEventListener("wheel",X,{passive:!1}),e.addEventListener("dblclick",Z),e.addEventListener("touchstart",q,{passive:!1}),e.addEventListener("touchmove",A,{passive:!1}),e.addEventListener("touchend",p),e.addEventListener("touchcancel",p))}function Y(){const e=f.value;e&&(e.removeEventListener("mousedown",F),e.removeEventListener("mousemove",S),e.removeEventListener("mouseup",m),e.removeEventListener("mouseleave",m),e.removeEventListener("wheel",X),e.removeEventListener("dblclick",Z),e.removeEventListener("touchstart",q),e.removeEventListener("touchmove",A),e.removeEventListener("touchend",p),e.removeEventListener("touchcancel",p))}return c.watchEffect(()=>(z.value?T():Y(),()=>{Y()})),{viewBox:o,resetZoom:G,isZoom:k}}exports.usePanZoom=O;