vue-data-ui
Version:
A user-empowering data visualization Vue 3 components library for eloquent data storytelling
133 lines (132 loc) • 5.51 kB
JavaScript
import { ref as h, computed as j, onMounted as J, onUnmounted as K, watchEffect as Q, watch as _ } from "vue";
function R(v, k = { x: 0, y: 0, width: 100, height: 100 }, z = 1, m, D = null) {
const o = h({ ...k }), n = h({ ...o.value }), i = h(1), E = h(!1), L = h(!1), S = h(0), T = h(null), P = h(1), x = h({ x: 0, y: 0 }), H = j(
() => n.value.x !== o.value.x || n.value.y !== o.value.y || n.value.width !== o.value.width || n.value.height !== o.value.height
);
let y = null;
function Z(e) {
if (e.length < 2) return 0;
const t = e[0].clientX - e[1].clientX, a = e[0].clientY - e[1].clientY;
return Math.hypot(t, a);
}
function Y(e) {
const t = v.value;
if (!t) return { x: 0, y: 0 };
const a = t.createSVGPoint();
a.x = e.clientX, a.y = e.clientY;
const l = t.getScreenCTM()?.inverse();
return l ? a.matrixTransform(l) : { x: 0, y: 0 };
}
function I(e, t) {
const a = v.value;
if (!a) return { dx: 0, dy: 0 };
const l = Math.max(1, a.clientWidth), u = Math.max(1, a.clientHeight), s = n.value.width / l, r = n.value.height / u;
return { dx: e * s, dy: t * r };
}
function F(e) {
E.value = !0;
const t = e.touches?.[0] || e;
x.value = { x: t.clientX, y: t.clientY }, v.value && (v.value.style.cursor = "grabbing");
}
function X(e) {
if (!E.value) return;
const t = e.touches?.[0] || e, a = t.clientX - x.value.x, l = t.clientY - x.value.y;
if (a === 0 && l === 0) return;
const { dx: u, dy: s } = I(a, l);
n.value.x -= u, n.value.y -= s, x.value = { x: t.clientX, y: t.clientY };
}
function f() {
E.value = !1, v.value && (v.value.style.cursor = "");
}
function b(e) {
D && D(), e.preventDefault();
const t = e.deltaY > 0 ? 0.9 : 1.1;
w(t, Y(e));
}
function A(e) {
e.preventDefault();
const t = Y(e), a = 1.5 * (1 + z / 100);
q(a, t);
}
function q(e, t) {
y && cancelAnimationFrame(y);
const a = i.value, l = a * e;
let u = null;
const s = 200, r = (d) => d < 0.5 ? 2 * d * d : -1 + (4 - 2 * d) * d, c = (d) => {
u == null && (u = d);
const V = Math.min((d - u) / s, 1), U = (a + (l - a) * r(V)) / i.value;
w(U, t), V < 1 ? y = requestAnimationFrame(c) : y = null;
};
requestAnimationFrame(c);
}
function w(e, t) {
const a = i.value * e, l = a / i.value, u = n.value.width / l, s = n.value.height / l, r = (t.x - n.value.x) * (1 - 1 / l), c = (t.y - n.value.y) * (1 - 1 / l);
n.value.x += r, n.value.y += c, n.value.width = u, n.value.height = s, i.value = a;
}
function B(e) {
e.touches.length === 2 ? (L.value = !0, S.value = Z(e.touches), T.value = { ...n.value }, P.value = i.value) : (e.preventDefault(), F(e));
}
function C(e) {
if (L.value && e.touches.length === 2) {
e.preventDefault();
const t = Z(e.touches);
if (!S.value || !t) return;
const a = t / S.value, u = P.value * a / i.value, s = (e.touches[0].clientX + e.touches[1].clientX) / 2, r = (e.touches[0].clientY + e.touches[1].clientY) / 2, c = Y({ clientX: s, clientY: r });
n.value = { ...T.value }, i.value = P.value, w(u, c);
} else
e.preventDefault(), X(e);
}
function p(e) {
e.touches.length < 2 && (L.value = !1), f();
}
function W(e = !1) {
if (!e) {
n.value = { ...o.value }, i.value = 1;
return;
}
const t = { ...n.value }, a = i.value, l = 300;
let u = null;
const s = (r) => {
u == null && (u = r);
const c = Math.min((r - u) / l, 1);
n.value = {
x: t.x + (o.value.x - t.x) * c,
y: t.y + (o.value.y - t.y) * c,
width: t.width + (o.value.width - t.width) * c,
height: t.height + (o.value.height - t.height) * c
}, i.value = a + (1 - a) * c, c < 1 && requestAnimationFrame(s);
};
requestAnimationFrame(s);
}
function G(e, t = {}) {
const { overwriteCurrentIfNotZoomed: a = !0 } = t, l = n.value.x !== o.value.x || n.value.y !== o.value.y || n.value.width !== o.value.width || n.value.height !== o.value.height;
o.value = { ...e }, !l && a && (n.value = { ...o.value }, i.value = 1);
}
function M() {
const e = v.value;
e && (e.addEventListener("mousedown", F), e.addEventListener("mousemove", X), e.addEventListener("mouseup", f), e.addEventListener("mouseleave", f), e.addEventListener("wheel", b, { passive: !1 }), e.addEventListener("dblclick", A), e.addEventListener("touchstart", B, { passive: !1 }), e.addEventListener("touchmove", C, { passive: !1 }), e.addEventListener("touchend", p), e.addEventListener("touchcancel", p));
}
function g() {
const e = v.value;
e && (e.removeEventListener("mousedown", F), e.removeEventListener("mousemove", X), e.removeEventListener("mouseup", f), e.removeEventListener("mouseleave", f), e.removeEventListener("wheel", b), e.removeEventListener("dblclick", A), e.removeEventListener("touchstart", B), e.removeEventListener("touchmove", C), e.removeEventListener("touchend", p), e.removeEventListener("touchcancel", p));
}
J(() => {
(!m || m.value) && M();
}), K(g), Q(() => {
if (m)
return m.value ? M() : g(), () => g();
}), _(v, () => {
g(), (!m || m.value) && M();
});
function N(e, t = !1) {
const a = {
x: n.value.x + n.value.width / 2,
y: n.value.y + n.value.height / 2
};
t ? q(e, a) : w(e, a);
}
return { viewBox: n, resetZoom: W, isZoom: H, setInitialViewBox: G, scale: i, zoomByFactor: N };
}
export {
R as u
};