import "./common.js"; //#region js/about-history.js function setActiveNav() { const pageNav = document.querySelector("[data-nav]")?.getAttribute("data-nav"); if (!pageNav) return; document.querySelectorAll(".site-header__nav a").forEach((link) => { const active = link.textContent.trim().startsWith(pageNav); link.classList.toggle("is-active", active); }); } function getHeaderOffset() { const header = document.querySelector(".site-header"); const h = header ? header.offsetHeight : 88; const isMobile = window.matchMedia("(max-width: 992px)").matches; if (isMobile) { const years = document.querySelector(".ah-nav__years"); const yearsH = years ? years.offsetHeight : 60; return h + yearsH + 12; } return h + 24; } function initHistorySpy() { const root = document.querySelector("[data-ah-spy]"); if (!root) return; const navItems = Array.from(root.querySelectorAll(".ah-nav__item[data-year]")); const blocks = Array.from(root.querySelectorAll(".ah-block[data-year]")); const yearsWrap = root.querySelector(".ah-nav__years"); const rail = root.querySelector(".ah-nav__rail"); const indicator = root.querySelector(".ah-nav__indicator"); if (!navItems.length || !blocks.length) return; let activeYear = navItems[0].dataset.year; let clicking = false; const syncRailHeight = () => { if (!yearsWrap || !rail) return; rail.style.height = `${yearsWrap.offsetHeight}px`; }; const updateLine = (item) => { if (!indicator || !item || !yearsWrap) return; syncRailHeight(); const itemRect = item.getBoundingClientRect(); const yearsRect = yearsWrap.getBoundingClientRect(); // 原点固定在顶部,线条延伸到当前高亮年份底部 const height = Math.max(itemRect.bottom - yearsRect.top, 8); indicator.style.height = `${height}px`; indicator.style.transform = ""; }; const updateLineSoon = (item) => { updateLine(item); requestAnimationFrame(() => updateLine(item)); window.setTimeout(() => updateLine(item), 320); }; const setActive = (year) => { if (!year || year === activeYear) { const current = navItems.find((el) => el.dataset.year === activeYear); updateLineSoon(current); return; } activeYear = year; navItems.forEach((el) => { el.classList.toggle("is-active", el.dataset.year === year); }); const current = navItems.find((el) => el.dataset.year === year); updateLineSoon(current); if (current && current.closest(".ah-nav__years") && window.matchMedia("(max-width: 992px)").matches) { current.scrollIntoView({ inline: "center", block: "nearest", behavior: "smooth" }); } }; const scrollToYear = (year) => { const target = blocks.find((el) => el.dataset.year === year); if (!target) return; clicking = true; setActive(year); const top = window.scrollY + target.getBoundingClientRect().top - getHeaderOffset(); const done = () => { clicking = false; }; if (window.lenis) { window.lenis.scrollTo(top, { duration: 1, onComplete: done }); } else { window.scrollTo({ top, behavior: "smooth" }); window.setTimeout(done, 800); } }; navItems.forEach((item) => { item.addEventListener("click", (event) => { event.preventDefault(); scrollToYear(item.dataset.year); }); }); const io = new IntersectionObserver((entries) => { if (clicking) return; const visible = entries.filter((e) => e.isIntersecting).sort((a, b) => b.intersectionRatio - a.intersectionRatio); if (!visible.length) return; const year = visible[0].target.getAttribute("data-year"); if (year) setActive(year); }, { root: null, rootMargin: `-${getHeaderOffset()}px 0px -45% 0px`, threshold: [0.05, 0.2, 0.4, 0.6] }); blocks.forEach((block) => io.observe(block)); const onScrollFallback = () => { if (clicking) return; const offset = getHeaderOffset() + 8; let current = blocks[0]?.dataset.year; for (const block of blocks) { if (block.getBoundingClientRect().top <= offset) current = block.dataset.year; } if (current) setActive(current); }; if (window.lenis) window.lenis.on("scroll", onScrollFallback); else window.addEventListener("scroll", onScrollFallback, { passive: true }); setActive(activeYear); window.addEventListener("resize", () => { const current = navItems.find((el) => el.dataset.year === activeYear); updateLineSoon(current); }); const hashYear = (location.hash || "").replace(/^#year-/, ""); if (hashYear && blocks.some((el) => el.dataset.year === hashYear)) { requestAnimationFrame(() => scrollToYear(hashYear)); } } setActiveNav(); initHistorySpy(); //#endregion