Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

view-transitions

View Transitions APIを使ったDOMの変更アニメーションを習得できます。手動のアニメーションコードを書かずに、ページ遷移やUI状態の切り替えをスムーズにアニメーションさせたいときに活用してください。

description の原文を見る

Teaches the View Transitions API for animating DOM changes. Use when you want smooth animated transitions between pages or UI states without manual animation code.

SKILL.md 本文

ビューの遷移アニメーション

目次

使用する際

  • 異なるページ状態間またはナビゲーション間のアニメーション遷移を実現したい場合に使用する
  • Webアプリケーション内で磨き上げられたアプリのようなナビゲーション体験を作成するのに役立つ

インストラクション

  • document.startViewTransition(callback) を使用してDOM変更をアニメーション化する
  • 状態間で遷移すべき要素に一意の view-transition-name CSS プロパティを割り当てる
  • APIを使用する前にブラウザのサポートを確認する (if (document.startViewTransition))
  • DOMがフリーズしている時間を最小化するため、データフェッチの完了後に遷移を開始する
  • View Transitions API をまだサポートしていないブラウザ向けに、CSSアニメーションのフォールバックを検討する

詳細

View Transitions APIの紹介

View Transitions API は、ビジュアルなDOM変更をある状態から次の状態へ遷移させるシンプルな方法を提供します。これには、コンテンツの切り替えなどの小さな変更から、あるページから別のページへのナビゲーションなどのより広範な変更まで含まれます。

JavaScriptのAPIは document.startViewTransition(callback) を中心に構成されており、 callback は通常DOMを新しい状態に更新する関数です。

<details> 要素の切り替えをシンプルな例として考えてみましょう:

if (document.startViewTransition) {
  // (ブラウザのサポートを確認)
  document.addEventListener("click", function (event) {
    if (event.target.matches("summary")) {
      event.preventDefault(); // (要素は自分たちで切り替える)
      const details = event.target.closest("details");
      document.startViewTransition(() => details.toggleAttribute("open"));
    }
  });
}

document.startViewTransition はコールバック呼び出しの前に現在のDOMのスクリーンショットを取得します。ここでは、コールバックは単に open 属性を切り替えるだけです。完了すると、ブラウザは初期スクリーンショットと新しいバージョン間で遷移できます。

これらの古いバージョンと新しいバージョンは疑似要素として表現され、CSSで ::view-transition-old(root)::view-transition-new(root) で参照できます。例えば、遷移を強調するために animation-duration を長くすることができます:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 2s;
}

ビューの遷移は複数の変更をアニメーション化することも可能で、デフォルトのクロスフェード以上の高度なアニメーションを実現できます。特定の要素にCSS view-transition-namelayout または paintcontainment を付与することで、APIは開発者に要素の幅、高さ、位置を含めた遷移方法に対する細かな制御を提供します。これらの高度な遷移は、あるページから次のページへのフローを非常に効果的に伝達するのに役立ちます。

写真ギャラリーを例として考えます。最も明白な遷移は写真のサイズと位置です。各ページの <img> 要素に同じ一意の view-transition-name を付与し、CSS containment 値を layout に設定することで、自動的に実現されます。 view-transition-name はスタイル属性にハードコーディングすることも、動的に追加することもできます(例えば、 onclick ハンドラ内で)。ただし、ページに一意であり、遷移開始前に追加される必要があります。

写真の下の詳細情報には、もう少し多くのスタイリングが必要です。各行要素に独自の view-transition-name を付与します:

figcaption h2 {
  contain: layout;
  view-transition-name: photo-heading;
}
figcaption div {
  contain: layout;
  view-transition-name: photo-location-time;
}
figcaption dl {
  contain: layout;
  view-transition-name: photo-meta;
}

これは各エリア用の 遷移グループ を生成します。これは前述の新しい/古いスクリーンショットと同じようなものですが、文書全体ではなくページのエリアのみを対象とします。文書全体の遷移要素が ::view-transition-old(root)::view-transition-new(root) で対象化できるのと同じように、これらの遷移グループは ::view-transition-old(NAME)::view-transition-new(NAME) で対象化できます。詳細テキストは写真グリッドページに存在しないため、グリッドから写真ページへ遷移する場合、 ::view-transition-new(NAME) が存在しますが、 ::view-transition-old(NAME) は存在しません。反対方向のナビゲーションでもその逆です。したがって、これらのケースは :only-child 疑似クラスを使用して対象化し、アニメーションをカスタマイズできます。 photo-heading グループについて:

/* Enter */
::view-transition-new(photo-heading):only-child {
  animation: 300ms ease 50ms both fade-in, 300ms ease 50ms both slide-up;
}

/* Exit */
::view-transition-old(photo-heading):only-child {
  animation: 200ms ease 150ms both fade-out, 200ms ease 150ms both slide-down;
}

これはAPIの基本です。Jake Archibaldの優れたView Transitions記事 はこの詳細をよくカバーしています。それでは、フルページナビゲーションをどのように遷移させるかを見てみましょう。

ページナビゲーション

典型的なページナビゲーションは以下のようなものです:

  1. ユーザーがリンクをクリック
  2. データのリクエストが行われる
  3. レスポンスでDOMが更新される

このフローにビューの遷移を適用するには、いくつかの考慮点があります。

まず、スクリーンがフリーズ状態にある時間を最小化することです。ビューの遷移が開始されると、コールバックが完了するまでDOMがインタラクティブでなくなることに気付いているかもしれません。ユーザーがリンクをクリックしたときに遷移を開始すると、UIがフリーズした状態で長く待つ可能性があります。この不快さを最小化するために、理想的には document.startViewTransition はリクエストが完了した後に呼び出されるべきです。そうすれば、変更の準備ができており、DOMをできるだけ迅速に更新できます。

次に、DOMを更新する前に初期DOMスクリーンショットがキャプチャされていることを確認する必要があります。サードパーティのフレームワークでページナビゲーションを操作する場合、レンダリングプロセスに完全に制御できません。レスポンスが受け取られるとDOMが自動的に更新されます。したがって、DOMの更新をきれいに実行する document.startViewTransition に渡すことができるスタンドアロン関数がありません。レンダリングをインターセプト、一時停止、再開して、DOMを更新する単一の関数を持つという仮想を作成する必要があるかもしれません。

運良いことに、DOM更新コールバックからpromiseを返す場合、ビューの遷移APIはそのresolveを待ってからアニメーションを実行します。この機能を使用して、上述のタイミング問題を処理できます。

React コンポーネント例

上記の問題に対処するため、関数型コンポーネントと比較してフローを説明しやすいため、Reactクラスコンポーネントを作成します。レンダリングを制御するために、以下のライフサイクルメソッドを使用します:

  • shouldComponentUpdate: ここで false を返し、ビューの遷移を開始します。これでスクリーンショットキャプチャが完了する時間を確保します
  • forceUpdate: スクリーンショットキャプチャ後にコンポーネントを手動で再レンダリング
  • componentDidUpdate: DOMが更新されたことをビューの遷移APIに通知

以下の実装例です:

import { Component } from "react";

export default class ViewTransition extends Component {
  shouldComponentUpdate() {
    if (!document.startViewTransition) return true; // サポートされていない場合はスキップ

    document.startViewTransition(() => this.#updateDOM());
    return false; // コンポーネントを更新しない。手動で行う
  }

  #updateDOM() {
    // スクリーンショットが取得されたことがわかっているので、強制的にレンダリングできます
    // (`shouldComponentUpdate` をスキップ)
    this.forceUpdate();
    // コンポーネントがレンダリングされるときにresolveするpromiseを設定
    return new Promise((resolve) => {
      this.#rendered = resolve;
    });
  }

  render() {
    return this.props.children;
  }

  #rendered = () => {};

  componentDidUpdate() {
    // `updateDOM` promiseをresolveしてビューの遷移APIに
    // DOMが更新されたことを通知
    this.#rendered();
  }
}

注: 執筆時点の Next.js App Router ベータ版であり、それに関するベストプラクティスとpagesディレクトリは変更される可能性があります。

Next.jsアプリで使用するには、まず開発でReactストリクトモードを無効化します。ストリクトモードはコンポーネントを2回レンダリングしてチェックを実行します。これは開発での ViewTransition レンダリングフローに干渉するため、グローバルに無効化し、 StrictMode コンポーネントで子コンポーネント用に再度有効化します。

// next.config.js
const nextConfig = {
  reactStrictMode: false,
};

module.exports = nextConfig;

次に、 pages/_app.js で、 ComponentViewTransitionStrictMode コンポーネントでラップしると、アニメーション化された遷移が表示されるようになります:

// pages/_app.js
import "@/styles/globals.css";
import { StrictMode } from "react";
import ViewTransition from "@/components/ViewTransition";

export default function App({ Component, pageProps }) {
  return (
    <ViewTransition>
      <StrictMode>
        <Component {...pageProps} />
      </StrictMode>
    </ViewTransition>
  );
}

Next.jsデモンストレーションライブNext.jsデモとそのソースを確認してください。

: React ドキュメントでは shouldComponentUpdateforceUpdate の使用に警告し、パフォーマンス最適化にのみ使用し、 shouldComponentUpdate が呼び出されることは保証されないと述べています。ページアニメーションは拡張機能であり、このコンポーネントは shouldComponentUpdate が呼び出されなくても動作するため、この注意は許容可能です。

View Transitionsを使用しない別のアプローチ

ページ遷移のためのView Transitions APIの必要な欠点の1つは、アニメーション化する前に新しいページHTMLが必要であることです。これには時間がかかり、リンククリック後のユーザーにフィードバックがありません。スピナーが隙間を埋める可能性がありますが、ユーザーがリンクをクリックするとすぐに要素をアニメーション化し、HTMLが到着したときに新しいHTMLをアニメーション化することで時間を稼げます。これは標準的なiOSナビゲーションが次の画面を読み込みながら即座にスライドする方法に似ています。

  1. ユーザーがリンクをクリック
  2. 要素はアニメーション化されます。その間、データのリクエストが行われます
  3. レスポンスとアニメーションの両方が完了するまで待機
  4. レスポンスをアニメーション化

このアプローチとView Transitions APIのアプローチの主な違いは、アニメーション化を実行するときに新しいHTMLを持っていないため、ある状態から次の状態への要素を 遷移 できないことです。

どちらのアプローチも状況に応じて有用です。例えば、あるページから次のページへの共有要素がある場合は、ビューの遷移を選択する可能性がありますが、変更が大きく共有要素が少ない場合は、終了アニメーションの即座のフィードバックの恩恵を受ける可能性があります。

これを実装するには、ルーティングイベントにフックイン必要があります。これは使用しているフレームワークまたはライブラリに依存します。特に、ユーザーが移動しているときに通知される必要があります。Next.jsでは、routeChangeStart ルーターイベントを使用して終了アニメーションを開始できますが、Next.js、React、または完全なクライアントレンダリングHTMLなし _でどのようにこれを達成するかを見てみましょう。

Turbo と Turn を使用したサーバーサイドレンダリング、マルチページアプリケーションのアニメーション化

: View Transitions APIがマルチページナビゲーション(つまりJavaScriptなし)で動作する計画があります。しかし、JavaScriptのAPIはより高度な遷移に必要かもしれません。

Hotwireライブラリスイートの一部である Turbo (Vercel's Turbo と混同しないでください)は、マルチページアプリケーション(MPA)をプログレッシブに拡張するレンダリングアプローチを提供します。完全にクライアントレンダリングされたアプリケーションとしてコードを構築することなくSPA速度を達成することを目的としており、リンククリックとフォーム送信をキャプチャし、JavaScriptでリクエストを実行し、 <body> をレスポンスからの新しい <body> に置き換えることでそうします。このように、ハイブリッドアプローチです。HTMLはサーバーで生成されますが、DOMはJavaScriptで更新されます。

Turn はTurboを使用してページナビゲーションをアニメーション化するためのライブラリです。両方のアニメーションアプローチをサポートしています(ただし、現在ビューの遷移は試験的です)。Turnは適切なタイミングで <html> 要素に turn-before-exitturn-exit、および turn-enter クラスを追加し、開発者がアニメーションをカスタマイズする方法を提供します。

それを機能させるには、アニメーション化したい要素に data-turn-exit および data-turn-enter 属性を追加し、CSSスタイルを適用します。例えば、フェードイン/フェードアウトの場合:

html.turn-exit [data-turn-exit] {
  animation-name: fade-out;
  animation-duration: 0.3s;
  animation-fill-mode: forwards;
}

html.turn-enter [data-turn-enter] {
  animation-name: fade-in;
  animation-duration: 0.6s;
  animation-fill-mode: forwards;
}

@keyframes fade-out {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

次に、アプリケーションのJavaScriptに Turn ライブラリをインポートし、 Turn.start() を呼び出します。

これはTurboのレンダリングイベントにフックイン、必要に応じてフローを制御することで機能します:

  1. turbo:visit: リクエスト開始直前に turn-exit クラスを追加
  2. turbo:before-render: リクエスト完了後だが新しいHTMLレンダリング前(Reactの shouldComponentUpdate に類似)、レンダリングを一時停止して終了アニメーション完了を待機
  3. turbo:render: 新しいHTMLがレンダリングされたら、 turn-exit クラスを削除して turn-enter クラスを追加
  4. 終了アニメーションが完了したら、 turn-enter クラスを削除

Turnはビューの遷移に対する実験的なサポートもあり、 Turn.config.experimental.viewTransitions = true を設定することで有効化されます。これはサポートされている場所でビューの遷移を使用し、CSSアニメーションアプローチにフォールバックします。

まとめ

ページ遷移は、あるページから次のページへの変更を伝達するのに優れた方法です。新しい組み込みビューの遷移APIは、古い状態と新しい状態が提供されるときに複雑な遷移を実行できます。フレームワークイベントにフックインすることで、これらの状態変更をAPIに伝達できます。ページナビゲーションの場合、理想的には遷移がリクエスト完了後に発生し、DOMが非アクティブ状態にならないようにする必要があります。

別の(または補完的な)アプローチは、ユーザーがリンクをクリックするとすぐに終了アニメーションを実行することです。これには、新しいHTMLが到着する前にリクエストが完了するまでの時間を確保できるという利点があります。

出典

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
patternsdev
リポジトリ
patternsdev/skills
ライセンス
MIT
最終更新
不明

Source: https://github.com/patternsdev/skills / ライセンス: MIT

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: patternsdev · patternsdev/skills · ライセンス: MIT