sveltekit-view-transitionを使ってSvelteKitでView Transition APIを簡単に使う

## View Transition APIとは
[MDN Web doc](https://developer.mozilla.org/ja/docs/Web/API/View_Transitions_API)によると
> ビュートランジション API は、異なる DOM 状態間のアニメーション遷移を簡単に作成する仕組みを提供し、同時に DOM コンテンツも単一の手順で更新します。

とのことです。つまりスマートフォンアプリなどで一般的なスムーズな遷移表現のWeb版ですね。

## SvelteKitとView Transition API
SvelteKitとView Transition APIについてはSvelte.devの[Blog記事](https://svelte.dev/blog/view-transitions)に記載の通り、SvelteKit 1.24で実装されたonNavigateライフサイクルで利用可能になりました。

以下のコードはページ遷移時にクロスフェード効果を適用します。
```js
onNavigate((navigation) => {
	if (!document.startViewTransition) return;
	return new Promise((resolve) => {
		document.startViewTransition(async () => {
			resolve();
			await navigation.complete;
		});
	});
});
```
僅かなCSSの記述とスニペットを使えばクロスフェード以外にも色々な遷移効果が実現できますが、もっと簡単に使いたいですよね。

## sveltekit-view-transitionを使えばいい

[sveltekit-view-transition](https://github.com/paoloricciuti/sveltekit-view-transition) はSvelteKitでView Transition APIをより簡単に利用できるライブラリです。

https://github.com/paoloricciuti/sveltekit-view-transition

## 準備

### プロジェクトの準備
今回の動作確認用に簡単なページ遷移を備えたプロジェクトを作りました。

![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/bb0960f4-a5f2-b7b1-c82b-fef733b22f5d.gif)


### sveltekit-view-transition のインストール
```bash
$ npm i -D sveltekit-view-transition@latest
```

## 使い方

### クロスフェード効果
以下のコードをルートlayoutなどに追記するだけで内部のページ遷移にクロスフェード効果が適用されます。とても簡単ですね。
```html
<script>
	import { setupViewTransition } from 'sveltekit-view-transition';

	setupViewTransition();
</script>
```
![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/cf977095-6c4f-b8ee-df5c-a43cdd55f6c4.gif)


### スライド効果
古いページが左へスライドしながらフェードアウトしてゆき、新しいページが右からフェードインします。前述のクロスフェード効果に下記のCSSでカスタムします。
```css
@keyframes fade-in {
  from {
    opacity: 0;
  }
}
@keyframes fade-out {
  to {
    opacity: 0;
  }
}
@keyframes slide-from-right {
  from {
    transform: translateX(100px);
  }
}
@keyframes slide-to-left {
  to {
    transform: translateX(-100px);
  }
}
:root::view-transition-old(root) {
  animation:
    90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
:root::view-transition-new(root) {
  animation:
    210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
```

![4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/48a0797a-ec7d-da68-97be-8168562b91c3.gif)


### 要素のトランジション
クリックした画像が遷移先の画像へと遷移するアレです。  
遷移元、遷移先の要素それぞれにuse:transitionで設定することで、同じ名前の要素同士が連動するようになります。

#### 遷移元
```html
<script>
  import { setupViewTransition } from 'sveltekit-view-transition';

  const { transition } = setupViewTransition();
</script>

<div class="grid grid-cols-3 gap-8">
  {#each Array(6) as _, i}
    <a href="/description/{i + 1}" use:transition={`image${i + 1}`}>
      <img
        class="rounded-xl shadow-xl"
        src="https://example.com/pic{i + 1}.png"
        alt="pic-{i}"
      />
    </a>
  {/each}
</div>
```

#### 遷移先
```html
<script>
  import { page } from '$app/stores';
  import { setupViewTransition } from 'sveltekit-view-transition';

  const { transition } = setupViewTransition();
</script>

<img
    use:transition={`image${$page.params.img_no}`}
    src="https://example.com/pic{$page.params.img_no}.png"
    alt="pic-{$page.params.img_no}"
/>
```

![3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/fb4a2c62-e381-85e1-8ff2-d6ef71a94cb1.gif)


## まとめ
View Transitionは見た目が華やかになるだけではなく、要素の連続性を表現することでUXを高める効果もあります。SvelteKitを使用する際はぜひsveltekit-view-transition を使用して効果的なView Transitionを適用してみてはいかがでしょうか。

## 参考

https://svelte.dev/blog/view-transitions
https://github.com/paoloricciuti/sveltekit-view-transition
https://developer.mozilla.org/ja/docs/Web/API/View_Transitions_API
https://developer.chrome.com/docs/web-platform/view-transitions/