179 lines
6.4 KiB
JavaScript
179 lines
6.4 KiB
JavaScript
import { w as withInstall } from "../badge/index2.js";
|
|
import { defineComponent, ref, shallowRef, computed, onMounted, onBeforeUnmount, withDirectives, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, withModifiers, renderSlot, createVNode, vShow } from "vue";
|
|
import { _ as _sfc_main$2W } from "../_chunks/@layui/index.js";
|
|
var index = /* @__PURE__ */ (() => ".layui-backtop{position:fixed;right:30px;bottom:40px;width:50px;height:50px;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:40px;background-color:#9f9f9f;color:#fff;border-radius:var(--global-border-radius);opacity:.95;z-index:999999}.layui-backtop :hover{opacity:.85}.layui-backtop-medium{width:40px;height:40px;font-size:30px}.layui-backtop-small{width:30px;height:30px;font-size:20px}\n")();
|
|
const _hoisted_1 = ["onClick"];
|
|
const __default__ = {
|
|
name: "LayBacktop"
|
|
};
|
|
const _sfc_main = defineComponent({
|
|
...__default__,
|
|
props: {
|
|
target: { default: "window" },
|
|
showHeight: { default: 200 },
|
|
disabled: { type: Boolean, default: false },
|
|
position: null,
|
|
right: null,
|
|
bottom: null,
|
|
size: null,
|
|
bgcolor: null,
|
|
opacity: null,
|
|
color: null,
|
|
borderRadius: null,
|
|
circle: { type: Boolean, default: false },
|
|
icon: { default: "layui-icon-top" },
|
|
iconSize: { default: 30 },
|
|
iconColor: null
|
|
},
|
|
emits: ["click"],
|
|
setup(__props, { emit }) {
|
|
const props = __props;
|
|
const backtopRef = ref(null);
|
|
const scrollTarget = shallowRef(void 0);
|
|
let visible = ref(props.showHeight === 0);
|
|
const classBacktop = computed(() => {
|
|
return {
|
|
"layui-backtop-medium": props.size === "medium",
|
|
"layui-backtop-small": props.size === "small"
|
|
};
|
|
});
|
|
const borderRadius = computed(() => {
|
|
if (props.circle) {
|
|
return "50%";
|
|
}
|
|
return typeof props.borderRadius === "number" ? `${props.borderRadius}px` : props.borderRadius;
|
|
});
|
|
const styleBacktop = computed(() => {
|
|
return {
|
|
position: props.position,
|
|
right: `${props.right}px`,
|
|
bottom: `${props.bottom}px`,
|
|
backgroundColor: props.bgcolor,
|
|
opacity: props.opacity,
|
|
color: props.color,
|
|
borderRadius: borderRadius.value
|
|
};
|
|
});
|
|
const easeInOut = (value) => {
|
|
return value < 0.5 ? 2 * value * value : 1 - 2 * (value - 1) * (value - 1);
|
|
};
|
|
const scrollToTop = () => {
|
|
if (!scrollTarget.value)
|
|
return;
|
|
if (scrollTarget.value instanceof Window) {
|
|
window.scrollTo({ top: 0, left: 0, behavior: "smooth" });
|
|
} else {
|
|
const previous = Date.now();
|
|
const scrollHeight = scrollTarget.value.scrollTop;
|
|
const animationFunc = () => {
|
|
if (!scrollTarget.value || scrollTarget.value instanceof Window)
|
|
return;
|
|
const elapsed = (Date.now() - previous) / 450;
|
|
if (elapsed < 1) {
|
|
scrollTarget.value.scrollTop = scrollHeight * (1 - easeInOut(elapsed));
|
|
window.requestAnimationFrame(animationFunc);
|
|
} else {
|
|
scrollTarget.value.scrollTop = 0;
|
|
}
|
|
};
|
|
window.requestAnimationFrame(animationFunc);
|
|
}
|
|
};
|
|
const handleScroll = () => {
|
|
if (!scrollTarget.value)
|
|
return;
|
|
const scrollTop = scrollTarget.value instanceof Window ? window.pageYOffset : scrollTarget.value.scrollTop;
|
|
visible.value = scrollTop >= props.showHeight;
|
|
};
|
|
const handleClick = (event) => {
|
|
if (!props.disabled) {
|
|
scrollToTop();
|
|
}
|
|
emit("click", event);
|
|
};
|
|
const handlerMousedown = () => {
|
|
backtopRef.value.style.opacity = "1";
|
|
};
|
|
const handlerMouseup = () => {
|
|
backtopRef.value.style.opacity = "0.95";
|
|
};
|
|
const getScrollTarget = () => {
|
|
if (props.target === "window") {
|
|
return getScrollParent(backtopRef.value, false);
|
|
} else {
|
|
const targetElement = document.querySelector(props.target);
|
|
if (!targetElement) {
|
|
throw new Error(`target is not existed: ${props.target}`);
|
|
}
|
|
if (props.position === "absolute") {
|
|
if (!targetElement.parentElement) {
|
|
throw new Error(`target parent element is not existed: ${props.target}`);
|
|
}
|
|
targetElement.parentElement.style.position = "relative";
|
|
}
|
|
return targetElement;
|
|
}
|
|
};
|
|
const getScrollParent = (element, includeHidden) => {
|
|
let style = getComputedStyle(element);
|
|
let excludeStaticParent = style.position === "absolute";
|
|
let overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
|
|
for (let parent = element; parent = parent.parentElement; ) {
|
|
style = getComputedStyle(parent);
|
|
if (excludeStaticParent && style.position === "static") {
|
|
continue;
|
|
}
|
|
if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
|
|
return parent;
|
|
}
|
|
}
|
|
return window;
|
|
};
|
|
const throttle = (func, wait) => {
|
|
var timer = null;
|
|
return (...args) => {
|
|
if (!timer) {
|
|
timer = setTimeout(() => {
|
|
timer = null;
|
|
func.apply(this, args);
|
|
}, wait);
|
|
}
|
|
};
|
|
};
|
|
const callback = throttle(handleScroll, 300);
|
|
onMounted(() => {
|
|
if (!props.target)
|
|
return;
|
|
scrollTarget.value = getScrollTarget();
|
|
scrollTarget.value.addEventListener("scroll", callback);
|
|
});
|
|
onBeforeUnmount(() => {
|
|
var _a;
|
|
(_a = scrollTarget.value) == null ? void 0 : _a.removeEventListener("scroll", callback);
|
|
});
|
|
return (_ctx, _cache) => {
|
|
return withDirectives((openBlock(), createElementBlock("div", {
|
|
ref_key: "backtopRef",
|
|
ref: backtopRef,
|
|
class: normalizeClass(["layui-backtop", unref(classBacktop)]),
|
|
style: normalizeStyle({ ...unref(styleBacktop) }),
|
|
onClick: withModifiers(handleClick, ["stop"]),
|
|
onMousedown: handlerMousedown,
|
|
onMouseup: handlerMouseup
|
|
}, [
|
|
renderSlot(_ctx.$slots, "default", {}, () => [
|
|
createVNode(unref(_sfc_main$2W), {
|
|
type: props.icon,
|
|
size: `${props.iconSize}px`,
|
|
color: props.iconColor
|
|
}, null, 8, ["type", "size", "color"])
|
|
])
|
|
], 46, _hoisted_1)), [
|
|
[vShow, unref(visible)]
|
|
]);
|
|
};
|
|
}
|
|
});
|
|
const component = withInstall(_sfc_main);
|
|
export { component as default };
|