はじめに
SvelteKit v1.24.0がリリースされ、onNavigateというライフサイクル関数が追加されました。
onNavigateを使用することでURLに移動する直前に指定したコールバックを実行することができます。
onNavigateを使うことでSvelteKitでView Transitions APIを使用して、リッチなページ遷移を実現する方法を説明します。
注意
View Transitions APIはChrome 111
以上、または Edge 111
以上 で使用できます。
FirefoxやSafariでは今のところ動かないので注意してください。
SvelteKitプロジェクトのセットアップ
まず、SvelteKitプロジェクトをセットアップします。以下のコマンドで新しいプロジェクトを作成できます。
テンプレートを選択できますが、SvelteKit demo app
を選択してください。
npm create svelte@latest my-app
┌ Welcome to SvelteKit!
│
◆ Which Svelte app template?
│ ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works without JavaScript!)
│ ○ Skeleton project
│ ○ Library project
└
次に、プロジェクトディレクトリに移動します。
cd my-app
依存関係をインストールします。
npm install
View Transitions APIを使って、リッチなページ遷移を実装する
+layout.svelte
を編集する
<script>
import Header from './Header.svelte';
import './styles.css';
+ import { onNavigate } from '$app/navigation';
+ onNavigate(() => {
+ if (!document.startViewTransition) return;
+
+ return new Promise((resolve) => {
+ document.startViewTransition(async () => {
+ resolve();
+ await navigation.complete;
+ });
+ });
+ });
</script>
<div class="app">
<Header />
<main>
<slot />
</main>
<footer>
<p>visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to learn SvelteKit</p>
</footer>
</div>
<style>
.app {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
display: flex;
flex-direction: column;
padding: 1rem;
width: 100%;
max-width: 64rem;
margin: 0 auto;
box-sizing: border-box;
}
footer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 12px;
}
footer a {
font-weight: bold;
}
@media (min-width: 480px) {
footer {
padding: 12px 0;
}
}
</style>
Header.svelte
を編集する
<script>
import { page } from "$app/stores";
import logo from "$lib/images/svelte-logo.svg";
import github from "$lib/images/github.svg";
</script>
<header>
<div class="corner">
<a href="https://kit.svelte.dev">
<img src={logo} alt="SvelteKit" />
</a>
</div>
<nav>
<svg viewBox="0 0 2 3" aria-hidden="true">
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
</svg>
<ul>
<li aria-current={$page.url.pathname === "/" ? "page" : undefined}>
<a href="/">Home</a>
</li>
<li aria-current={$page.url.pathname === "/about" ? "page" : undefined}>
<a href="/about">About</a>
</li>
<li
aria-current={$page.url.pathname.startsWith("/sverdle")
? "page"
: undefined}
>
<a href="/sverdle">Sverdle</a>
</li>
</ul>
<svg viewBox="0 0 2 3" aria-hidden="true">
<path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" />
</svg>
</nav>
<div class="corner">
<a href="https://github.com/sveltejs/kit">
<img src={github} alt="GitHub" />
</a>
</div>
</header>
<style>
header {
display: flex;
justify-content: space-between;
}
.corner {
width: 3em;
height: 3em;
}
.corner a {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.corner img {
width: 2em;
height: 2em;
object-fit: contain;
}
nav {
display: flex;
justify-content: center;
--background: rgba(255, 255, 255, 0.7);
}
svg {
width: 2em;
height: 3em;
display: block;
}
path {
fill: var(--background);
}
ul {
position: relative;
padding: 0;
margin: 0;
height: 3em;
display: flex;
justify-content: center;
align-items: center;
list-style: none;
background: var(--background);
background-size: contain;
}
li {
position: relative;
height: 100%;
}
li[aria-current="page"]::before {
--size: 6px;
content: "";
width: 0;
height: 0;
position: absolute;
top: 0;
left: calc(50% - var(--size));
border: var(--size) solid transparent;
border-top: var(--size) solid var(--color-theme-1);
}
nav a {
display: flex;
height: 100%;
align-items: center;
padding: 0 0.5rem;
color: var(--color-text);
font-weight: 700;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.1em;
text-decoration: none;
transition: color 0.2s linear;
}
a:hover {
color: var(--color-theme-1);
}
+ li[aria-current="page"]::before {
+ view-transition-name: active-page;
+ }
</style>
app.d.ts
を編集する
startViewTransition
がIDE等でうまく認識してくれなくて型エラーになる場合があります。
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface Platform {}
}
+ interface ViewTransition {
+ updateCallbackDone: Promise<void>;
+ ready: Promise<void>;
+ finished: Promise<void>;
+ skipTransition: () => void;
+ }
+ interface Document {
+ startViewTransition(updateCallback: () => Promise<void>): ViewTransition;
+ }
}
export {};
キャプチャ画面
オレンジのインジケーターがスムーズに動くようになりました
さいごに
今回は、SvelteKit v1.24.0で追加されたonNavigateを用いて、View Transitions APIを使ったリッチなページ遷移の実装方法を説明しました。
この実装により、ユーザのナビゲーション体験を向上させることが可能だと思うので是非試してみてください!