Karan Engineering Blog
進捗状況
0%

2024-03-16

TransitionAPIとテーマのロジック変更

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の向上につながるのであれば引き続きできることはキャッチアップしていきたい。

© 2023 Karan. All Rights Reserved.