107 lines
3.9 KiB
JavaScript
107 lines
3.9 KiB
JavaScript
// Page transition functionality
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
// Top/Bottom curtain transition system
|
|
const curtainTop =
|
|
document.getElementById("pageCurtainTop") ||
|
|
(() => {
|
|
const div = document.createElement("div");
|
|
div.id = "pageCurtainTop";
|
|
div.className =
|
|
"fixed inset-x-0 top-0 h-1/2 z-50 transform -translate-y-full transition-transform duration-600 ease-in-out";
|
|
div.style.background = "linear-gradient(0deg, #b03037, #8a252a)";
|
|
document.body.appendChild(div);
|
|
return div;
|
|
})();
|
|
|
|
const curtainBottom =
|
|
document.getElementById("pageCurtainBottom") ||
|
|
(() => {
|
|
const div = document.createElement("div");
|
|
div.id = "pageCurtainBottom";
|
|
div.className =
|
|
"fixed inset-x-0 bottom-0 h-1/2 z-50 transform translate-y-full transition-transform duration-600 ease-in-out";
|
|
div.style.background = "linear-gradient(180deg, #b03037, #8a252a)";
|
|
document.body.appendChild(div);
|
|
return div;
|
|
})();
|
|
|
|
// Add entrance animation class
|
|
document.body.style.animation = "pageEnter 0.6s ease-out";
|
|
|
|
document.querySelectorAll("a[data-trans]").forEach((a) => {
|
|
a.addEventListener("click", (e) => {
|
|
const href = a.getAttribute("href");
|
|
if (!href || href.startsWith("#")) return;
|
|
e.preventDefault();
|
|
|
|
// Collect elements that had delayed entrance and fade them out in reverse order
|
|
const animatedEls = Array.from(
|
|
document.querySelectorAll('[style*="animation-delay"]')
|
|
).map((el) => {
|
|
const m = (el.getAttribute("style") || "").match(
|
|
/animation-delay:\s*([0-9.]+)s/
|
|
);
|
|
const delay = m ? parseFloat(m[1]) : 0;
|
|
return { el, delay };
|
|
});
|
|
|
|
const sorted = animatedEls
|
|
.sort((a, b) => b.delay - a.delay)
|
|
.map((item, idx) => ({ ...item, order: idx }));
|
|
|
|
sorted.forEach((item) => {
|
|
setTimeout(() => {
|
|
item.el.style.animation = "staggerFadeOut 260ms ease-out forwards";
|
|
}, item.order * 50);
|
|
});
|
|
|
|
const totalStaggerTime = (sorted.length - 1) * 50 + 260 + 130;
|
|
|
|
setTimeout(() => {
|
|
// Crossfade + tiny zoom of the whole page (longer)
|
|
document.body.style.animation = "pageExit 900ms ease forwards";
|
|
setTimeout(() => {
|
|
location.href = href;
|
|
}, 920);
|
|
}, totalStaggerTime);
|
|
});
|
|
});
|
|
|
|
// Hide curtains and close nav just before page is cached (prevents blank back step)
|
|
window.addEventListener("pagehide", () => {
|
|
if (curtainTop) curtainTop.style.transform = "translateY(-100%)";
|
|
if (curtainBottom) curtainBottom.style.transform = "translateY(100%)";
|
|
const navEl = document.getElementById("navMenu");
|
|
const gridEl = document.getElementById("menuGrid");
|
|
if (navEl) navEl.classList.add("hidden");
|
|
const wrapEl = document.getElementById("menuWrap");
|
|
if (wrapEl) wrapEl.classList.remove("open");
|
|
});
|
|
|
|
// Handle back/forward navigation
|
|
window.addEventListener("pageshow", function (event) {
|
|
if (event.persisted) {
|
|
// Page was loaded from cache (back/forward)
|
|
window.location.reload();
|
|
}
|
|
});
|
|
|
|
// Ensure back/forward navigation (bfcache) shows a clean page
|
|
window.addEventListener("pageshow", () => {
|
|
const loadingScreen = document.getElementById("loadingScreen");
|
|
if (loadingScreen) {
|
|
loadingScreen.style.display = "none";
|
|
loadingScreen.style.opacity = "0";
|
|
}
|
|
const ct = document.getElementById("pageCurtainTop");
|
|
const cb = document.getElementById("pageCurtainBottom");
|
|
if (ct) ct.style.transform = "translateY(-100%)";
|
|
if (cb) cb.style.transform = "translateY(100%)";
|
|
|
|
// Close nav if it was left open and reset grid icon
|
|
const navMenuEl = document.getElementById("navMenu");
|
|
const wrapEl2 = document.getElementById("menuWrap");
|
|
if (navMenuEl) navMenuEl.classList.add("hidden");
|
|
if (wrapEl2) wrapEl2.classList.remove("open");
|
|
});
|
|
});
|