Motion(旧 Framer Motion)デザインレビュー運用:Figma パラメータ同期と差分共有のワークフロー

デザインと実装の間には、常に「見た目は同じなのに動きが違う」という課題が存在します。特にアニメーションを含むコンポーネントでは、Figma で定義したタイミング関数やデュレーションが実装時に正確に反映されず、デザインレビューで何度も指摘と修正を繰り返すことになりがちです。
本記事では、Motion(旧 Framer Motion)を使ったアニメーション実装において、Figma のパラメータを確実に同期し、変更差分を開発チームと共有するワークフローをご紹介します。このワークフローを導入すれば、デザイナーとエンジニアの間での認識のズレが減り、レビューサイクルが大幅に短縮されるでしょう。
背景
デザインツールとアニメーションライブラリの分断
現代の Web 開発では、Figma がデザインの標準ツールとして広く使われています。一方、React ベースのプロジェクトではアニメーション実装に Motion(旧 Framer Motion)が選ばれることが多く、両者は別々のエコシステムで動作しているのが現状です。
Figma ではイージング関数(ease-in、ease-out など)やデュレーション(0.3s、0.5s など)を視覚的に設定できます。しかし、これらのパラメータをエンジニアに伝える際、ドキュメントやコメントで「ease-in-out、300ms」と文字で記載するだけでは、実装時に微妙なズレが生じやすくなります。
デザインレビューでの繰り返し修正
デザインレビューの場で「この動きは少し早すぎる」「イージングが違う気がする」といった指摘が続くと、開発速度が低下するだけでなく、チームのモチベーションにも影響を与えます。特にアニメーションは体感的な要素が強いため、数値だけでは伝わりにくいのが難点です。
以下の図は、従来のワークフローにおける課題を示しています。
mermaidflowchart LR
designer["デザイナー"] -->|Figma で設計| figma["Figma ファイル"]
figma -->|口頭・ドキュメント| eng["エンジニア"]
eng -->|Motion で実装| code["実装コード"]
code -->|レビュー依頼| designer
designer -->|差分指摘| eng
eng -->|再実装| code
style figma fill:#f9f,stroke:#333
style code fill:#9cf,stroke:#333
このように、Figma とコード間でパラメータが分断されており、往復のやり取りが発生しやすい構造になっています。
課題
1. パラメータの手動転記によるミス
Figma で定義したアニメーションパラメータを、エンジニアが手動で Motion のコードに転記する際、以下のようなミスが発生します。
- デュレーションの単位違い: Figma は
ms
、Motion は秒数で指定するため、300ms
を0.3
に変換し忘れる - イージング関数の名称違い: Figma の
ease-in-out
が Motion ではeaseInOut
と表記が異なる - 遅延(delay)の見落とし: Figma で設定した
delay
を実装時に忘れる
これらのミスは、レビュー時に初めて発覚することが多く、手戻りコストが大きくなります。
2. 変更差分の追跡困難
デザインが更新された際、「どのパラメータがどう変わったのか」を把握するのが困難です。Figma のバージョン履歴を見ても、アニメーションパラメータの変更は視覚的に分かりにくく、エンジニアが変更点を見逃しやすくなります。
3. レビューコミュニケーションの非効率
デザインレビューでは、「この部分のアニメーションを修正してください」という指摘に対し、具体的な数値が伝わらないことがあります。結果として、何度も試行錯誤を繰り返すことになり、レビューサイクルが長期化します。
以下の図は、主な課題を整理したものです。
mermaidflowchart TB
subgraph issues["デザインレビューの課題"]
issue1["パラメータ転記ミス"]
issue2["差分追跡困難"]
issue3["レビュー非効率"]
end
issue1 -->|原因| cause1["手動転記"]
issue2 -->|原因| cause2["履歴の可視性低"]
issue3 -->|原因| cause3["数値伝達不足"]
cause1 --> impact["手戻りコスト増"]
cause2 --> impact
cause3 --> impact
style issues fill:#fdd,stroke:#333
style impact fill:#faa,stroke:#333
解決策
Figma と Motion のパラメータ同期ワークフロー
これらの課題を解決するために、以下の 3 つの仕組みを組み合わせたワークフローを構築します。
- Figma プラグインによるパラメータ出力: Figma でアニメーションパラメータを JSON 形式で出力
- Motion 設定ファイルとの同期: 出力した JSON を Motion の設定として読み込み
- 差分管理と共有: Git でパラメータファイルを管理し、変更差分を可視化
このワークフローにより、Figma のパラメータが直接コードに反映され、手動転記ミスがなくなります。また、Git の差分表示により、デザイン変更が明確に追跡できるようになります。
以下の図は、改善後のワークフロー全体像を示しています。
mermaidflowchart LR
designer["デザイナー"] -->|Figma で設計| figma["Figma ファイル"]
figma -->|プラグインで出力| json["JSON パラメータ"]
json -->|Git で管理| repo["リポジトリ"]
repo -->|読み込み| code["Motion コード"]
code -->|レビュー依頼| designer
designer -->|差分確認| repo
repo -->|更新| json
style json fill:#9f9,stroke:#333
style repo fill:#99f,stroke:#333
このフローでは、JSON ファイルが単一の信頼できる情報源(Single Source of Truth)となり、デザイナーとエンジニアが同じパラメータを参照できます。
ワークフローの構成要素
このワークフローを実現するために、以下の技術要素を組み合わせます。
# | 要素 | 役割 | 技術 |
---|---|---|---|
1 | Figma プラグイン | アニメーションパラメータ出力 | Figma Plugin API |
2 | JSON パラメータファイル | デザイン定義の保存 | JSON 形式 |
3 | Motion 設定読み込み | パラメータの実装適用 | TypeScript, Motion |
4 | バージョン管理 | 差分追跡と共有 | Git, GitHub |
具体例
ステップ 1: Figma プラグインの作成
まず、Figma でアニメーションパラメータを抽出するプラグインを作成します。このプラグインは、選択したレイヤーのトランジション設定を JSON 形式で出力します。
プラグインの基本構造
以下は、Figma プラグインのエントリーポイントです。
typescript// manifest.json の設定
{
"name": "Motion Parameters Exporter",
"id": "motion-params-exporter",
"api": "1.0.0",
"main": "code.js",
"ui": "ui.html"
}
プラグインのメイン処理では、選択されたノードからトランジション情報を取得します。
typescript// code.ts(プラグインのメインロジック)
// Figma の選択ノードを取得
const selection = figma.currentPage.selection;
// 選択がない場合のエラーハンドリング
if (selection.length === 0) {
figma.notify(
'アニメーション対象のレイヤーを選択してください'
);
figma.closePlugin();
}
アニメーションパラメータの抽出
Figma のノードからトランジション情報を抽出する関数を実装します。
typescript// トランジション情報を抽出する関数
interface AnimationParams {
name: string;
duration: number; // 秒単位
easing: string;
delay: number;
}
function extractTransition(
node: SceneNode
): AnimationParams | null {
// FrameNode または ComponentNode のみ対応
if (node.type !== 'FRAME' && node.type !== 'COMPONENT') {
return null;
}
// reactions(プロトタイプ設定)を確認
const reactions = node.reactions;
if (!reactions || reactions.length === 0) {
return null;
}
return reactions
.filter((r) => r.action?.type === 'NODE')
.map((r) => ({
name: node.name,
duration: r.action.transition.duration / 1000, // ms を秒に変換
easing: convertEasing(r.action.transition.easing),
delay: (r.action.transition.delay || 0) / 1000,
}))[0];
}
イージング関数の変換
Figma のイージング設定を Motion の形式に変換します。
typescript// Figma のイージングを Motion 形式に変換
function convertEasing(easing: any): string {
const easingMap: Record<string, string> = {
EASE_IN: 'easeIn',
EASE_OUT: 'easeOut',
EASE_IN_OUT: 'easeInOut',
LINEAR: 'linear',
EASE_IN_BACK: 'backIn',
EASE_OUT_BACK: 'backOut',
};
return easingMap[easing.type] || 'easeInOut';
}
JSON の出力
抽出したパラメータを JSON 形式で出力します。
typescript// パラメータを JSON として出力
const params = selection
.map((node) => extractTransition(node))
.filter((p) => p !== null);
// UI に結果を送信
figma.ui.postMessage({
type: 'export',
data: JSON.stringify(params, null, 2),
});
このプラグインを実行すると、以下のような JSON が出力されます。
json[
{
"name": "Button Hover",
"duration": 0.3,
"easing": "easeInOut",
"delay": 0
},
{
"name": "Modal Open",
"duration": 0.5,
"easing": "backOut",
"delay": 0.1
}
]
ステップ 2: パラメータファイルの管理
出力した JSON をプロジェクトリポジトリに配置します。
ディレクトリ構成
プロジェクト内に専用のディレクトリを作成し、デザインパラメータを管理します。
bash/src
/config
/animation
motion-params.json # Figma から出力したパラメータ
index.ts # パラメータ読み込み用モジュール
パラメータファイルの例
json{
"button": {
"hover": {
"duration": 0.3,
"easing": "easeInOut",
"delay": 0
},
"press": {
"duration": 0.15,
"easing": "easeIn",
"delay": 0
}
},
"modal": {
"open": {
"duration": 0.5,
"easing": "backOut",
"delay": 0.1
},
"close": {
"duration": 0.3,
"easing": "easeIn",
"delay": 0
}
}
}
ステップ 3: Motion での読み込み実装
パラメータファイルを Motion のコンポーネントで利用します。
型定義の作成
まず、アニメーションパラメータの型を定義します。
typescript// src/config/animation/types.ts
// アニメーションパラメータの型定義
export interface MotionParams {
duration: number;
easing: string;
delay: number;
}
// パラメータセット全体の型
export interface AnimationConfig {
button: {
hover: MotionParams;
press: MotionParams;
};
modal: {
open: MotionParams;
close: MotionParams;
};
}
パラメータ読み込みモジュール
JSON ファイルを読み込み、型安全にアクセスできるモジュールを作成します。
typescript// src/config/animation/index.ts
import motionParamsJson from './motion-params.json';
import type { AnimationConfig } from './types';
// JSON を型付きオブジェクトとして export
export const animationConfig: AnimationConfig =
motionParamsJson;
// 特定のアニメーションパラメータを取得するヘルパー関数
export function getAnimationParams(
category: keyof AnimationConfig,
action: string
): MotionParams {
const params = animationConfig[category][action];
if (!params) {
console.warn(
`Animation params not found: ${category}.${action}`
);
// デフォルト値を返す
return { duration: 0.3, easing: 'easeInOut', delay: 0 };
}
return params;
}
Motion コンポーネントでの利用
パラメータを実際の Motion コンポーネントに適用します。
typescript// src/components/Button.tsx
import { motion } from 'motion/react';
import { getAnimationParams } from '@/config/animation';
export function Button({
children,
}: {
children: React.ReactNode;
}) {
// Figma のパラメータを取得
const hoverParams = getAnimationParams('button', 'hover');
const pressParams = getAnimationParams('button', 'press');
return (
<motion.button
whileHover={{
scale: 1.05,
transition: {
duration: hoverParams.duration,
ease: hoverParams.easing,
delay: hoverParams.delay,
},
}}
whileTap={{
scale: 0.95,
transition: {
duration: pressParams.duration,
ease: pressParams.easing,
delay: pressParams.delay,
},
}}
>
{children}
</motion.button>
);
}
モーダルコンポーネントの例
より複雑なアニメーションを持つモーダルコンポーネントでも同様に適用できます。
typescript// src/components/Modal.tsx
import { motion, AnimatePresence } from 'motion/react';
import { getAnimationParams } from '@/config/animation';
interface ModalProps {
isOpen: boolean;
onClose: () => void;
children: React.ReactNode;
}
export function Modal({
isOpen,
onClose,
children,
}: ModalProps) {
// Figma 定義のパラメータを使用
const openParams = getAnimationParams('modal', 'open');
const closeParams = getAnimationParams('modal', 'close');
return (
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{
opacity: 1,
scale: 1,
transition: {
duration: openParams.duration,
ease: openParams.easing,
delay: openParams.delay,
},
}}
exit={{
opacity: 0,
scale: 0.9,
transition: {
duration: closeParams.duration,
ease: closeParams.easing,
delay: closeParams.delay,
},
}}
onClick={onClose}
className='modal-overlay'
>
{children}
</motion.div>
)}
</AnimatePresence>
);
}
ステップ 4: Git による差分管理
パラメータファイルを Git で管理することで、デザイン変更の履歴を追跡できます。
コミット例
デザイナーがパラメータを更新した際のコミット例です。
bash# パラメータファイルの変更をステージング
git add src/config/animation/motion-params.json
# わかりやすいコミットメッセージ
git commit -m "design: モーダルの開閉アニメーションを高速化(0.5s → 0.4s)"
プルリクエストでの差分確認
GitHub のプルリクエスト画面では、JSON の差分が視覚的に確認できます。
diff{
"modal": {
"open": {
- "duration": 0.5,
+ "duration": 0.4,
"easing": "backOut",
"delay": 0.1
}
}
}
このように、具体的な数値変更が一目で分かるため、レビュアーは変更内容を正確に把握できます。
レビューコメントの例
プルリクエストでのレビューコメントも、具体的な数値を参照しながら行えます。
markdown# レビューコメント例
モーダルの開くアニメーションが 0.4s に短縮されていますが、
少し速すぎる印象です。0.45s くらいが適切かと思います。
変更後の動作確認済み ✅
ステップ 5: 自動化とワークフロー統合
GitHub Actions での検証
パラメータファイルの形式が正しいか、自動でチェックする仕組みを導入します。
yaml# .github/workflows/validate-animation-params.yml
name: Validate Animation Parameters
on:
pull_request:
paths:
- 'src/config/animation/motion-params.json'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: yarn install
- name: Validate JSON schema
run: yarn validate:animation-params
バリデーションスクリプト
パラメータファイルの妥当性を検証するスクリプトです。
typescript// scripts/validate-animation-params.ts
import { readFileSync } from 'fs';
import { join } from 'path';
// スキーマ定義(簡易版)
interface ParamSchema {
duration: number;
easing: string;
delay: number;
}
// 許可されたイージング関数
const ALLOWED_EASINGS = [
'linear',
'easeIn',
'easeOut',
'easeInOut',
'backIn',
'backOut',
'backInOut',
];
function validateParams(params: any): boolean {
let isValid = true;
// 再帰的にパラメータを検証
function validate(obj: any, path: string = ''): void {
if (obj.duration !== undefined) {
// duration の検証
if (
typeof obj.duration !== 'number' ||
obj.duration <= 0
) {
console.error(
`❌ ${path}.duration: 正の数値である必要があります`
);
isValid = false;
}
// easing の検証
if (!ALLOWED_EASINGS.includes(obj.easing)) {
console.error(
`❌ ${path}.easing: 許可されていない値です`
);
isValid = false;
}
// delay の検証
if (typeof obj.delay !== 'number' || obj.delay < 0) {
console.error(
`❌ ${path}.delay: 0以上の数値である必要があります`
);
isValid = false;
}
} else {
// ネストされたオブジェクトを検証
for (const key in obj) {
validate(obj[key], path ? `${path}.${key}` : key);
}
}
}
validate(params);
return isValid;
}
// メイン処理
const paramsPath = join(
__dirname,
'../src/config/animation/motion-params.json'
);
const params = JSON.parse(
readFileSync(paramsPath, 'utf-8')
);
if (validateParams(params)) {
console.log('✅ アニメーションパラメータは正常です');
process.exit(0);
} else {
console.error(
'❌ アニメーションパラメータに問題があります'
);
process.exit(1);
}
package.json へのスクリプト追加
json{
"scripts": {
"validate:animation-params": "ts-node scripts/validate-animation-params.ts"
}
}
ステップ 6: デザインレビューフローの改善
このワークフローを導入した後のデザインレビューの流れを整理します。
mermaidsequenceDiagram
participant Designer as デザイナー
participant Figma as Figma
participant Plugin as プラグイン
participant Git as Git リポジトリ
participant Engineer as エンジニア
participant Code as Motion コード
Designer->>Figma: アニメーション設計
Designer->>Plugin: パラメータ出力
Plugin->>Git: JSON コミット
Git->>Engineer: PR 作成通知
Engineer->>Git: 差分確認
Engineer->>Code: パラメータ読み込み
Code->>Engineer: 実装完了
Engineer->>Designer: レビュー依頼
Designer->>Code: 動作確認
Designer->>Git: 承認
このフローでは、以下の改善が実現されています。
- パラメータの自動同期: 手動転記が不要
- 差分の可視化: Git で変更内容が明確
- レビューの効率化: 具体的な数値でコミュニケーション
実運用での Tips
実際にこのワークフローを運用する際の実践的なポイントをご紹介します。
1. パラメータの命名規則
JSON ファイル内のキー名は、Figma のレイヤー名と一致させることで、追跡しやすくなります。
json{
"button_primary_hover": {
"duration": 0.3,
"easing": "easeInOut",
"delay": 0
}
}
2. デフォルト値の設定
すべてのアニメーションを JSON で管理する必要はありません。汎用的なものはデフォルト値として定義します。
typescript// src/config/animation/defaults.ts
export const DEFAULT_ANIMATION = {
duration: 0.3,
easing: 'easeInOut',
delay: 0,
};
export function withDefaults(
params: Partial<MotionParams>
): MotionParams {
return { ...DEFAULT_ANIMATION, ...params };
}
3. Storybook での確認
パラメータ変更後の動作を Storybook で確認できるようにします。
typescript// src/components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
import { animationConfig } from '@/config/animation';
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
parameters: {
// 現在のアニメーションパラメータを表示
docs: {
description: {
component: `
Hover animation: ${JSON.stringify(
animationConfig.button.hover,
null,
2
)}
`,
},
},
},
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Default: Story = {
args: {
children: 'Click me',
},
};
まとめ
本記事では、Motion(旧 Framer Motion)を使ったアニメーション実装において、Figma のパラメータを確実に同期し、デザインレビューを効率化するワークフローをご紹介しました。
このワークフローの要点は以下の通りです。
- Figma プラグインで JSON 出力: アニメーションパラメータを自動抽出し、手動転記ミスを防止
- Git による差分管理: デザイン変更を明確に追跡し、レビュアーが正確に把握可能
- Motion での自動読み込み: パラメータファイルを単一の情報源とし、実装との同期を保証
- 自動検証の導入: GitHub Actions でパラメータの妥当性をチェック
このアプローチにより、デザイナーとエンジニアの間での認識のズレが減り、レビューサイクルが大幅に短縮されます。また、デザインシステムの一貫性を保ちながら、アニメーションの品質を向上させることができるでしょう。
アニメーションは、ユーザー体験を左右する重要な要素です。このワークフローを導入することで、デザイン意図を正確に実装に反映し、より洗練された UI を実現していただければ幸いです。
関連リンク
- article
Motion(旧 Framer Motion)デザインレビュー運用:Figma パラメータ同期と差分共有のワークフロー
- article
Motion(旧 Framer Motion)アニメオーケストレーション設計:timeline・遅延・相互依存の整理術
- article
Motion(旧 Framer Motion)useAnimate/useMotionValueEvent 速習チートシート
- article
Motion(旧 Framer Motion)× Vite/Next/Turbopack:ツリーシェイク最適化とバンドル最小化の初期設定
- article
Motion(旧 Framer Motion)でカクつき・ちらつきを潰す:レイアウトシフトと FLIP の落とし穴
- article
Motion(旧 Framer Motion)アーキテクチャ概説:Renderer と Animation Engine を俯瞰する
- article
NestJS 監視運用:SLI/SLO とダッシュボード設計(Prometheus/Grafana/Loki)
- article
WebRTC AV1/VP9/H.264 ベンチ比較 2025:画質・CPU/GPU 負荷・互換性を実測
- article
MySQL アラート設計としきい値:レイテンシ・エラー率・レプリカ遅延の基準
- article
Vitest フレーク検知技術の運用:`--retry` / シード固定 / ランダム順序で堅牢化
- article
Motion(旧 Framer Motion)デザインレビュー運用:Figma パラメータ同期と差分共有のワークフロー
- article
esbuild プリバンドルを理解する:Vite の optimizeDeps 深掘り
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来