vue-amazing-ui
Version:
An Amazing Vue3 UI Components Library, Using TypeScript.
150 lines (149 loc) • 4.72 kB
JavaScript
import { defineComponent as x, ref as r, computed as g, watch as G, onMounted as B, createElementBlock as $, openBlock as k, normalizeStyle as E, Fragment as H, renderList as M, createBlock as A, unref as N, mergeProps as O, withCtx as V, createElementVNode as b, normalizeClass as j } from "vue";
import q from "../spin/index.js";
import { useResizeObserver as D } from "../utils/index.js";
const J = ["href", "target"], K = ["src", "alt", "onLoad"], X = /* @__PURE__ */ x({
__name: "Waterfall",
props: {
images: { default: () => [] },
columnCount: { default: 3 },
columnGap: { default: 20 },
width: { default: "100%" },
borderRadius: { default: 8 },
backgroundColor: { default: "#F2F4F8" },
spinProps: { default: () => ({}) }
},
setup(o) {
const t = o, s = r(), h = r(0), C = r([]), c = r([]), v = r([]), i = r([]), p = r(0), W = g(() => typeof t.width == "number" ? `${t.width}px` : t.width), z = g(() => Math.max(...i.value) + t.columnGap), f = g(() => (h.value - (t.columnCount + 1) * t.columnGap) / t.columnCount), y = g(() => t.images.length);
G(
() => t.images,
(e, a) => {
(e.length !== e.length || e.some((n, l) => n.src !== a[l]?.src)) && (c.value = [], d());
},
{
deep: !0,
flush: "post"
}
), G(
() => [t.columnCount, t.columnGap, t.width],
() => {
d();
},
{
deep: !0,
flush: "post"
}
), B(() => {
d();
}), D(s, () => {
const e = s.value.offsetWidth;
t.images.length && e !== h.value && d();
});
function d() {
s.value && (h.value = s.value.offsetWidth, i.value = Array(t.columnCount).fill(0), v.value.splice(0), p.value++, I(p.value));
}
async function I(e) {
for (let a = 0; a < y.value; a++)
if (e === p.value)
c.value[a] ? w(a) : await P(t.images[a].src, a);
else
return !1;
}
function P(e, a) {
if (c.value[a])
w(a);
else
return new Promise((l, u) => {
const m = new Image();
m.src = e, m.onload = function() {
c.value[a] = {
// 保存已加载图片的尺寸信息
width: m.naturalWidth,
height: m.naturalHeight
}, w(a), l("loaded");
}, m.onerror = function(R) {
u(new Error(`Failed to load image at ${e}, err: ${R}`));
};
});
}
function w(e) {
const a = c.value[e], n = a.height / (a.width / f.value);
v.value[e] = {
width: f.value,
height: n,
...S(e, n)
};
}
function S(e, a) {
if (e < t.columnCount)
return i.value[e] = t.columnGap + a, {
top: t.columnGap,
left: (f.value + t.columnGap) * e + t.columnGap
};
{
const n = Math.min(...i.value);
let l = 0;
for (let u = 0; u < t.columnCount; u++)
if (i.value[u] === n) {
l = u;
break;
}
return i.value[l] = n + t.columnGap + a, {
top: n + t.columnGap,
left: (f.value + t.columnGap) * l + t.columnGap
};
}
}
function F(e) {
C.value[e] = !0;
}
function L(e) {
if (e) {
if (e.name)
return e.name;
{
const a = e.src.split("?")[0].split("/");
return a[a.length - 1];
}
}
return "";
}
return (e, a) => (k(), $("div", {
ref_key: "waterfallRef",
ref: s,
class: "waterfall-wrap",
style: E(`
--waterfall-border-radius: ${o.borderRadius}px;
--waterfall-bg-color: ${o.backgroundColor};
--waterfall-width: ${W.value};
--waterfall-height: ${z.value}px;
`)
}, [
(k(!0), $(H, null, M(v.value, (n, l) => (k(), A(N(q), O({
class: "waterfall-image",
style: `width: ${n.width}px; height: ${n.height}px; top: ${n && n.top}px; left: ${n && n.left}px;`,
spinning: !C.value[l],
size: "small",
indicator: "dynamic-circle"
}, { ref_for: !0 }, o.spinProps, { key: l }), {
default: V(() => [
b("a", {
class: j(["image-link", { "link-cursor": o.images[l].link }]),
href: o.images[l].link,
target: o.images[l].target ? o.images[l].target : "_blank"
}, [
b("img", {
class: "image-item",
src: o.images[l].src,
alt: L(o.images[l]),
onLoad: (u) => F(l)
}, null, 40, K)
], 10, J)
]),
_: 2
}, 1040, ["style", "spinning"]))), 128))
], 4));
}
});
export {
X as default
};