Files
AboutMe/src/components/navbar.astro
2026-02-02 22:47:52 +03:00

171 lines
6.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
import { Icon } from "astro-icon/components";
import { navbarConfig, siteConfig } from "@/config";
import { LinkPresets } from "@constants/link-presets";
import { LinkPreset, type NavbarLink } from "@/types/config";
import { url } from "@utils/url";
import { getNavbarTransparentModeForWallpaperMode, getDefaultWallpaperMode } from "@utils/wallpaper";
import NavLinks from "@components/navbar/navLinks.astro";
import NavMenu from "@components/navbar/navMenu.svelte";
import Search from "@components/navbar/search.svelte";
import Translator from "@components/navbar/translator.svelte";
import DisplaySettings from "@components/navbar/displaySettings.svelte";
import LightDarkSwitch from "@components/navbar/lightDarkSwitch.svelte";
import WallpaperSwitch from "@components/navbar/wallpaperSwitch.svelte";
const className = Astro.props.class;
// 获取导航栏透明模式配置 - 根据当前壁纸模式读取正确的配置
const navbarTransparentMode = getNavbarTransparentModeForWallpaperMode(getDefaultWallpaperMode());
// 检查是否为首页
const isHomePage = Astro.url.pathname === "/" || Astro.url.pathname === "";
let links: NavbarLink[] = navbarConfig.links.map(
(item: NavbarLink | LinkPreset): NavbarLink => {
if (typeof item === "number") {
return LinkPresets[item];
}
return item;
},
);
---
<div id="navbar" class="z-50 onload-animation-down px-3 sm:px-6 md:px-0" data-transparent-mode={navbarTransparentMode} data-is-home={isHomePage}>
<div class="absolute h-8 left-0 right-0 -top-8 bg-(--card-bg) transition"></div> <!-- used for onload animation -->
<div class:list={[
className,
"overflow-visible! max-w-(--page-width) h-18 mx-auto flex items-center justify-between md:px-4"]}>
<a href={url('/')} class="btn-plain scale-animation rounded-lg h-13 px-5 font-bold active:scale-95">
<div class="flex flex-row text-(--primary) items-center text-md">
<Icon name="material-symbols:home-pin-outline" class="text-[1.75rem] mb-1 mr-2" />
{siteConfig.title}
</div>
</a>
<div class="hidden md:flex items-center navbar-nav-links">
{links.map((l) => {
return <NavLinks link={l} />;
})}
</div>
<div class="flex items-center navbar-buttons" id="navbar-buttons">
<Search client:load></Search>
<Translator client:load></Translator>
<DisplaySettings client:load></DisplaySettings>
<LightDarkSwitch client:load></LightDarkSwitch>
<WallpaperSwitch client:load></WallpaperSwitch>
<NavMenu client:load links={links}></NavMenu>
</div>
</div>
</div>
<script>
// 为semifull模式添加滚动检测逻辑
function initSemifullScrollDetection() {
const navbar = document.getElementById('navbar');
if (!navbar) return;
const transparentMode = navbar.getAttribute('data-transparent-mode');
if (transparentMode !== 'semifull') return;
const isHomePage = navbar.getAttribute('data-is-home') === 'true';
// 如果不是首页,移除滚动事件监听器并设置为半透明状态
if (!isHomePage) {
// 移除之前的滚动事件监听器(如果存在)
if (window.semifullScrollHandler) {
window.removeEventListener('scroll', window.semifullScrollHandler);
window.semifullScrollHandler = null;
}
// 设置为半透明状态
navbar.classList.add('scrolled');
return;
}
// 移除现有的scrolled类重置状态
navbar.classList.remove('scrolled');
let ticking = false;
function updateNavbarState() {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
const threshold = 50; // 滚动阈值,可以根据需要调整
if (scrollTop > threshold) {
navbar?.classList.add('scrolled');
} else {
navbar?.classList.remove('scrolled');
}
ticking = false;
}
function requestTick() {
if (!ticking) {
requestAnimationFrame(updateNavbarState);
ticking = true;
}
}
// 移除之前的滚动事件监听器(如果存在)
if (window.semifullScrollHandler) {
window.removeEventListener('scroll', window.semifullScrollHandler);
}
// 保存新的事件处理器引用
window.semifullScrollHandler = requestTick;
// 监听滚动事件
window.addEventListener('scroll', requestTick, { passive: true });
// 初始化状态
updateNavbarState();
}
// 将函数暴露到全局对象,供页面切换时调用
window.initSemifullScrollDetection = initSemifullScrollDetection;
// 页面加载完成后初始化滚动检测
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initSemifullScrollDetection);
} else {
initSemifullScrollDetection();
}
</script>
{import.meta.env.PROD && <script is:inline define:vars={{scriptUrl: url('/pagefind/pagefind.js')}}>
async function loadPagefind() {
try {
const response = await fetch(scriptUrl, { method: 'HEAD' });
if (!response.ok) {
throw new Error(`Pagefind script not found: ${response.status}`);
}
const pagefind = await import(scriptUrl);
await pagefind.options({
excerptLength: 20
});
window.pagefind = pagefind;
document.dispatchEvent(new CustomEvent('pagefindready'));
console.log('Pagefind loaded and initialized successfully, event dispatched.');
} catch (error) {
console.error('Failed to load Pagefind:', error);
window.pagefind = {
search: () => Promise.resolve({ results: [] }),
options: () => Promise.resolve(),
};
document.dispatchEvent(new CustomEvent('pagefindloaderror'));
console.log('Pagefind load error, event dispatched.');
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', loadPagefind);
} else {
loadPagefind();
}
</script>}