finish animations and add elevation
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
import { page } from '$app/stores';
|
||||
|
||||
import {
|
||||
mapTransitionCover,
|
||||
markPageLoading,
|
||||
markPageReady,
|
||||
pageContentReady
|
||||
@@ -104,10 +105,14 @@
|
||||
const OVERLAY_CEILING_MS = 15000;
|
||||
|
||||
// The map is a cross-origin iframe, and a browser does not paint one into a
|
||||
// view transition snapshot. Any transition with the maps page on either side
|
||||
// animates a hole where the map is: leaving it, the map drops out at frame one
|
||||
// and that blank sits under the incoming page for the whole run. Swapping
|
||||
// outright is the honest answer - there is nothing here to cross-fade.
|
||||
// view transition snapshot - captured bare, any transition with the maps page
|
||||
// on either side would animate a hole where the map is. The way out is to
|
||||
// make sure the map is never what gets captured: the maps page keeps an
|
||||
// opaque cover over the iframe while the map boots (so an arrival fades into
|
||||
// a clean panel, and the map fades up once ready), and raises the same cover
|
||||
// again just before a departure is captured (see mapTransitionCover). Both
|
||||
// snapshots then hold real pixels and the maps page transitions like any
|
||||
// other route.
|
||||
const MAPS_ROUTE = '/weather/maps';
|
||||
const onMapsPage = () => routePath(get(page).url.pathname).startsWith(MAPS_ROUTE);
|
||||
|
||||
@@ -187,7 +192,7 @@
|
||||
|
||||
/**
|
||||
* True when the navigation lands on the route and params the page is already
|
||||
* showing - the sidebar's home link from the 7-day page it points at, or a
|
||||
* showing - the sidebar's home link from the week page it points at, or a
|
||||
* link that differs only in the query string.
|
||||
*
|
||||
* SvelteKit keeps the page component mounted for those, and nothing it holds
|
||||
@@ -206,7 +211,7 @@
|
||||
return JSON.stringify(from.params ?? {}) === JSON.stringify(to.params ?? {});
|
||||
}
|
||||
|
||||
onNavigate((navigation) => {
|
||||
onNavigate(async (navigation) => {
|
||||
const pending =
|
||||
PENDING_ROUTES.has(navigation.to?.route?.id ?? '') && !landsOnCurrentPage(navigation);
|
||||
// Either way the flag is set explicitly: leaving a page that never resolved
|
||||
@@ -217,9 +222,16 @@
|
||||
// `startViewTransition` decides whether a transition is possible at all
|
||||
// (support, reduced motion, one already capturing) and runs the update
|
||||
// inline when it is not - so there is exactly one path from here down.
|
||||
const touchesMap =
|
||||
navigation.from?.route?.id === MAPS_ROUTE || navigation.to?.route?.id === MAPS_ROUTE;
|
||||
const underTransition = canStartViewTransition() && !touchesMap;
|
||||
const underTransition = canStartViewTransition();
|
||||
|
||||
// Leaving the maps page: cover the iframe before the outgoing state is
|
||||
// captured, so the snapshot holds a clean panel instead of a hole where
|
||||
// the map was. The tick makes sure the cover is actually in the DOM by
|
||||
// the time the capture reads it.
|
||||
if (underTransition && navigation.from?.route?.id === MAPS_ROUTE) {
|
||||
mapTransitionCover.set(true);
|
||||
await tick();
|
||||
}
|
||||
|
||||
return new Promise<void>((swap) => {
|
||||
void startViewTransition(
|
||||
@@ -242,6 +254,11 @@
|
||||
let mainEl = $state<HTMLElement | null>(null);
|
||||
|
||||
afterNavigate((navigation) => {
|
||||
// The departure snapshot (if any) is taken by now, so the maps cover has
|
||||
// done its job; lowering it here also means a later visit to the maps page
|
||||
// starts from its own boot cover rather than a stuck one.
|
||||
mapTransitionCover.set(false);
|
||||
|
||||
// The page scrolls inside <main>, not the window, so SvelteKit's own scroll
|
||||
// handling never touches it and a new page would open half way down.
|
||||
// Back/forward and in-page anchors keep their position.
|
||||
|
||||
Reference in New Issue
Block a user