import Headroom from "headroom.js";
export default function useHeaderRoom(selector: HTMLElement, options?: any) {
const defaultOptions = {
offset: 30, // 在元素没有固定之前,垂直方向的偏移量(以 px 为单位)
tolerance: { up: 10, down: 0 }, // 容忍度 scroll tolerance in px before state changes
scroller: window,
classes: {
initial: "animated", // 当元素初始化后所设置的 class
pinned: "slideUp", // 向上滚动时设置的 class
unpinned: "slideDown", // 向下滚动时所设置的 class
// when above offset
top: "headroom--top",
// when below offset
notTop: "headroom--not-top",
// when at bottom of scroll area
bottom: "headroom--bottom",
// when not at bottom of scroll area
notBottom: "headroom--not-bottom",
// when frozen method has been called
frozen: "headroom--frozen"
// multiple classes are also supported with a space-separated list
// pinned: "headroom--pinned foo bar"
},
onPin: function () {
// console.log("onPin", this);
},
onUnpin: function () {
// console.log("onUnpin");
},
onTop: function () {
// console.log("onTop");
},
onNotTop: function () {
// console.log("onNotTop");
},
onBottom: function () {
// console.log("onBottom");
},
onNotBottom: function () {
// console.log("onNotBottom");
},
onUp: function () {
// console.log("onUp");
},
onDown: function () {
// console.log("onDown");
}
};
new Headroom(selector, {
...defaultOptions,
...options
}).init();
}
<template>
<div class="w-full relative">
<nuxt-loading-indicator color="red" :duration="2000">
<div class="custom-loading-text">加载中...</div>
</nuxt-loading-indicator>
<nav-bar id="container-header" />
<nuxt-page />
<footer-bar />
<nav-search id="nav-search" />
<a-back-top>
<a-button shape="circle" type="primary" size="large">
<icon-to-top :size="28" />
</a-button>
</a-back-top>
</div>
</template>
<script setup lang="ts">
// 防抖
onMounted(async () => {
await nextTick();
useDeviceType();
const throttledUseDeviceType = debounce(useDeviceType, 200);
window.onresize = throttledUseDeviceType;
useHeaderRoom(document.querySelector("#container-header")!);
useHeaderRoom(document.querySelector("#nav-search")!, {
offset: 30,
tolerance: { up: 10, down: 0 },
classes: {
initial: "search-animated", // 当元素初始化后所设置的 class
pinned: "slideUp", // 向上滚动时设置的 class
unpinned: "slideDown" // 向下滚动时所设置的 class
}
});
});
// 组件卸载时清除事件监听器
onUnmounted(() => {
window.onresize = null; // 或者使用 removeEventListener,但在这里直接设为 null 就足够了
});
</script>
<style lang="less">
.search-animated {
will-change: transform;
position: fixed;
top: 4.4rem;
left: 0;
right: 0;
transition: all 0.2s ease-in-out;
}
.search-animated.slideDown {
top: -6.5rem;
}
.search-animated.slideUp {
top: 4.4rem;
}
.custom-loading-text {
color: #fff;
font-size: 18px;
text-align: center;
margin-top: 50px;
}
</style>
css
// header 导航栏样式
.animated {
will-change: transform;
position: fixed;
top: 0;
left: 0;
right: 0;
transition: all 0.2s ease-in-out;
}
.animated.slideDown {
top: -6.25rem;
}
.animated.slideUp {
top: 0;
}
.animated.headroom--top {
@apply !bg-black;
.app-link {
color: white !important;
}
.app-menu {
color: white !important;
}
}
.animated.headroom--not-top {
.app-link {
@apply !text-black;
}
}