vuux
Version:
Vue3 Nuxt3 Nuxt4 组件库
104 lines (103 loc) • 3.66 kB
JavaScript
import { reactive as P, ref as m, computed as H, watch as R, onMounted as U, onUnmounted as q, nextTick as T } from "vue";
import { Utils as W } from "@vuux/utils";
const O = (h, x) => {
const t = P({
//目标元素x
x: 0,
//目标元素y
y: 0,
//目标元素宽
w: 0,
//目标元素高
h: 0,
//高亮圆角
border: 4,
//是否显示SVG高亮
isShowSvg: !1,
//当前步骤
currentStep: 0,
//是否在上方显示
isTop: !1,
//是否在下方显示
isBottom: !1
}), p = m({
top: "",
left: ""
}), s = m(null), g = m(null), S = H(() => h.data.length), f = m([]), V = H(() => {
const { x: n, y: o, w: r, h: a, border: e } = t, { width: c, height: l } = W.windowSize(), i = Math.max(r - 2 * e, 0), d = Math.max(a - 2 * e, 0);
return `
M${c},0 L0,0 L0,${l} L${c},${l} L${c},0 Z
M${n},${o + e}
a${e},${e} 0 0 1 ${e},-${e}
h${i}
a${e},${e} 0 0 1 ${e},${e}
v${d}
a${e},${e} 0 0 1 -${e},${e}
h-${i}
a${e},${e} 0 0 1 -${e},-${e}
v-${d} z
`;
}), B = (n) => {
const o = n.getBoundingClientRect();
return {
w: Math.round(o.width) + 12,
h: Math.round(o.height) + 12,
x: Math.round(o.left) - 6,
y: Math.round(o.top) - 6
};
}, k = (n, o = 30) => {
const r = n.getBoundingClientRect(), a = window.innerHeight;
return r.top < o ? (window.scrollBy({ top: r.top - o, behavior: "smooth" }), !0) : r.bottom > a - o ? (window.scrollBy({ top: r.bottom - a + o, behavior: "smooth" }), !0) : !1;
}, v = async (n) => {
const o = f.value[n];
if (!o)
return;
await T();
const r = B(o);
if (t.x = r.x, t.y = r.y, t.w = r.w, t.h = r.h, t.isShowSvg = !0, !s.value)
return;
const a = s.value;
a.style.bottom = "auto", k(o, 30), await T();
const e = window.innerHeight, c = window.innerWidth, l = B(o), i = a.offsetWidth, d = a.offsetHeight;
let w = l.y + l.h + 12, b = !1, L = !0;
w + d + 30 > e && (w = l.y - d - 12, b = !0, L = !1), w = Math.max(w, 30);
let u = l.x + l.w / 2 - i / 2;
if (u < 10 && (u = 10), u + i + 10 > c && (u = c - i - 10), a.style.top = `${w}px`, a.style.left = `${u}px`, g.value) {
let y = l.x + l.w / 2 - u - 6;
y = Math.max(6, Math.min(y, i - 6)), g.value.style.left = `${y}px`;
}
t.x = l.x, t.y = l.y, t.w = l.w, t.h = l.h, n === 0 && (p.value.top = `${w}px`, p.value.left = `${u}px`), t.isTop = b, t.isBottom = L;
}, $ = () => {
!h.modelValue || !f.value.length || !s.value || !f.value[t.currentStep] || v(t.currentStep);
}, M = () => {
f.value = h.data.map((n) => document.querySelector(`.${n.class}`)).filter(Boolean), f.value.length > 0 ? v(0) : t.isShowSvg = !1;
}, E = async (n) => {
t.currentStep = 0, x("update:modelValue", !1), n === "close" && x("close"), n === "ok" && x("ok"), await W.wait(500), s.value && (s.value.style.top = p.value.top, s.value.style.left = p.value.left);
}, z = () => {
t.currentStep === S.value - 1 ? E("ok") : (t.currentStep++, v(t.currentStep));
}, C = () => {
t.currentStep = Math.max(0, t.currentStep - 1), v(t.currentStep);
};
return R(
() => h.modelValue,
(n) => {
n && M();
}
), U(() => {
h.modelValue && M(), window.addEventListener("resize", $), window.addEventListener("scroll", $, { passive: !0 });
}), q(() => {
window.removeEventListener("resize", $), window.removeEventListener("scroll", $);
}), {
state: t,
stepEl: s,
arrowEl: g,
stepCount: S,
computedPath: V,
handleClose: E,
handleNext: z,
handlePrev: C
};
};
export {
O as useTour
};