Svelteのtransition機能を使ってみる
はじめに
個人開発でSvelte, SvelteKitを利用しています。
svelteにはtransitionという機能が用意されています。この機能は触ってみると結構便利な点がありました。
今回はこれを使ってsnackbarを実装してみます。
前提
"svelte": "4.2.7",
"@sveltejs/kit": "1.27.6",
"@pandacss/dev": "0.19.0",
svelte/transitionとは?
svelteには現在7つのtransition関数が用意されています。
今回はsnackbarの実装をしたいので、slideを使うことにしました。
- fade
- blur
- fly
- slide
- scale
- draw
- crossfade
以下がざっくりとした実装例です。
多少のstyleは実装する必要がありますが、これだけでslideのアニメーションを実装することができるのは手軽で良いですね。
<script lang="ts">
import { slide } from 'svelte/transition'
// buttonのclickイベント等で値の更新をする
let visible: boolean = false
</script>
{#if visible}
<div class="slide" transition:slide={{ delay: 200, duration: 300, axis: 'x' }} >
slide transition
</div>
{/if}
<style>
.slide {
position: fixed;
width: 200px;
bottom: 20px;
right: 20px;
background-color: white;
}
</style>
この例ではslideにdelay, duration, axisといったパラメータを設定していています。それぞれ以下を意味しています。
- delay: アニメーション開始をどのくらい遅らせるか(ミリ秒)
- duration: animationの開始から終了までの時間(ミリ秒)
- axis: slideの動きの方向(xまたはy)
各transitionでは、このようにアニメーションに変化を与えるためのパラメータを設定可能です(各transition関数によって渡せるパラメータが一部異なる)。
今回の実装では使いませんが、transition-eventsというものも便利な機能です。
introstart, introend, outrostart, outroend といったように、アニメーションのタイミングに合わせて処理を割り当てることができます。
今回の実装方針
ざっと今回の実装方針は以下のよう感じです。
- Snackbarコンポーネントは、routes直下の直下の+layout.svelteで呼び出す
- 上記のため、snackbarに関する状態管理はグローバルな状態として管理する(storeを利用)
実際の実装
状態管理
前述した通り、svelteのstore機能を使って状態管理します。
+layout.svelte(必要な部分だけ)
<script lang="ts">
// ...省略
import { createSnackbar } from '$globalStates/snackbar'
import Snackbar from '$ui/Snackbar/Snackbar.svelte'
const snackbars = createSnackbar
</script>
<!-- ...省略 -->
<div class={snackbarContainer}>
{#each $snackbars as snackbar (snackbar.id)}
<Snackbar status={snackbar.status} message={snackbar.message} />
{/each}
</div>
Snackbarコンポーネント
ここで1つ注意点があります。
globalで状態を管理しているからといって、Layoutとは別でsnackbarのstoreを呼び出してその値をコンポーネントで使うことは避けた方が良いです。
理由は以下の恩恵を受けられなくなるためです。
おそらくですがtransitionにはアニメーションの完了までdom側で状態を保持してくれる機能があります。
今回の実装だと、addSnackbarの処理では、指定した時間後に対象のsnackbarの状態を削除するようになっています。
本来であればsnackbarはoutrostartのタイミングでmessage等の状態は消えているはずですが、dom側ではoutroendのタイミングまでmessageやstatusが確認できているのがその証拠です。
今回は以上です。
Discussion