130 lines
4.7 KiB
JavaScript
130 lines
4.7 KiB
JavaScript
(function () {
|
|
function syncPublicNavigation() {
|
|
let token = "";
|
|
|
|
try {
|
|
token = window.localStorage.getItem("genealogy_auth_token") || "";
|
|
} catch (error) {
|
|
return;
|
|
}
|
|
if (!token) return;
|
|
|
|
document.querySelectorAll(".nav-actions").forEach((actions) => {
|
|
const loginLink = actions.querySelector('a[href="login.html"]');
|
|
const registerLink = actions.querySelector('a[href="register.html"]');
|
|
const createLink = actions.querySelector('a[href="create-genealogy.html"]');
|
|
|
|
if (loginLink) {
|
|
loginLink.href = "profile.html";
|
|
loginLink.textContent = "个人中心";
|
|
}
|
|
if (registerLink) {
|
|
registerLink.href = "profile-data.html";
|
|
registerLink.textContent = "账户资料";
|
|
}
|
|
if (createLink) createLink.href = "profile-create-family.html";
|
|
});
|
|
}
|
|
|
|
function initSiteMenu() {
|
|
const body = document.body;
|
|
const header = document.querySelector(".site-header");
|
|
const nav = header && header.querySelector(".nav");
|
|
const navLinks = nav && nav.querySelector(".nav-links");
|
|
const navActions = nav && nav.querySelector(".nav-actions");
|
|
|
|
if (!body || body.matches(".page-profile, .page-profile-module")) return;
|
|
if (!header || !nav || !navLinks || nav.querySelector("[data-site-menu-toggle]")) return;
|
|
|
|
const menuId = "site-mobile-menu";
|
|
const toggle = document.createElement("button");
|
|
const menu = document.createElement("div");
|
|
const inner = document.createElement("div");
|
|
|
|
toggle.className = "site-menu-toggle";
|
|
toggle.type = "button";
|
|
toggle.textContent = "菜单";
|
|
toggle.setAttribute("data-site-menu-toggle", "");
|
|
toggle.setAttribute("aria-expanded", "false");
|
|
toggle.setAttribute("aria-controls", menuId);
|
|
|
|
menu.className = "site-mobile-menu";
|
|
menu.id = menuId;
|
|
menu.hidden = true;
|
|
menu.setAttribute("data-site-mobile-menu", "");
|
|
menu.setAttribute("aria-hidden", "true");
|
|
|
|
inner.className = "container site-mobile-menu-inner";
|
|
[...navLinks.querySelectorAll("a"), ...(navActions ? navActions.querySelectorAll("a") : [])].forEach((link) => {
|
|
inner.appendChild(link.cloneNode(true));
|
|
});
|
|
menu.appendChild(inner);
|
|
nav.appendChild(toggle);
|
|
header.appendChild(menu);
|
|
body.classList.add("has-site-mobile-menu");
|
|
|
|
const setOpen = (isOpen) => {
|
|
menu.hidden = !isOpen;
|
|
menu.classList.toggle("is-open", isOpen);
|
|
menu.setAttribute("aria-hidden", isOpen ? "false" : "true");
|
|
toggle.setAttribute("aria-expanded", isOpen ? "true" : "false");
|
|
};
|
|
|
|
toggle.addEventListener("click", (event) => {
|
|
event.stopPropagation();
|
|
setOpen(toggle.getAttribute("aria-expanded") !== "true");
|
|
});
|
|
menu.addEventListener("click", (event) => {
|
|
if (event.target.closest("a")) setOpen(false);
|
|
event.stopPropagation();
|
|
});
|
|
document.addEventListener("click", () => setOpen(false));
|
|
document.addEventListener("keydown", (event) => {
|
|
if (event.key !== "Escape" || menu.hidden) return;
|
|
setOpen(false);
|
|
toggle.focus();
|
|
});
|
|
}
|
|
|
|
syncPublicNavigation();
|
|
initSiteMenu();
|
|
|
|
// 只在精确指针设备上启用微动效,触屏和减少动效偏好下保持静态。
|
|
const finePointer = window.matchMedia("(hover: hover) and (pointer: fine)").matches;
|
|
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
|
|
if (!finePointer || reduceMotion) return;
|
|
|
|
document.querySelectorAll(".tilt-card").forEach((card) => {
|
|
// 卡片倾斜角度通过 CSS 变量传递,具体视觉效果仍由 CSS 控制。
|
|
card.addEventListener("pointermove", (event) => {
|
|
const rect = card.getBoundingClientRect();
|
|
const px = (event.clientX - rect.left) / rect.width - 0.5;
|
|
const py = (event.clientY - rect.top) / rect.height - 0.5;
|
|
card.style.setProperty("--tilt-y", `${px * 5}deg`);
|
|
card.style.setProperty("--tilt-x", `${py * -5}deg`);
|
|
});
|
|
|
|
card.addEventListener("pointerleave", () => {
|
|
card.style.setProperty("--tilt-y", "0deg");
|
|
card.style.setProperty("--tilt-x", "0deg");
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll(".magnetic").forEach((item) => {
|
|
// 品牌 logo 不做磁吸,避免导航视觉跳动。
|
|
if (item.classList.contains("brand") || item.querySelector(".brand-logo")) return;
|
|
|
|
item.addEventListener("pointermove", (event) => {
|
|
const rect = item.getBoundingClientRect();
|
|
const x = event.clientX - rect.left - rect.width / 2;
|
|
const y = event.clientY - rect.top - rect.height / 2;
|
|
item.style.transform = `translate(${x * 0.08}px, ${y * 0.08}px)`;
|
|
});
|
|
|
|
item.addEventListener("pointerleave", () => {
|
|
item.style.transform = "";
|
|
});
|
|
});
|
|
})();
|