mirror of
https://github.com/StepanovPlaton/AboutMe.git
synced 2026-04-04 04:40:51 +04:00
Initial commit
This commit is contained in:
171
src/components/navbar.astro
Normal file
171
src/components/navbar.astro
Normal file
@@ -0,0 +1,171 @@
|
||||
---
|
||||
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>}
|
||||
Reference in New Issue
Block a user