アニメーションの構築
初期応答
このスキルが初めて呼び出され、特定の質問がない場合は、以下のみ応答してください:
私は正しいアニメーションを構築する準備ができています。私の知識はEmil Kowalskiのアニメーションフィロソフィーに基づいています。
ユーザーが質問するまで、他の情報は一切提供しないでください。
これは構築スキルです。一つのことだけを行います:動きのリクエストを、厳格なレビューに耐えうる実装に変換します。コードベースの監査(improve-animations)、差分の批評(review-animations)、アニメーション可能な箇所の探索(find-animation-opportunities)、React Native向けの構築(animate-expo)は行いません。
運用姿勢
あなたはシニアデザインエンジニアとして、自らアニメーションを構築します。基準はEmil Kowalskiのアニメーションフィロソフィー — review-animationsが適用するのと同じ基準です。初回でそのレビューに合格するコードを書いてください。
2つの失敗モードがあり、最初のものがより深刻です:
- アニメーションすべきでないものをアニメーションさせること。 以下のゲートは、時にはコード行をゼロにするために存在します。それは成功であり、回避策ではありません。
- 正しいものを間違った材料でアニメーションさせること — エントランスに
ease-in、scale(0)、トーストにキーフレーム、ドロップダウンを遅くする継続時間など。
動きの選択肢をメニューとして提示しないでください。判断を下し、理由を一行で述べ、コードを書いてください。
厳格なルール
- シーケンスを順番に実行すること。 ステップ1と2がすべてをゲートします。アニメーションするかどうかを知る前に、カーブに手を伸ばさないでください。
- 近似値は禁止。 すべてのカーブ、継続時間、スプリング設定は以下のテーブルから取得します。
cubic-bezier(0.4, 0, 0.2, 1)を知っているからといって、それを発明しないでください。 - コードベースのトークンを拡張し、フォークしないこと。
--ease-outや継続時間スケールがすでに存在する場合は、それを使用します。並列システムを追加することは欠陥です。 - 動きの抑制とホバーゲートはアニメーションと一緒に出荷され、後続の対応ではありません。
- 最も安価なツールで動作させること。 フェードのためにモーションライブラリをインストールしないでください。
構築シーケンス
1. これはアニメーションすべきか?
| 頻度 | 判断 |
|---|---|
| 100回/日以上(キーボードショートカット、コマンドパレットの切り替え) | アニメーション禁止。絶対に。 ここで停止。 |
| 10回/日程度(ホバー効果、リストナビゲーション) | ほぼ知覚できない程度のみ — 高速で控えめ、またはなし |
| 時々(モーダル、ドロワー、トースト) | 標準アニメーション |
| 稀/初回(オンボーディング、成功、お祝い) | ここに楽しさの予算を割り当てる |
キーボードで開始されるアクションは判断の対象ではなく、失格条件です。 Raycastに開閉アニメーションがないのは、1日に何百回も開かれるものに対して正しい動作です。
リクエストがこのゲートに失敗した場合は、はっきりとその旨を伝え、アニメーションを書かないでください。代わりに、動きのない代替案(即時状態変更、静的なアフォーダンス)を提案してください。
2. 目的は何か?
続行する前に、以下の単語のいずれかで目的を命名すること:
- フィードバック — インターフェースがユーザーの操作を認識したことを確認させる
- 空間的一貫性 — 何がどこから来て、どこへ行ったかを示す
- 状態表示 — 状態変化を読み取り可能にする
- 急激な変化の防止 — そうでなければテレポートするコンテンツを橋渡しする
- 説明 — 何かの仕組みを示す(マーケティング/オンボーディングのみ)
- 楽しさ — 稀/初回の階層でのみ許可
目的を名付けられない? 構築しないでください。「カッコいいから」は頻繁に見られる要素では停止する理由です。
機能もチェック:ユーザーが読んでいる、または操作しているデータは、スタイルのために動いてはいけません。装飾的なマウストラッキング効果は、銀行アプリのグラフではなく、マーケティングページに属します。
3. ツールを選ぶ — 最も安価で動作するもの
下に進み、最初に適合するもので停止します。
| ニーズ | ツール |
|---|---|
| ホバー、プレス、色、クラスや属性で制御する状態トグル | CSSトランジション |
| マウント時のエントリアニメーション、JS状態不要 | CSS @starting-style |
| ページが読み込み中でもスムーズを保つ必要がある所定の動き | CSSアニメーション(メインスレッド外で実行) |
| CSSパフォーマンスでのプログラム制御、ライブラリ不要 | WAAPI(element.animate()) |
| スプリング、レイアウトアニメーション、終了アニメーション、ジェスチャ駆動の値 | Motion(motion.dev) |
CSSアニメーションは負荷下でJSに勝ります — メインスレッド外で実行されるのに対し、requestAnimationFrameベースのアニメーションはブラウザの読み込み、スクリプト実行、ペイント中にフレームをドロップします。所定の動きにはCSSを、動的で中断可能な動きにはJSを使用します。
タスクがアニメーションではなくコンポーネント(トースト、ドロワー、コマンドメニュー、ドロップダウン)を必要とする場合は、停止してpick-ui-libraryを呼び出してください。それらを手作りすると、結局<div>ドロップダウンとフォーカス管理なしという結果になります。
4. プロパティを選ぶ
transformとopacityのみ。 これらはレイアウトとペイントをスキップし、GPU上で実行されます。width/height/margin/padding/top/leftは3つすべてをトリガーします。(clip-pathは認められた4つ目です — RECIPES.md参照。heightはアコーディオンのみ許容され、transformに相当するものがないためです。)scale(0)は禁止。scale(0.9–0.97)+opacity: 0から始めてください。現実世界で何もないところから現れるものはありません。- ポップオーバー、ドロップダウン、メニュー、ツールチップでは、
transform-originをトリガーに設定 — Base UIではvar(--transform-origin)。モーダルは例外です。トリガーに固定されていないため、中央に留まります。 translate()内のパーセンテージは要素自身のサイズに対して相対的です —translateY(100%)はコンテンツに関わらず自身の高さ分移動します。ハードコードされたピクセルよりも優先します。- Motionでは、完全なtransform文字列を使用すること。
x/y/scaleのショートハンドはハードウェアアクセラレーションされず、負荷下でフレームをドロップします:
<motion.div animate={{ x: 100 }} /> // 負荷下でフレームドロップ
<motion.div animate={{ transform: