睿能科技
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

151 lines
4.5 KiB

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