120 lines
3.9 KiB
JavaScript
120 lines
3.9 KiB
JavaScript
|
import { w as withInstall } from "../badge/index2.js";
|
||
|
import { defineComponent, ref, computed, onMounted, nextTick, onUnmounted, openBlock, createElementBlock, normalizeStyle, unref, renderSlot } from "vue";
|
||
|
var index = /* @__PURE__ */ (() => ".layui-affix{display:block;z-index:999;transition:all .3s ease-in-out}\n")();
|
||
|
const __default__ = {
|
||
|
name: "LayAffix"
|
||
|
};
|
||
|
const _sfc_main = defineComponent({
|
||
|
...__default__,
|
||
|
props: {
|
||
|
offset: { default: 0 },
|
||
|
target: { default: () => {
|
||
|
return document.body;
|
||
|
} },
|
||
|
position: { default: "top" }
|
||
|
},
|
||
|
emits: ["scroll"],
|
||
|
setup(__props, { emit }) {
|
||
|
const props = __props;
|
||
|
const outWindow = ref(false);
|
||
|
const dom = ref();
|
||
|
let changeScrollTop = 0;
|
||
|
let orginOffsetLeft = 0;
|
||
|
let marginLeft = 0;
|
||
|
let marginTop = 0;
|
||
|
let marginBottom = 0;
|
||
|
let fixedOffset = 0;
|
||
|
const getStyle = computed(() => {
|
||
|
if (outWindow.value && dom.value) {
|
||
|
let style = {
|
||
|
position: "fixed !important",
|
||
|
top: "unset",
|
||
|
bottom: "unset",
|
||
|
left: orginOffsetLeft - marginLeft + "px"
|
||
|
};
|
||
|
if (props.position === "top") {
|
||
|
style.top = fixedOffset - marginTop + "px";
|
||
|
} else {
|
||
|
style.bottom = fixedOffset - marginBottom + "px";
|
||
|
}
|
||
|
return style;
|
||
|
}
|
||
|
});
|
||
|
const checkInWindow = () => {
|
||
|
var _a;
|
||
|
if (dom.value) {
|
||
|
let offsetTop = dom.value.offsetTop;
|
||
|
let scrollTop = (_a = props.target) == null ? void 0 : _a.scrollTop;
|
||
|
if (props.position === "top") {
|
||
|
let result = offsetTop - scrollTop + props.target.offsetTop;
|
||
|
if (result < fixedOffset) {
|
||
|
if (outWindow.value) {
|
||
|
if (scrollTop <= changeScrollTop) {
|
||
|
outWindow.value = false;
|
||
|
}
|
||
|
} else {
|
||
|
changeScrollTop = scrollTop;
|
||
|
outWindow.value = true;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
let viewHeight = props.target.offsetHeight > window.innerHeight ? window.innerHeight : props.target.offsetHeight;
|
||
|
let result = viewHeight + scrollTop - offsetTop - dom.value.offsetHeight;
|
||
|
if (outWindow.value) {
|
||
|
if (scrollTop >= changeScrollTop) {
|
||
|
outWindow.value = false;
|
||
|
}
|
||
|
} else {
|
||
|
if (result < fixedOffset) {
|
||
|
changeScrollTop = scrollTop - result + props.offset;
|
||
|
outWindow.value = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
emit("scroll", {
|
||
|
targetScroll: scrollTop,
|
||
|
affixed: outWindow.value,
|
||
|
offset: !outWindow.value ? 0 : Math.abs(scrollTop - changeScrollTop)
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
const getDomStyle = (dom2, attr) => {
|
||
|
if (dom2.currentStyle) {
|
||
|
return dom2.currentStyle[attr];
|
||
|
} else {
|
||
|
return document.defaultView.getComputedStyle(dom2, null)[attr];
|
||
|
}
|
||
|
};
|
||
|
onMounted(() => {
|
||
|
nextTick(() => {
|
||
|
dom.value.offsetTop - props.target.offsetTop;
|
||
|
orginOffsetLeft = dom.value.getBoundingClientRect().left;
|
||
|
marginLeft = parseFloat(getDomStyle(dom.value, "marginLeft"));
|
||
|
marginTop = parseFloat(getDomStyle(dom.value, "marginTop"));
|
||
|
marginBottom = parseFloat(getDomStyle(dom.value, "marginBottom"));
|
||
|
fixedOffset = props.offset + props.target.offsetTop;
|
||
|
if (props.position === "bottom") {
|
||
|
fixedOffset = props.offset;
|
||
|
}
|
||
|
props.target.addEventListener("scroll", checkInWindow, true);
|
||
|
checkInWindow();
|
||
|
});
|
||
|
});
|
||
|
onUnmounted(() => {
|
||
|
props.target.removeEventListener("scroll", checkInWindow);
|
||
|
});
|
||
|
return (_ctx, _cache) => {
|
||
|
return openBlock(), createElementBlock("div", {
|
||
|
class: "layui-affix",
|
||
|
style: normalizeStyle(unref(getStyle)),
|
||
|
ref_key: "dom",
|
||
|
ref: dom
|
||
|
}, [
|
||
|
renderSlot(_ctx.$slots, "default")
|
||
|
], 4);
|
||
|
};
|
||
|
}
|
||
|
});
|
||
|
const component = withInstall(_sfc_main);
|
||
|
export { component as default };
|