Skip to content

Commit

Permalink
Page transition tidying
Browse files Browse the repository at this point in the history
  • Loading branch information
Gyanreyer committed May 15, 2023
1 parent 32b4e33 commit 651f4b0
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 58 deletions.
6 changes: 1 addition & 5 deletions src/_components/home/homepage-section.webc
Expand Up @@ -176,7 +176,7 @@
}

:host-context(main[data-transition="enter-start"]) .section-content > aside {
--translate-y: calc(var(var(--translate-y)) + 1.5rem);
--translate-y: 1rem;
}

:host-context(main[data-transition="entering"]) .section-content > * {
Expand All @@ -194,10 +194,6 @@
transform: translate3d(0, 0, 0);
}

:host-context(main[data-transition="entering"]) .section-content > aside {
--translate-y: var(--translate-y);
}

:host-context(main[data-transition="entering"]):first-of-type header {
transition-delay: 0s;
}
Expand Down
8 changes: 8 additions & 0 deletions src/_components/shared/scroll-to-top.webc
Expand Up @@ -70,5 +70,13 @@
});

navObserver.observe(document.querySelector("nav"));

document.addEventListener(
"transition:pageclosed",
() => {
navObserver.disconnect();
},
{ once: true }
);
}
</script>
8 changes: 4 additions & 4 deletions src/_includes/layouts/base.webc
Expand Up @@ -21,7 +21,7 @@
<!-- Critical CSS -->
<style
@raw="getBundle('css', 'critical')"
data-pg-trns-id="css-crit"
pgtrns:id="css-crit"
webc:keep
></style>
<link rel="stylesheet" href="../../css/reset.css" webc:bucket="critical" />
Expand All @@ -30,13 +30,13 @@
<link
rel="stylesheet"
:href="getBundleFileUrl('css', 'transition-persist')"
data-pg-trns-id="css-trns-persist"
pgtrns:id="css-trns-persist"
webc:keep
/>
<script
:src="getBundleFileUrl('js', 'transition-persist')"
type="module"
data-pg-trns-id="js-trns-persist"
pgtrns:id="js-trns-persist"
webc:keep
></script>

Expand All @@ -62,6 +62,6 @@
<body>
<template @raw="content" webc:nokeep></template>
<!-- Element which is animated for page transitions -->
<div data-pg-trns-id="trns-anim-element"></div>
<div pgtrns:id="trns-anim-element"></div>
</body>
</html>
22 changes: 9 additions & 13 deletions src/_includes/layouts/work.webc
Expand Up @@ -13,22 +13,18 @@ theme: "light"
<scroll-to-top></scroll-to-top>

<!-- Shoelace -->
<script
type="module"
src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.4.0/dist/translations/en.js"
data-pg-trns-id="sl-en"
webc:keep
></script>
<script
type="module"
src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.4.0/dist/shoelace-autoloader.js"
data-pg-trns-id="sl-loader"
webc:keep
></script>
<script type="module" pgtrns:id="sl-components" webc:keep>
await import(
"https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.4.0/dist/translations/en.js"
);
import(
"https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.4.0/dist/components/carousel/carousel.js"
);
</script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.4.0/dist/themes/light.css"
data-pg-trns-id="sl-theme"
pgtrns:id="sl-theme"
webc:keep
/>

Expand Down
16 changes: 8 additions & 8 deletions src/css/page-transition.css
@@ -1,4 +1,4 @@
[data-pg-trns-id="trns-anim-element"] {
[pgtrns\:id="trns-anim-element"] {
position: fixed;
top: 0;
left: 0;
Expand All @@ -13,8 +13,8 @@
--angled-segment-height: calc(100vw * tan(var(--angle)));
}

[data-pg-trns-id="trns-anim-element"]::before,
[data-pg-trns-id="trns-anim-element"]::after {
[pgtrns\:id="trns-anim-element"]::before,
[pgtrns\:id="trns-anim-element"]::after {
content: "";
position: absolute;
left: 0;
Expand All @@ -24,25 +24,25 @@
transform: rotate(calc(-1 * var(--angle)));
}

[data-pg-trns-id="trns-anim-element"]::before {
[pgtrns\:id="trns-anim-element"]::before {
bottom: 100%;
transform-origin: top right;
}

[data-pg-trns-id="trns-anim-element"]::after {
[pgtrns\:id="trns-anim-element"]::after {
top: 100%;
transform-origin: bottom left;
}

[data-pg-trns-state] [data-pg-trns-id="trns-anim-element"] {
[pgtrns\:state] [pgtrns\:id="trns-anim-element"] {
visibility: visible;
transition: transform 0.6s;
}

[data-pg-trns-state="start"] [data-pg-trns-id="trns-anim-element"] {
[pgtrns\:state="start"] [pgtrns\:id="trns-anim-element"] {
transform: translateY(0%);
}

[data-pg-trns-state="end"] [data-pg-trns-id="trns-anim-element"] {
[pgtrns\:state="end"] [pgtrns\:id="trns-anim-element"] {
transform: translateY(calc(-100% - var(--angled-segment-height)));
}
8 changes: 8 additions & 0 deletions src/index.webc
Expand Up @@ -284,6 +284,14 @@ description: "art director/they/them"
for (const el of document.getElementsByClassName("scroll-reveal-hidden")) {
scrollRevealObserver.observe(el);
}

document.addEventListener(
"transition:pageclosed",
() => {
scrollRevealObserver.disconnect();
},
{ once: true }
);
}
</script>
<script>
Expand Down
10 changes: 3 additions & 7 deletions src/js/lazy-video.mjs
Expand Up @@ -26,18 +26,14 @@
);

const watchLazyVideos = () => {
const lazyVideos = Array.from(document.querySelectorAll("video.lazy"));
for (const video of lazyVideos) {
document.querySelectorAll("video.lazy").forEach((video) => {
lazyVideoObserver.observe(video);
}
});

document.addEventListener(
"transition:pageclosed",
() => {
for (const video of lazyVideos) {
lazyVideoObserver.unobserve(video);
}
lazyVideos.length = 0;
lazyVideoObserver.disconnect();
},
{ once: true }
);
Expand Down
81 changes: 60 additions & 21 deletions src/js/page-transition.mjs
Expand Up @@ -3,21 +3,40 @@
history.scrollRestoration = "manual";
}

let previousURL = new URL(window.location.href);
/** @type {null | URL} */
let previousURL = null;
let currentURL = new URL(window.location.href);
const previousScrollPositions = {};

/**
* @param {URL} newURL
*/
const updatePreviousURL = (newURL) => {
previousScrollPositions[previousURL.pathname] = window.scrollY;
previousURL = newURL;
previousScrollPositions[currentURL.pathname] = window.scrollY;
previousURL = currentURL;
currentURL = newURL;
};

const pageTransitionStateAttr = "data-pg-trns-state";
const pageTransitionIDAttr = "data-pg-trns-id";
const pageTransitionStateAttr = "pgtrns:state";
const pageTransitionIDAttr = "pgtrns:id";
const pageTransitionIDSelector = "pgtrns\\:id";

/**
* @typedef {Object} PageCacheEntry
* @property {string} theme
* @property {HTMLElement[]} headChildren
* @property {HTMLElement[]} bodyChildren
*/

/** @type {Object.<string, Promise<PageCacheEntry> | PageCacheEntry> }} */
const pageCache = {};

const domParser = new DOMParser();

/**
* @param {string} pathname
* @returns {Promise<PageCacheEntry>}
*/
const fetchPage = async (pathname) => {
if (pageCache[pathname]) {
return pageCache[pathname];
Expand All @@ -38,9 +57,18 @@
};
});

pagePromise.then((pageData) => {
// Unwrap the data returned from the promise into the cache
pageCache[pathname] = pageData;
});

return (pageCache[pathname] = pagePromise);
};

/**
* @param {HTMLElement} targetElement
* @param {HTMLElement[]} newChildren
*/
const applyNewPageContents = (targetElement, newChildren) => {
const initialChildCount = targetElement.childNodes.length;
for (let i = initialChildCount - 1; i >= 0; i--) {
Expand All @@ -56,7 +84,7 @@

if (pageTransitionID) {
const existingPageTransitionElement = targetElement.querySelector(
`[${pageTransitionIDAttr}="${pageTransitionID}"]`
`[${pageTransitionIDSelector}="${pageTransitionID}"]`
);
if (existingPageTransitionElement) {
continue;
Expand All @@ -65,9 +93,11 @@

if (child.tagName === "SCRIPT") {
const scriptTag = document.createElement("script");
if (child.src) {
scriptTag.setAttribute("src", child.src);
} else {
// Transfer over all attributes to the new script tag
for (const attr of child.attributes) {
scriptTag.setAttribute(attr.name, attr.value);
}
if (child.textContent) {
scriptTag.appendChild(document.createTextNode(child.textContent));
}
targetElement.appendChild(scriptTag);
Expand All @@ -77,11 +107,21 @@
}
};

/** @type {URL[]} */
const transitionURLQueue = [];
let isTransitioning = false;

const transitionToPage = async (newPageURL, isBackNavigation) => {
/**
* @param {URL} newPageURL
* @param {boolean} isBackNavigation
*/
const transitionToPage = async (
newPageURL,
isBackNavigation = newPageURL.pathname === previousURL?.pathname
) => {
try {
updatePreviousURL(newPageURL);

transitionURLQueue.push(newPageURL);
// Start fetching the new page so we can load it while the transition animation is playing
fetchPage(newPageURL.pathname);
Expand Down Expand Up @@ -112,12 +152,14 @@
applyNewPageContents(document.head, headChildren);
applyNewPageContents(document.body, bodyChildren);

if (!isBackNavigation && newPageURL.hash) {
document.getElementById(newPageURL.hash.substring(1)).scrollIntoView();
} else {
if (isBackNavigation) {
// Restore the previous scroll position for this page if available, otherwise scroll to the top
window.scroll(0, previousScrollPositions[newPageURL.pathname] || 0);
delete previousScrollPositions[newPageURL.pathname];
} else if (newPageURL.hash) {
document.getElementById(newPageURL.hash.substring(1)).scrollIntoView();
} else {
window.scroll(0, 0);
}

document.dispatchEvent(new CustomEvent("transition:pageopened"));
Expand All @@ -136,7 +178,7 @@
// start transitioning again for the new target URL
const nextPageURL = transitionURLQueue.pop();
transitionURLQueue.length = 0;
transitionToPage(nextPageURL);
transitionToPage(nextPageURL, isBackNavigation);
});
}
} catch (err) {
Expand All @@ -148,14 +190,13 @@
}
};

const onClick = (e) => {
const onClickLink = (e) => {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
// Don't play the page transition animation if the user prefers reduced motion
return;
}

const targetURL = new URL(e.currentTarget.href);
updatePreviousURL(targetURL);

if (targetURL.pathname === window.location.pathname) {
if (targetURL.hash) {
Expand All @@ -180,13 +221,13 @@

const addLinkTransitionListeners = () => {
document.querySelectorAll('a[href^="/"]:not([download])').forEach((el) => {
el.addEventListener("click", onClick);
el.addEventListener("click", onClickLink);

// When the current page is closed, clean up listeners
document.addEventListener(
"transition:pageclosed",
function onPageClosed() {
el.removeEventListener("click", onClick);
el.removeEventListener("click", onClickLink);
document.removeEventListener("transition:pageclosed", onPageClosed);
}
);
Expand All @@ -205,10 +246,8 @@
window.addEventListener("popstate", () => {
const newURL = new URL(window.location.href);

if (newURL.pathname !== previousURL.pathname) {
if (newURL.pathname !== currentURL.pathname) {
transitionToPage(newURL, true);
}

updatePreviousURL(newURL);
});
}

0 comments on commit 651f4b0

Please sign in to comment.