見出し画像

SolidJS 用アニメーションライブラリ、Solid Transition Group を使ってみた

この記事は「株式会社メンバーズ Jamstack研究会主催 Advent Calendar
2023
」の20日目の記事です。


はじめに

この記事では、SolidJS 用のアニメーションライブラリである Solid Transition Group を使ってみましたので、その感想と、使い方のざっくりとした説明などをまとめました。

設計や機能は、React 用の React Transition Group と、Vue の Transition に影響を受けている、とのことです。
触ってみた感想としては、それらと大部分は似通っていますが、更にシンプルに扱えるよう、調整・洗練されている箇所が多いと感じました。

本記事は、Solid Transition Groupの v0.2.3 を利用した場合の内容となっています。

インストール

SolidJS がインストール済みのプロジェクトが既にある前提で話を進めていきます。

インストール作業は、solid-transition-group の package をお好みの方法でインストールするだけです。

npm install solid-transition-group
# or
yarn add solid-transition-group
# or
pnpm add solid-transition-group

インストールが完了したら、早速アプリ内で利用してみましょう。

Transition コンポーネント を使ったシンプルな例

Solid Transition Group では、<Transition> と <TransitionGroup> の2種類のアニメーション制御を扱えます。今回は <Transition> に絞ってご紹介したいと思います。

<Transition> は、要素やコンポーネントが DOM 内に enter (挿入) 、exit (削除) されるとき、アニメーションを適用するために利用します。

例として、以下の画像とソースコードで示したページで考えてみましょう。

Show と Hide の2つのボタンがあり、それぞれを押すことで、表示状態を管理する isVisible の true / false が切り替わります。

その下には、p 要素で包まれた "Hello transition!" というテキストがあり、SolidJS 組み込みの <Show> コンポーネントが isVisible をもとに DOM への挿入、削除を制御しています。

import { Show, createSignal } from 'solid-js';
import { Transition } from 'solid-transition-group';
import './App.css'

function App() {
  const [isVisible, setVisible] = createSignal(true)

  return (
    <>
      <button onClick={() => setVisible(true)}>Show</button>
      <button onClick={() => setVisible(false)}>Hide</button>

      <Show when={isVisible()}>
        <div>Hello transition!</div>
      </Show>
    </>
  )
}

export default App

今回は、上記のページに対し、以下のアニメーションを実装することを目標に進めてみます。

  • 初期状態

    • Show ボタンと Hide ボタンだけが表示され、”Hello transition!” は非表示

  • Show ボタンをクリックしたとき

    • "Hello transition!" がフェードイン

    • 透明状態から 1.5s かけて不透明になる

  • Hide ボタンをクリックしたとき

    • "Hello transition!" がフェードアウト

    • 不透明状態から 1s かけて透明になる

Transition コンポーネント に要素を渡す

<Transition> を import して JSX 内に配置し、アニメーションさせたい要素・コンポーネントを children として渡すことで、アニメーションの対象とすることができます。

今回は、<Show> で制御されている p 要素のアニメーションを制御するため、以下のように記述します。

import { Transition } from "solid-transition-group"

(中略)

<Transition name="fade">
  <Show when={isVisible()}>
    <p>Hello transition!</p>
  </Show>
</Transition>

ライフサイクル

<Transition> は、アニメーションのライフサイクル内の各段階ごとに class を生成し、children として渡した要素・コンポーネントに対し適用し、その段階が終われば自動で class を削除します。

ライフサイクルは以下の通りです。

enter(要素の追加時)

  • enter : enter 開始の瞬間

  • enter-to : enter の開始後、遷移が続いている間

  • enter-active : enter と enter-to を含めた、遷移が続いている間

exit(要素の削除時)

  • exit : exit 開始の瞬間

  • exit-to : exit が開始後、遷移が続いている間

  • exit-active : exit と exit-to を含めた、遷移が続いている間

要素・コンポーネントに適用される class 名は、上記のコード内で <Transition> の props として指定した name (今回は "fade" としました。省略した場合のデフォルトは "s" になります) が先頭につき、ライフサイクル内のステップ名が続きます。
例えば、enter の遷移中は、同時に `enter-to` と `enter-active` の2つの状態になるので、実際にレンダリングされる p 要素は以下のようになります。

<p class="fade-enter-to fade-enter-active">Hello transition!</p>

適用される class 名は既に分かっているので、CSS ファイル内に、上記の class 名の通りに selector を指定し、ライフサイクルの段階ごとにどの style が適用されてほしいか、を記述します。

今回は、以下のような CSS が出来上がりました。

/* enter, exit のそれぞれで transition プロパティを指定することができる */
.fade-enter-active {
  transition: opacity 1.5s;
}
.fade-exit-active {
  transition: opacity 1s;
}

/* enter の開始時は opacity: 0(透明) */
.fade-enter {
  opacity: 0; 
}

/* enter の終了時に opacity: 1(不透明) になるよう遷移させる */
.fade-enter-to {
  opacity: 1;
}

/* 
  enter 後(isVisible = true)の間は opacity: 1(不透明) になっているので、
  .fade-exit で opacity: 1 を指定する必要はな
*/

/* exit の終了時に opacity: 0(透明) になるよう遷移させる */
.fade-exit-to {
  opacity: 0;
}

上の例では、.fade-enter と .fade-exit で指定している内容は同じなのでまとめてもいいんですが、分かりやすくするため別々に分けています。

動かしてみる

目指していた動作が実現できました!
適用されているクラスが分かるよう、DevTools も同時に表示しています。(.fade-enter と .fade-exit は一瞬すぎて見えませんが……)

同系統のライブラリでは、class を付与してから削除するまでの時間を timeout という props として指定しなければならない場合もあるんですが、
Solid Transition Group では、デフォルトで CSS の transitionend, animationend イベントを検知して自動で class を削除してくれるため、とてもシンプルに使えると感じました。

今回は CSS での適用だけでしたが、<Transition> に渡す props によって、アニメーションのライフサイクルの各段階で JavaScript の関数呼び出しをさせることができるため、
遷移完了を検出して何かのトリガーにするなど、活用の幅も広がります。

まとめ

この記事の執筆時点では、Solid Transition Group について書かれた日本語の記事が見当たらなかったため、Solid Transition Group をはじめとした関連ライブラリをもっと広め、導入の敷居を下げたいという思いで記事を書いてみました。

Jamstack での文脈上では、SolidJS は Astro 上でも利用できたり、まだベータ版ですがメタフレームワークである SolidStart があったりと、SolidJS はまだまだ盛り上がりそうな様子です。これから更に利用者が増えるよう、情報発信を続けていきたいです。

最後までご覧いただき、ありがとうございました!


この記事が気に入ったらサポートをしてみませんか?