[WIP] View Transition APIによるスムーズな遷移のサンプル

View Transition APIとは

- `View Transition API` を使用すると、WEBサイトのさまざまなView間でシームレスな視覚的な遷移を作成できる - マルチページ アプリケーション (`MPA`) とシングルページ アプリケーション (`SPA`)、どちらでも対応可能

View遷移の動き

1. ブラウザが、新旧の状態のスナップショットを作成 2. レンダリングが抑制されている間にDOMが更新される 3. 遷移にCSSアニメーションを利用

SPAでの同一ドキュメントView遷移

1. 同じドキュメント ビューの移行をトリガーするには、`document.startViewTransition` を呼び出す 2. ブラウザを呼び出すと、`view-transition-name` CSS プロパティが宣言されている全ての要素のスナップショットが自動的にキャプチャされる - スナップショットは疑似要素のツリーに配置され、CSSアニメーションの機能を使用してアニメーション化される 3. 渡されたコールバックを実行してDOMを更新する 4. 新しい状態のスナップショットを取得する - 元の状態と新しい状態のスナップショットのペアは、コンテンツがクロスフェードしている間、以前の位置とサイズから新しい場所にスムーズに移行する - 必要に応じて、CSSを使用してアニメーションをカスタマイズ可能

クロスフェード: デフォルトの遷移

- デフォルトのView遷移は「クロスフェード」 - `.startViewTransition()` が呼び出されると、API はページの現在の状態を取得する - スナップショットの取得も含まれる
function spaNavigate(data) {
  // View Transition APIに未対応なブラウザ用のFallback
  if (!document.startViewTransition) {
    updateTheDOMSomehow(data);
    return;
  }

  // View Transition APIを使った遷移
  document.startViewTransition(() => updateTheDOMSomehow(data));
}

新しい状態が取り込まれると構築される擬似要素ツリー

::view-transition
└─ ::view-transition-group(root)
    └─ ::view-transition-image-pair(root)
      ├─ ::view-transition-old(root)
      └─ ::view-transition-new(root)
- `::view-transition` は、ページ上のすべての要素の上にオーバーレイとして配置される - 遷移の背景色を設定する場合に便利 - `::view-transition-old(root)` は古いビューのスクリーンショットで、`::view-transition-new(root)` は新しいビューのライブ表現 - どちらもCSSの「置換コンテンツ」(`` など) としてレンダリングされる - 古いビューは `opacity: 1` から `opacity: 0` にアニメーション化され、新しいビューは `opacity: 0` から `opacity: 1` にアニメーション化され、クロスフェードが作成される - 全てのアニメーションは、CSSアニメーションを使用して実行されるため、CSSでカスタマイズが可能

CSSで遷移をカスタマイズ

- フェードを遅くする例
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 5s;
}

複数の要素の遷移

- ページの残りの部分からヘッダーを抽出して、個別にアニメーション化するには、要素に `view-transition-name` を割り当てる - `view-transition-name` の値には任意の値を使用できる - ただし、遷移名がない `none` は除く - 遷移全体で、要素を一意に識別するために使用される
.main-header {
  view-transition-name: main-header;
}
- 上記のCSS指定でヘッダーは固定され、クロスフェードされる

`view-transition-class` を使用して同じ方法で複数の擬似要素をアニメーション化

- 複数のカードを使用するビュー遷移があり、ページ上にタイトルもある場合、タイトルを除く全てのカードをアニメーション化するには、全てのカードをターゲットとするセレクタを作成する必要がある - ビュー遷移疑似要素で `view-transition-class` を使用して、同じスタイルルールを適用可能 - キャプチャが機能するためには、全ての要素に一意の `view-transition-name` を指定する必要がある - `view-transition-class` は、アニメーション スタイルの重複を除去する
#card1 { view-transition-name: card1; }
#card2 { view-transition-name: card2; }
#card3 { view-transition-name: card3; }
#card4 { view-transition-name: card4; }
#card5 { view-transition-name: card5; }
…
#card20 { view-transition-name: card20; }

#cards-wrapper > div {
  view-transition-class: card;
}
html::view-transition-group(.card) {
  animation-timing-function: var(--bounce);
}

遷移をデバッグ

- View遷移はCSSアニメーションの上に作成されるため、遷移のデバッグにはChrome DevToolsの `[Animations]` パネルが最適 - Chrome DevToolsを開いて `ESC` を押すと出てくる部分の `︙` をクリックすると、`[Animations]` パネルを表示可能 - `[Animations]` パネルで、次のアニメーションを一時停止してから、アニメーション内を前後にスクラブできる - この間、遷移の疑似要素は [要素] パネルに表示される

参照