Empro Labs Animation Skill
Webモーションデザインスキル。2つのステップで進めます:最初にモーション仕様(ANIMATION.md)を作成し、その後でコードを作成します。
ANIMATION.mdはプロジェクトに保存されるファイルです。手動で編集したり、他のプロジェクトで再利用したり、他のツールで読み込んだりできます。
このファイル内のパスはスキルフォルダー(~/.claude/skills/empro-labs-animation-skill/)を基準にしています。スクリプトを実行するときは絶対パスを使用してください。
リクエスト
スラッシュコマンドからのユーザーのリクエスト:
$ARGUMENTS
上記のリクエストが空の場合は、1つの質問をしてください:何を動かしたいのか、どこで動かしたいのか?その後、フェーズAを開始します。
コアフロー
フェーズA 入力を理解 ──→ フェーズB ANIMATION.mdを作成(ユーザー承認) ──→ フェーズC 実装 ──→ フェーズD 監査
起動時チェック(この順序で)
- プロジェクトに
ANIMATION.mdがあるか? → ユーザーの要求に応じて、それを再利用、編集、または再構築します。 DESIGN.md(web-designスキルから)があるか? → その色、フォント、スタイルの方向性を継承します。モーションをそれと一貫させます。- モーショントークン(
--motion-*変数やモーションファイル)があるか? → それらを再利用します。新しい値は発明しません。 - すでにアニメーションコードがあるか? → 先に
python scripts/analyze_motion.py <project> --inventoryを実行し、変更を提案する前に何が存在するかを把握します。 - 上記のいずれでもない場合 → フェーズA。
フェーズA:理解
入力は組み合わせ可能です:
| 入力 | 何をするか |
|---|---|
| 参照URL | python scripts/capture_motion.py --url [URL] --output ./motion-capture を実行します。実際の継続時間、イージング、アニメーションプロパティ、スクロール連動エフェクトについては capture.json を読みます。ムードについては top.png を使用します。 |
| モーションの動画またはスクリーンショット | トリガー、おおよその継続時間、イージングの感触を説明します。数値をユーザーに確認します。 |
| キーワード(「スナッピー」「シネマティック」) | references/motion-personalities.md のパーソナリティにマッチングします。 |
| ブランド名(「Linearみたいに」) | ライブサイトに到達可能ならキャプチャします。できない場合は、参照URLを尋ねます。記憶からブランドのモーションを推測しないでください。 |
| 既存コード | インベントリスクリプトを実行し、動作するものを維持します。 |
A1. パーソナリティ(最大2つの質問をする)
- 感触: 落ち着いた(calm)、スナッピー(snappy)、遊び心のある(playful)、またはシネマティック(cinematic)?
- ページタイプ: コンテンツ重視(モーションは邪魔にならない)またはショーケース(モーションが主役になれる)?
references/motion-personalities.md から1つか2つの候補を、それぞれ1行の理由とともに表示します。ユーザーが確認します。
A2. インタラクション層(必須、スキップしない)
references/interaction-tiers.md を参照。
| 層 | エクスペリエンス | ツーリング |
|---|---|---|
| L1 マイクロ | ホバー、フォーカス、プレス、トグル、小さな状態変化 | CSSトランジションのみ |
| L2 振り付け | 出現と消滅、スタッガーされたリスト、モーダル、ドロワー、ルート変更、ローダー | CSSキーフレーム、Web Animations API、またはGSAPタイムライン |
| L3 スクロールストーリー | スクロール連動表示、ピン留め、パララックス、タイムラインで駆動されるセクション | GSAP + ScrollTrigger、またはCSSスクロール駆動アニメーション(フォールバック付き) |
L3はページあたり2つのピン留めセクションに制限されます。各ページセクションは仕様書に自身の層を明記します。
A3. スタック
package.json とフレームワーク(プレーンHTML、React、Vue、Svelte、Next.js)を確認します。references/tooling.md を参考にツーリングを選択します。デフォルト:CSSとWeb Animations API。L3または複雑なタイムラインの場合のみGSAPを追加します。
フェーズB:ANIMATION.mdを作成
references/animation-md-template.md に従います。10のセクション:
- モーションパーソナリティと原則
- モーショントークン(継続時間、イージング、距離)
- 振り付けインベントリ(表:要素、トリガー、プロパティ、継続時間、イージング、遅延、動き軽減フォールバック)
- コンポーネントモーション(デフォルト、ホバー、フォーカス可視、アクティブ、無効、出現、消滅)
- スクロール動作
- ページおよびルート遷移
- パフォーマンス予算
- アクセシビリティ
- やるべきこととやってはいけないこと(少なくとも8項目、そのうち少なくとも5つは「やってはいけないこと」)
- 依存関係
サマリーをユーザーに表示し、承認を待ちます。その後、ANIMATION.md をプロジェクトルートに保存します。
フェーズC:実装
- トークンをどこでも使用。 すべての継続時間とイージングは
var(--motion-duration-base)のような変数です。コンポーネント内にマジックナンバーはありません。 - 軽量なプロパティのみをアニメーション。 まず
transformとopacity。clip-pathとfilterは小さな要素で許可されます。width、height、top、left、margin、paddingは、ANIMATION.md に理由とともに例外が記録されない限り、アニメーションさせないでください。 - 動きの軽減は最初のバージョンの一部であり、後からのパッチではありません。 動きは除去され、状態変化は維持されます。距離トークンは動き軽減下でゼロになり、
templates/motion-tokens.cssのprefers-reduced-motionブロックがそのパターンを示します。 - プロジェクトにまだモーションレイヤーがない場合は、スターターファイル
templates/motion-tokens.cssとtemplates/reveal.jsを使用します。 - ループには終了方法が必要。
infiniteアニメーションは動き軽減下で停止または簡略化されます。5秒以上実行されるループには一時停止コントロールが必要です。 - JavaScriptをクリーンアップ。 GSAPタイムラインとScrollTriggerはアンマウント時に削除します(
gsap.context()またはuseGSAPを使用)。Observerを切断し、リスナーを削除します。 - モーションを1箇所にまとめる。 トークンは1つのファイルに、レシピは小さなモジュールに配置します。タイミング値をコンポーネント全体に散らばせないでください。
フェーズD:監査
- 静的監査を実行:
python scripts/analyze_motion.py <project> --strict。すべてのエラーを修正します。すべての警告を確認し、修正するか、ANIMATION.md に理由を記録します。 - ブラウザチェックを実行:
- 動き軽減を有効にする(DevTools → Rendering →
prefers-reduced-motion: reduce)。動きが残っていないこと、コンテンツがまだ表示されていることを確認します。 - CPUをスロットル(4×)し、モーション再生中にPerformanceパネルを記録します。長いフレームを探します。
- 電話幅(390px)で確認します。アニメーション要素による水平オーバーフローを探します。
- 動き軽減を有効にする(DevTools → Rendering →
references/quality-checklist.mdを吟味します。- 合格したもの、不合格だったもの、修正したものを報告します。
絶対条件(すべての項目が合格必須)
- ANIMATION.md のすべてのアニメーションに動き軽減フォールバックがあること。
transform、opacity、および記録された例外のみがアニメーションされること。- すべての継続時間とイージングがトークンから来ていること。
- すべての
infiniteループが動き軽減を尊重し、5秒より長いループには一時停止コントロールがあること。 - 1秒間に3回以上点滅するものがないこと。
- インタラクティブフィードバックが100ms以内に現れること。マイクロアニメーションは250ms以下。出現およびルート遷移は500ms以下。
- ホバーのみのフィードバックには、キーボードフォーカス状態とタッチ相当のものがあること。
- 幅600px以下では、アニメーション要素による水平スクロールが発生せず、ピン留めセクションは無効化または簡略化されること。
- JavaScriptアニメーションはアンマウント時にクリーンアップされること。
リファレンスインデックス
現在のフェーズに必要なファイルのみを読みます。すべてを読み込まないでください。
| ファイル | 内容 | いつ読むか |
|---|---|---|
references/animation-md-template.md | ANIMATION.md 出力テンプレート(10セクション) | フェーズB |
references/motion-principles.md | なぜ、いつアニメーションするか、タイミングとイージングのルール | フェーズAとB |
references/interaction-tiers.md | L1、L2、L3の層定義とコードパターン | フェーズA2とB |
references/motion-personalities.md | トークン値を持つ4つのパーソナリティプリセット | フェーズA1とB |
references/tooling.md | CSS vs WAAPI vs GSAP vs Motion vs View Transitions vs Lottie | フェーズA3 |
references/component-recipes.md | ボタン、カード、アコーディオン、モーダル、ドロワー、トースト、タブ、ローダー | フェーズC |
references/gsap-recipes.md | GSAPタイムライン、ScrollTrigger、matchMedia、Reactクリーンアップ | フェーズC(GSAPのみ) |
references/scroll-patterns.md | 表示、プログレスバー、スティッキースタック、パララックス、水平スクロール | フェーズB(スクロール)とC |
references/performance.md | フレーム予算、コンポジターに優しいルール、モバイルダウングレード | フェーズBとD |
references/accessibility.md | 動き軽減、WCAGモーション基準、前庭トリガー | フェーズBとD |
references/quality-checklist.md | 100ポイント監査チェックリスト | フェーズD |
スクリプト
| スクリプト | 用途 | 必要なもの |
|---|---|---|
scripts/analyze_motion.py | プロジェクトのCSSとJSの静的監査。レイアウトアニメーション、transition: all、無限ループ、長い継続時間、欠落した動き軽減処理を検出します。--inventory は既存のタイミング値を一覧表示します。 | Python 3(標準ライブラリのみ) |
scripts/capture_motion.py | ライブURL上の宣言済みおよび実行中のアニメーションを記録し、ページをスクロールし、動き軽減下で何がまだ実行されるかをチェックします。capture.json と top.png を書き出します。 | Python 3、pip install playwright、python -m playwright install chromium |
両スクリプトとも --help を受け付けます。
テンプレート
| ファイル | 用途 |
|---|---|
templates/motion-tokens.css | トークン変数、ベースキーフレーム、表示ルール、動き軽減ブロック。プロジェクトにコピーします。 |
templates/reveal.js | IntersectionObserverを使用し、動き軽減を尊重する依存関係なしのスクロール表示。 |
言語
ANIMATION.md とサマリーはユーザーの言語で作成します。CSS、JavaScript、トークン名は英語のままにします。
フォールバックチェーン
- キャプチャスクリプトが失敗する(Playwrightがない、またはサイトがブラウザをブロックする)→ スクリーンショットまたは短いスクリーン録画を求め、その説明から構築します。
- 参照が特定できないアニメーションライブラリを使用している → その旨を伝え、感触を合わせるか、正確なモーションを合わせるかを尋ねます。
- 入力がまったくない → 感触について1つ質問し、その後 calm パーソナリティを使用します。