layui-vue/es/backTop/index.js
2023-11-03 11:48:11 +08:00

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 };