ui-animation について
インターフェースアニメーションの設計、実装、レビュー、デバッグや、録画からの動きの測定に使うスキルです。目的とアクセシビリティを重視し、パターン、タイミング、性能、実装の参考情報を備えています。
主な機能
- 01UIモーションの設計とデバッグ
- 02動きを加える箇所の発見とレビュー
- 03動きの測定とカーブフィッティング
- 04CSS、WAAPI、JS の実装指針
- 05操作性とアクセシビリティの原則
活用シーン
- 01ボタン、メニュー、モーダルの遷移調整
- 02遅い、または跳ねる動きの原因調査
- 03録画を基にした動きの再現
- 04アニメーションコードの操作性レビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nexu-io/ open-design --skill ui-animationインストール後、Claude Code で/ui-animationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSESOURCES.mdreferences/choreography.mdclip-path-techniques.mdcode-output.mdcomponent-patterns.mdcontextual-animations.mdcurve-fitting.mddebugging-symptoms.mddecision-framework.mdgesture-drag.mdinterface-sfx.mdmeasurement-guide.mdperformance-deep-dive.mdreview-format.mdscroll-animations.mdspring-animations.mdsvg-animation.mdtransition-recipes.mdvocabulary.mdscripts/extract_frames.pyfit_curves.pytrack_motion.py詳細
UIアニメーション
Open Design の実行コンテキスト
ユーザーの現在のインターフェースまたは承認済みのブリーフに対する機能的な補助として使用してください。ホストのタスクルート、現在のステージ、ツールの利用可否、出力契約を維持してください。プランニングでは動きを記述し、実装はホストのオーサリングステージでのみ行います。ホストが許可していないレビュー、録画、レンダリング、承認のフェーズを追加しないでください。プロジェクトで既に使われているスタックとモーショントークンを再利用してください。補助スキルは任意です。インストールされている場合にのみ使用し、そうでない場合はツール呼び出しを捏造せず、ここに記載された関連ガイダンスを適用してください。実際に観測した場合にのみ測定値を報告し、視覚的な推定値や実施できなかった確認は明示してください。
- 該当する作業: UIモーション(スプリング、ジェスチャー、ドラッグ、イージング、CSSトランジション、キーフレーム、Motion)の設計、実装、レビュー、デバッグ、モーションが本当に役立つ場面を見つけるためのインターフェースの確認、録画からモーションを測定して(フレーム抽出、トラッキング、曲線のフィッティング)、コードと引き継ぎ用仕様を作成すること、説明されたモーション効果の名称を特定すること(逆引き用語検索)、疎なインターフェースサウンドの使用可否を判断すること。
- 該当しない作業: 全体的なビジュアルの方向性、配色、タイポグラフィの選定(
ui-designの Direction モードを使用)、ページ全体の UI 品質の監査(ui-designの Audit モードを使用)、名称が指定されたテキスト効果の仕様策定(インストールされている場合は、外部のanimate-textスキルを使用)。
参照ファイル
| ファイル | 読むタイミング |
|---|---|
| references/decision-framework.md | 基本:アニメーションを使うかどうか・その理由の判断、イージングの特性の選択。また、「どこをアニメーションさせるべきか」を探るディスカバリー調査 |
| references/spring-animations.md | スプリング物理、Motion useSpring、スプリングパラメーターの設定、Appleの減衰値・応答値、開くときと閉じるときで異なる動きの特性、中断の仕組み |
| references/component-patterns.md | ボタン、トースト、クロスフェード、リストの段階的表示と削除、ホバー、ステップ形式のフォーム、Motionのレイアウトモーフィングと自動高さ、3D |
| references/clip-path-techniques.md | 表示、タブ、長押しでの削除、比較スライダーに使うclip-path |
| references/gesture-drag.md | ドラッグ、スワイプで閉じる動作、慣性、ポインターキャプチャ、速度の引き継ぎ、慣性の投影、回転ダイヤル/ノブのドラッグ、デテント、カルーセルのtouch-action |
| references/scroll-animations.md | スクロールをトリガーにした表示、スクロールに連動したアニメーション(animation-timeline、useScroll)、視差効果、スティッキー要素を使ったスクロールストーリーテリング、スクロールアニメーションを使うべきでない場合 |
| references/performance-deep-dive.md | カクつき、CSSとJS、WAAPI、CSS変数の落とし穴、Framer Motionの注意点 |
| references/debugging-symptoms.md | アニメーションに違和感があるものの、原因が特定できない場合:もたつく、ロボットのよう、安っぽい、跳ねる、意図どおりに動かないといった動きの症状別テーブル |
| references/svg-animation.md | ベクター画像のアニメーション:線の描画(stroke-dashoffset)、SVGのtransform-originの落とし穴、パスのモーフィング、揺れ、環境に馴染む動き |
| references/review-format.md | アニメーションコードのレビュー:10の基準(それぞれに一目でわかる警告サイン)、変更前/変更後/理由のテーブル、ブロック/承認の判定 |
| references/contextual-animations.md | 状況に応じたアイコンの切り替え、単語単位で段階的に表示するアニメーション、周辺要素の強調を弱める動き、固定オフセットでの退出 |
| references/transition-recipes.md | CSSトランジションの導入:コンテナーのモーフィング、カードのリサイズ、バッジ、ドロップダウンとツールチップ(ライブラリ由来の変数を含む)、モーダル(@starting-styleを使った表示)、パネルとドロワー、ページスライド、アイコンの切り替え、数値のポップイン、オドメーター風のロール、テキストの切り替え、成功、アバターのホバー、エラー時の揺れ |
| references/measurement-guide.md | リバースエンジニアリング:測定対象、目視とスクリプト、metrics.jsonの読み方、ROIの選択 |
| references/curve-fitting.md | リバースエンジニアリング:fit_curves.pyの出力の読み方、スプリングとベジェ、フィッティング誤差の評価、開くときと閉じるときの非対称性 |
| references/code-output.md | リバースエンジニアリング:CSS、Motion/Framer Motion、SwiftUI、React Native、UIKit向けのコード生成 |
| references/choreography.md | リバースエンジニアリング:複数要素・複数フェーズの動き:段階的な表示、移動前のぼかし、エッジごとの収束 |
| references/vocabulary.md | ユーザーが曖昧に表現した動きの効果の名称を特定する(「あの動きは何て呼ぶの?」) |
| references/interface-sfx.md | クリック音、インターフェースの音声、UI効果音、触覚フィードバックと音の組み合わせ、または「なぜウェブでは音が敬遠されるのか」 |
基本ルール
- フィードバック、方向感、連続性、または意図的な楽しさを伝えるためにアニメーションを使います。「見た目がかっこいい」というだけで、ユーザーが頻繁に目にするものには使いません。
- キーボードフォーカスと繰り返し行うナビゲーションは即座に応答させます。フォーカスやタスクの完了を待たせないのであれば、状態遷移をアニメーションさせてもかまいません。
- 中断可能な UI には CSS トランジションを優先します。キーフレームは中断されると最初から再生されますが、トランジションは目標を切り替えます。キーフレームは、あらかじめ決められたシーケンスにのみ使います。
- 実装の優先順位は、CSS トランジション > WAAPI > CSS キーフレーム > JS(
requestAnimationFrame)です。負荷がかかっても CSS は滑らかに動作しますが、JS はフレーム落ちします。 - タイミングに変化をつけます。ときどき行われる操作では、表示を少し遅く、終了を速くできます。高頻度で一時的な UI(ホバーのハイライト、ポップオーバー、パネルの切り替え)では逆に、表示は即座に行い(0ms)、終了時には短くフェードさせます(100-150ms)。こうすることで、操作が即座に反映されたように感じられます。
- タップ可能なコントロールは
:activeで 0ms で押下状態にし、touch-action: manipulationを設定します。 - DOM への追加には
@starting-styleを使います。未対応の環境ではdata-mounted属性をフォールバックとして使います。 - 小さな
filter: blur(2px)を適用すると、コンテンツを入れ替える際の粗いクロスフェードが目立たなくなります。
モーションデザインの原則
- 瞬間移動より連続性を優先します。 両方の状態で表示される要素は、その場で遷移させます。新しい要素をフェードインさせるのではなく、要素がある位置から展開します。永続する要素を複製したり、コンポーネントを共有するビュー間をハードカットで切り替えたりしてはいけません。ハードカットでは空間的な文脈が失われます。
- 動く方向を位置に合わせます。 タブやカルーセルの遷移は、空間的なレイアウトに合った方向にアニメーションさせます(進むときは左から右、戻るときは右から左)。
- トリガーから現れるようにします。 オーバーレイ、トレイ、パネルは、それを開いた要素から外側に向かってアニメーションさせます。画面中央から汎用的に表示すると、空間的な方向感が損なわれます。形状が合う場合は、さらに望ましい方法として、トリガー自体をサーフェスに変化させます(コンテナーモーフのレシピを参照)。
- 隅ではなく、その場で結果を伝えます。 操作の結果は、その操作を引き起こしたコントロールに表示します。ボタンが「コピーしました」に変わり、その状態を保ってから元に戻るようにします。画面の反対側にトーストが表示されると、ユーザーは操作が成功したか確かめるため、たった今触れた要素から視線を移さなくてはなりません。画面上に発生元がない結果(バックグラウンドジョブの完了、受信メッセージなど)に限って、隅のトーストを使います。
- 対になる状態は一緒にアニメーションさせます。 開くときにアニメーションさせるなら、閉じるときもアニメーションさせます。ホバーに動きがあるなら、フォーカス時と押下時にも同等のフィードバックを与えます。繰り返し行う操作の片側だけを磨き込んではいけません。
- 操作の頻度が低いほど、楽しさを加えます。 まれな操作には個性を加え、高頻度の操作では動きを意識させないようにします。
- モーションで体感速度を高めます。 同じ読み込み時間でも、滑らかな遷移はハードカットより速く感じられます。
アニメーションさせる対象
- 動き:
transformとopacityのみを使用します。レイアウトとペイントをスキップできます。 - 状態のフィードバック:
color、background-color、opacityは使用できます。 - レイアウトプロパティ(
width、height、top、left)はアニメーションさせないでください。フレームごとにレイアウトの再計算が発生します。(例外:意図的なコンテナのアニメーション。カードのリサイズとコンテナのモーフィングのレシピを参照してください。) transition: allは使用しないでください。意図しないプロパティまでアニメーションし、将来追加されるプロパティも暗黙的に対象になります。対象を明示してください。- コアとなるインタラクションでは、
filterのアニメーションは避けてください。避けられない場合は、ぼかしを 20px 以下にしてください(強いぼかしは、特に Safari で処理コストが高くなります)。 - SVG:
<g>ラッパーにtransform-box: fill-box; transform-origin: centerを適用してください。これがないと、キャンバスの原点を中心に回転/拡大縮小されます。線の描画、パスのモーフィング、Motion の SVG 原点オーバーライドについては、references/svg-animation.md を参照してください。 transform: scale()は子要素(アイコン、テキスト、枠線も比例して拡大縮小されます)も拡大縮小します。width/heightとは異なり、押下時のフィードバックには便利ですが、内側の要素を固定サイズにする必要がある場合は考慮してください。- テーマの切り替え中はトランジションを無効にしてください(
[data-theme-switching] * { transition: none !important })。そうしないと、テーマに関連するすべてのプロパティが一斉にアニメーションします。切り替え後に再フローを強制し(void document.body.offsetHeight)、次のフレームでオーバーライドを削除するか、next-themesのdisableTransitionOnChangeを使用してください。
イージングのデフォルト値
| 要素 | 期間 | イージング |
|---|---|---|
| ボタン押下時のフィードバック | 100-160ms | cubic-bezier(0.22, 1, 0.36, 1) |
| ツールチップ、小さなポップオーバー | 125-200ms | ease-out またはエントリーカーブ |
| ドロップダウン、セレクト | 150-250ms | cubic-bezier(0.22, 1, 0.36, 1) |
| モーダル、ドロワー | 200-350ms | cubic-bezier(0.22, 1, 0.36, 1) |
| 画面上の移動/スライド | 200-300ms | cubic-bezier(0.25, 1, 0.5, 1) |
| ページ遷移 | 250-400ms | エントリーカーブまたは移動カーブ |
| ホバー(色/不透明度)、単一コントロール | 200ms | ease |
| ホバー(transform/scale) | 100-150ms | エントリーカーブ |
| イラスト/マーケティング用途 | 最大 1000ms | スプリングまたはカスタム |
通常の UI は 300ms 未満にしてください。距離に応じて期間を調整します(全画面のスライドは 300ms を超えてもかまいませんが、ツールチップの 6px の移動は 150ms 未満にします)。
名前付きカーブ
- エントリー: 登場時や transform ベースのホバーには
cubic-bezier(0.22, 1, 0.36, 1)を使用します - 移動: スライド、ドロワー、パネルには
cubic-bezier(0.25, 1, 0.5, 1)を使用します - ドロワー(iOS 風):
cubic-bezier(0.32, 0.72, 0, 1)(開始が非常に急で、500ms でも遅く感じない理由です) - Expo out: 大胆な表示、カードのホバー、テキストの表示には
cubic-bezier(0.19, 1, 0.22, 1)を使用します - 押下: ボタン押下時のフィードバックには
cubic-bezier(0.25, 0.46, 0.45, 0.94)を使用します - 画面上の移動: 画面内にとどまる往復移動には
cubic-bezier(0.645, 0.045, 0.355, 1)を使用します
UI では ease-in を避けてください。動き始めが遅いため、要素がユーザーの操作に遅れて追従し、もたついて感じられます。加速が緩やかで、きびきびした印象ではなく柔らかい印象になる組み込みの ease/ease-out よりも、easing.dev のカスタムカーブを優先してください。
トランジションの選択ルール
まず UI 要素を照合し、次に references/transition-recipes.md からレシピを選びます。
| UI パターン | レシピ |
|---|---|
| トリガー+浮かぶドット/件数 | 通知バッジ |
| トリガーが、開くサーフェスへと拡大する | コンテナのモーフィング |
| トリガー+位置が固定されたサーフェス | メニューのドロップダウン |
| ページの前面に表示される中央配置のサーフェス | モーダルダイアログ |
| 既存のコンテナ内へスライドするパネル | パネルの表示 |
| リスト↔詳細、またはウィザードのステップ | ページの左右スライド |
| 要素の寸法が変化する | カードのサイズ変更 |
| テキストがその場で更新される | テキスト状態の切り替え |
| 同じスロットにある2つのアイコン | アイコンの切り替え |
| 単独で現れる数字 | 数字のポップイン |
| ユーザーが操作して変化させる数字 | オドメーター式の数字スクロール |
| 確認/成功の瞬間 | 成功の演出 |
| 横並びのスタックでホバーされた項目 | アバターグループのホバー |
| フォームの入力エラー | エラー状態のシェイク |
デザイン上 JavaScript によるオーケストレーションが必要な場合を除き、オーバーヘッドの小さいトランジション(CSS のみ)を優先します。
空間とシーケンス
- ポップオーバーの
transform-originはトリガーの位置に設定します(モーダルはcenterのままにします)。ダイアログ/メニューの表示アニメーションはscale(0)ではなくscale(0.9-0.96)から開始します(小さなポップオーバーは範囲の下限、ダイアログ全体のような大きなものは上限にします。大きなサーフェスは絶対ピクセル数で大きく移動するためです)。スタッガーは30〜50ms(合計300ms未満)とし、最も重要な要素を先に動かします。詳細なルールとコードは references/transition-recipes.md と references/contextual-animations.md を参照してください。 - ペア要素のルール: 一緒にアニメーションする要素(モーダル+オーバーレイ、ツールチップ+矢印、FAB+ラベル)は、同じイージングと時間を設定する必要があります。タイミングの不一致は、「何か違和感がある」と感じる原因としてよくあります。
アクセシビリティ
- ホバー(動きと描画)は
@media (hover: hover) and (pointer: fine)の内側に限定するか、タッチデバイスではタップでホバーを再現します。ゲートを追加する前に生成された CSS を確認してください。Tailwind v4 ではhover:がすでに@media (hover: hover)で囲まれています。 - 直接操作中は、イージングをかけずに要素をポインターに追従させます。イージングは操作後にのみ追加します。
- インターフェースの効果音は任意です。控えめに使い、ジェスチャーによるロック解除後に再生し、確認音に限定します。references/interface-sfx.md を参照してください。
パフォーマンス
IntersectionObserverを使って、画面外ではループアニメーションを一時停止します。見えない状態でも GPU を消費します。will-changeは負荷の高い動きがある間だけtransform/opacityに対して有効にし、終了後に解除します。レイヤー昇格のたびにコンポジターのメモリを消費します。多数の要素を恒久的に昇格させるのは、まったく昇格させない場合よりも悪影響があります。- コンテナ上の CSS 変数を使ってドラッグをアニメーションさせないでください。更新のたびにすべての子要素のスタイルが再計算されます。移動する要素に直接
transformを設定してください。 - 軸方向の移動やドラッグには、Motion の
x/y値がデフォルトで適しています(React の再レンダリングを回避できます)。複数の transform 関数を1つの所有者が組み合わせる必要がある場合、Motion 以外のコードと相互運用する場合、またはメインスレッドが混雑している状況でも滑らかに動かす場合は、完全なtransform文字列を使用します。省略形はrequestAnimationFrame上で実行され、動きがナビゲーション、データ読み込み、ハイドレーションと重なるとフレームが落ちます。そのような状況でも CSS/WAAPI は滑らかさを保ちます。 - 動きがときどきカクつく(表示時、ナビゲーション中、データの反映中)場合、原因はたいていアニメーション自体の負荷ではなく、同じティックで実行される長時間タスクです。アニメーションの開始と負荷の高い処理を同じティックで実行しないでください。先に動きを開始して、1フレーム描画されてから処理を行うか、
transitionendまで処理を延期します。 - WAAPI、コンポジティングレイヤー、アニメーション中の長時間タスク、CSS と JS の比較表については、references/performance-deep-dive.md を参照してください。
アンチパターン
上記で取り上げていない、重大な失敗例:
- ユーザーの操作なしにマウント時にアニメーションさせる:予期しない動きはユーザーを戸惑わせます。ユーザーは何もしていないのに動くためです。
- ドラッグの境界で急停止させる:動作が壊れているように感じられます。境界を越えると動きが弱まるように、摩擦や減衰を適用してください(gesture-drag のリファレンスを参照)。
- コンテナーとその子要素の両方をスタガー表示でアニメーションさせる:コンテナーごとに、表示時のアニメーションは1つ選びます。パネルがスライドインするなら、到着時には内容がすでに表示されている必要があります。
- グループ内で最初のツールチップが開いた後もアニメーションさせる:以降のツールチップは即座に開くようにしてください。そうしないと、ツールバーの動作が遅く感じられます。
- 製品 UI、ファーストビューのコンテンツ、またはページ内のすべてのセクションをスクロールに合わせて表示する:スクロールに連動した表示は、マーケティング画面で選んだ少数の場面に限って一度だけ実行し、上方向へのスクロールでは再アニメーションさせないでください(references/scroll-animations.md を参照)。
- スクロール位置に連動するモーションにイージングや時間を設定する:スクロール位置が時間軸なので、カーブや時間を設定するとスクロールバーに遅れて動きます。ここでは
linearを指定し、時間を設定しないのが正解です。 - CSS だけで動きを軽減する設定を処理する:Motion の JavaScript 駆動アニメーションは
@media (prefers-reduced-motion)ブロックを無視するため、CSS 側の制御がレビューに通っても、空間移動のアニメーションは実行されます。アプリを<MotionConfig reducedMotion="user">でラップするか、useReducedMotion()を使って分岐してください。逆に、軽減設定時にグローバルな* { transition: none !important }を適用する過剰な対応も、動きを軽減しても維持される不透明度や色のフィードバックまで取り除いてしまいます。 - 新しい作業に
framer-motionをインストールする:現在のパッケージ名はmotionで、React のインポート元はmotion/reactです。古いパッケージも引き続き解決されるため、コードベースに新旧が混在していてもコンパイルは成功し、ライブラリが2つ同梱されてしまいます。
ワークフロー
コピーして記録してください:
Animation progress:
- [ ] Step 1: Decide whether the interaction should animate
- [ ] Step 2: Choose purpose, easing, and duration
- [ ] Step 3: Pick the implementation style
- [ ] Step 4: Load the relevant component or technique reference
- [ ] Step 5: Validate timing, interruption, and device behavior
- references/decision-framework.md にある4つの質問に答えます:アニメーションさせるか?目的は何か?イージングは?速度は?
- 上記のイージングのデフォルト表から時間を選びます。値に意見が分かれる場合は、実際のコンポーネントを使い、DevTools のベジェエディター(Chrome または Firefox。Safari にはありません)でリアルタイムに調整します。その後、リテラル値を他の時間定数の横にソースコードへ貼り付けます。DevTools での編集はページ遷移時に失われるためです。
- 実装方法を選びます:CSS transition > WAAPI > spring > keyframe > JS。
- コンポーネントまたは手法に対応するリファレンスを読み込みます。
- レビュー時は references/review-format.md にある厳格な進め方に従います:10項目の基準と照らし合わせ、Before/After/Why の表を出力した後、Block/Approve の判断で締めくくる段階別の評価を提示します。
検証
各チェックについて、証拠を提示してください(「問題なさそう」ではなく、DevTools での観察結果):
- 差分を grep し、レイアウトプロパティのトランジション(
width、height、top、left)とtransition: allがないか確認します。 - コンポーネントをすばやく繰り返し切り替え、トランジションがゼロから再開するのではなく、新しい状態へ向けて遷移することを確認します。
- DevTools の Animations パネルで速度を10%に落とし、通常速度では気づきにくいタイミングや
transform-originの問題を見つけます。 will-changeがアニメーションの前後で切り替わり、常時設定されていないこと、およびループするアニメーションが画面外で一時停止することを確認します。- 実機でタッチ操作をテストします。シミュレーターでは、ジェスチャーやタップ時のホバーに関する問題が過少に現れます。
prefers-reduced-motionを尊重します:空間移動を即時の状態変化、または控えめなフェードに置き換えます。ループする装飾はanimation-play-state: pausedで一時停止します(display: noneで無理に消さないでください)。ユーザーが明示的に起こした操作へのフィードバックは維持します。そのモードで同じタスクを実行して確認します。
発見ワークフロー
「どこをアニメーションさせるべきか」については、references/decision-framework.md の Discovery スイープを実行します。目的と使用頻度に裏付けられた機会と、採用しなかった機会を報告します。実装が作業範囲に含まれる場合にのみ、提案を実装します。
リバースエンジニアリングのワークフロー
このブランチを使って、画面録画から既存のアニメーションを測定し、それを再現するコードと引き継ぎ仕様を作成します。scripts/ 以下のスクリプトが、標準となる決定論的な手順です。ロジックを再構築せず、スクリプトを実行してください。
以下のすべての scripts/ コマンドは、アプリケーションの作業ディレクトリではなく、インストール済みのスキルディレクトリを基準に実行してください。
依存関係: 計測スクリプトを実行する前に、ffmpeg/ffprobe と、opencv-python、numpy、scipy を含む Python 環境があることを確認してください。これらが Open Design によってインストールされているとは限りません。利用可能な分離された Python 環境を再利用してください。依存関係のセットアップを行う場合は、ホストの認可要件に従ってください。ffmpeg だけが利用可能な場合は、フレームを抽出し、分析結果は視覚的な推定であることを明記してください。メディアを検査できない場合は、不足している機能を明記してください。計測したタイミング、フィッティングした曲線、録画との比較を行ったと主張してはいけません。古いフレームがコンタクトシートに混入しないよう、抽出のたびに新しいタスク専用の出力ディレクトリを使用してください。以下のスクリプトは任意の計測ツールであり、通常のインターフェースアニメーションの実装に必須ではありません。
Reverse-engineer progress:
- [ ] Step 1: Extract frames + contact sheet (per direction if open differs from close)
- [ ] Step 2: Vision pass: identify element, effects, phases
- [ ] Step 3: Decide precision (eye-only vs scripted)
- [ ] Step 4: Track motion and fit curves (if escalating)
- [ ] Step 5: Annotate choreography (delays, asymmetry)
- [ ] Step 6: Emit code for the target(s)
- [ ] Step 7: Validate against the recording
- 抽出。
python3 scripts/extract_frames.py <video> <outdir>を実行します。--start/--durationでトランジションだけに絞り込みます。インタラクションに開く動作と閉じる動作の両方がある場合は、2つの区間を切り出し、方向ごとにパイプラインを1回ずつ実行してください(ほとんどの場合、互いに鏡像にはなりません)。--fpsをソースのフレームレートに合わせてください(ffprobeで確認します)。ソースのフレームレートを超えてサンプリングしてはいけません。まずcontact_sheet.pngを開きます。 - 視覚的な分析。 動く要素、すべての効果(移動、スケール変化〔異方的なことがよくあります〕、不透明度、ぼかし、角丸、影、色)、および各フェーズを特定し、どのプロパティが先行し、どれが遅れるかを記録します。
references/measurement-guide.mdのチェックリストを使用してください。 - 精度の判断。 単純なフェードや線形スライドの場合は、コンタクトシートからタイミングを読み取り、ステップ5に進みます。弾む動き、バネのような動き、複数プロパティの動きの場合は、ステップ4に進みます(バネの動きを目測するのは信頼できません)。
- 追跡とフィッティング。
python3 scripts/track_motion.py <outdir>を実行してmetrics.jsonを生成します(要素を1つに絞り込むには--bbox X,Y,W,Hを指定します)。次にpython3 scripts/fit_curves.py <outdir>/metrics.jsonを実行して、バネのパラメーター、三次ベジェ曲線、プロパティごとのフィッティング誤差を取得します。抽出時と同じ--fpsを指定してください。モデルの選択にはreferences/curve-fitting.mdを参照してください。両方のモデルで誤差が大きい場合は、複数フェーズの動きです(区間に分割して、それぞれフィッティングします)。 - 注釈付け。
references/choreography.mdを読み込みます。各プロパティが開始し、収束するタイミングを記したタイミングオフセット表を作成します。先行・遅延の間隔と過伸展の持続は、単一の曲線よりも動きの印象に大きく影響します。 - 出力。 対象に合わせて
references/code-output.mdのテンプレートにフィッティングしたパラメーターを当てはめます。動きはtransform/opacityで表現してください。開く動作と閉じる動作が異なる場合は2つのトランジションを出力し、動画なしで実装できるよう、統合した引き継ぎ仕様も出力します。 - 検証。 導出し直して確認します。出力したアニメーションを再生して画面録画し、その動画を
extract_frames.pyに再度通して、コンタクトシートを並べて比較します。0.1倍速にして、フェーズの順序と過伸展が保たれていることを確認します。コードがアニメーション化するのはtransform、opacity、filterだけであることを確認してください。
リバースエンジニアリング時の注意点:
fit_curves.pyのデフォルトは--fps 30です。60 fps で抽出しても、デフォルトのままフィッティングすると、すべてのduration_msが2倍になり、フィッティングされた剛性は4分の1に低下します。フィッティングには必ず抽出時の fps を指定してください。- ソースのフレームレートを超えてサンプリングすると、重複フレームが発生します。24 fps の GIF を 60 fps で抽出すると、
metrics.jsonに平坦な区間が生じ、フィッティング誤差が大きくなります。ソースのフレームレートを確認し、それに合わせてください。 - 画面録画ではフレームが欠落することがあり、iOS/QuickTime のキャプチャは可変フレームレートです。連続して同一の行がある場合は、一時停止ではなく重複フレームです。平坦な区間が多い場合は、より安定したフレームレートで再録画してください。
- 開く動作と閉じる動作は別々のクリップとして計測し、曲線を2つ報告してください。1つの曲線をフィッティングして逆再生して使い回してはいけません(
references/choreography.mdを参照)。フィッティングのerrorが 0.08 を超える場合は、信頼性に疑いがあるものとして扱ってください。
関連スキル
product-design:存在する状態、アクションが影響する対象、元に戻せるかどうかを扱います。ジェスチャーによってコントロールが置き換わる場合は、まずこちらを参照してください。スワイプで削除したり、長押しで確定したりする操作は、動き方を変える前にユーザーができることを変えるためです。ui-designの方向性モード:ビジュアルの方向性、配色、タイポグラフィを扱います。モーションを調整する前に、ビジュアルシステムを固めてください。ui-designの監査モード:ページ/機能レベルの UI 品質監査を扱います。モーションの仕上げと修正はこちらで行います。- インストールされている場合は、外部の
animate-textスキルを任意で利用できます。名前付きのテキストエフェクト(タイプライター、行の表示、段階的な表示)を、正確な JSON 仕様とともに提供します。
上流の評価フィクスチャは、このランタイムバンドルには含まれていません。ソースおよび適応の詳細は SOURCES.md に記録されています。