2024-03-16
TransitionAPIとテーマのロジック変更
TransitionAPIの導入
今まで気になってはいたが機能的なものではなくアニメーションのものなのであってもなくてもいいかなと思っていた。
しかし,ページ自体の読み込み待ちの時間の短縮に繋がるなら間接的にUXの向上につながると考え,このたび導入した。
またAstroではドキュメントが整理されているため簡単に導入することができた。
参考サイト
Transitionについて
https://developer.mozilla.org/ja/docs/Web/API/View_Transitions_API
TransitionAPIチュートリアル
https://docs.astro.build/ja/tutorials/add-view-transitions/#update-scripts
TransitionAPIドキュメント
https://docs.astro.build/en/guides/view-transitions/
ダークモードの実装
https://karan-dev-blog.com/blog/0qxprbzqjm
実装
一番注意すべきこと
もしすでにテーマの実装をしているのであれば,初期化されてしまうかもれない。
理由としてSPAモードになるため,ページナビゲーション時にダークモードを設定するJavascriptが再実行されないようになる。
そのことを事前に想定していればより理解しやすいように感じる。
ページ全体
Layout.astro
// TODO: deleted
<script>
const theme = localStorage.getItem("theme");
if (theme) {
if (theme === "dark") {
document.documentElement.classList.add("dark");
}
} else {
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
document.documentElement.classList.add("dark");
localStorage.setItem("theme", "dark");
}
}
</script>
// TODO: add
import { ViewTransitions } from "astro:transitions";
---
<script>
const setClassTheme = () => {
const theme = localStorage.theme;
if (theme) {
theme === "dark"
? document.documentElement.classList.add("dark")
: document.documentElement.classList.remove("dark");
} else {
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
document.documentElement.classList.add("dark");
localStorage.theme = "dark";
} else {
document.documentElement.classList.remove("dark");
localStorage.theme = "light";
}
}
};
setClassTheme();
document.addEventListener("astro:after-swap", () => setClassTheme());
</script>
<ViewTransitions />
これだけでViewTransitionAPIをページ全体で利用することができるようになる。
変更の主な違いとして
astro:after-swap
イベントをリッスンしており、SPAモードでのページ間の遷移時にもテーマ設定が適切に適用されるようになった。- また関数としてsetClassThemeとすることで初期表示とSPAでの両方に対応することができている。
また現在の改善点として,初期表示の際にLocalStorageのデータがない場合のみelse以下の部分を実行してそれ以外の場合は実行しないというリファクタリングをすることができる。
実際にSPAでのページ遷移については活発になると思うためここの部分のスクリプトで何度も呼ばれるafter-swapでの関数は初期表示とSPAとで切り分けた方がパフォーマンスの向上につながると考える。
テーマ変更ボタン
SwapThemeButton.astro
// TODO: html part add transition:persist in parent element
// link this:
<button transition:persist >text</button/>
<script>
// TODO: deleted
document.addEventListener("DOMContentLoaded", () => {
// TODO: add
document.addEventListener("astro:page-load", () => {
</script/>
リスナーの大きな違いとしてSPAに対応するかどうかという点である。
astro:page-load
は、ページの初回読み込みだけでなく,SPAモードでのページ遷移時にも発火するがDOMContentLoaded
はページの初回読み込み時にのみ発火するという違いがある。
今回のようにTransitionAPIを利用する場合はページ遷移後もテーマの状態を正しく維持する必要があるためSPA時での発火も求められる。
またtransition:persist
を利用することで遷移間の状態や要素を維持するなど、ページ遷移をカスタマイズすることができる。
ここまですることによってSPAでも常に遷移時もLocalStorageのテーマを参照することができるようになり,現状のアプリケーションにTransitionを追加することができるようになる。
SPAによる複雑化
シンプルなページの際の初期表示のみを管理するだけではなくその後の状態も管理する必要が出てくる。
そのため,シンプルにTransitionAPI自体は利用することはできるかもしれないが今までより,リッスンするイベントを追加したりする必要があるため複雑化はする。
しかしAstro側ですでにSPA対応のハンドラーを定義してくれているので,あとはいかに初期表示の部分とSPAの際のスクリプトの切り分けをすることができるかが大切になってくると感じる。
しかしそれ以上にUXの向上につながるのであれば引き続きできることはキャッチアップしていきたい。