2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FigmaでAIを強化する | 第3章:デザインデータ分析:AIによるUIインサイト

Posted at

はじめに

第2章では、Figmaのコメントを読み書きするMCPサーバーを構築し、フィードバックを自動化するエージェントを実現しました。これにより、AIがデザインコメントを処理・生成できるようになり、デザインプロセスの効率が向上しました。今回は、この基盤を活用して、Figmaのデザインデータを分析し、UIの品質や一貫性に関するインサイトを生成するUI分析エージェントを構築します。

この第3章では、Figmaのファイルからノードデータ(例:色、フォント、レイアウト)を抽出し、アクセシビリティやデザインの整合性を評価するMCPサーバーを実装します。たとえば、AIが色のコントラスト不足を検出したり、フォントサイズのばらつきを指摘したりできます。コード例とステップごとのガイドで、UI分析AIの構築を体験しましょう。さあ、始めましょう!

UI分析エージェントとは?

UI分析エージェントは、Figmaのデザインデータを解析し、UIの品質やユーザー体験に関するインサイトを提供するAIです。MCPサーバーを介して、以下のような機能を実現できます:

  • アクセシビリティチェック:色のコントラスト比やフォントサイズを評価。
  • 一貫性分析:デザイン全体での色やフォントのばらつきを検出。
  • 提案生成:分析結果に基づいて改善案をコメントとして投稿。

ユースケース

  • デザインレビュー:AIがアクセシビリティの問題を自動検出し、修正案を提案。
  • 品質管理:デザインシステムの一貫性を維持し、ブランドガイドラインを遵守。
  • チームコラボレーション:分析結果をチームと共有し、フィードバックを効率化。

開発環境の準備

第2章の環境を基に、以下の追加準備を行います:

  • Python 3.8以降mcpライブラリrequestsライブラリClaude Desktop:これまでと同じ。
  • webcolorsライブラリ:色の分析用。
  • Figmaファイル:分析用のデザインデータを準備。

インストールコマンド:

pip install webcolors

Figmaファイルの準備

  1. テストデザインの作成
    • 第2章のFigmaファイル(例:MCP-Design)を使用。
    • 以下の要素を含むデザインを追加:
      • ボタン(背景色:青 #007BFF、テキスト色:白 #FFFFFF
      • テキスト(フォントサイズ:16px、色:黒 #000000
      • 別のテキスト(フォントサイズ:14px、色:グレー #666666
    • コメントでノードID(例:1:2)を確認し、記録。
  2. APIトークンの確認
    • 第2章のPersonal Access Tokenを再利用(ファイルデータとコメントの読み書きに必要)。
  3. 環境変数
    第2章の.envファイル(FIGMA_TOKENFIGMA_FILE_ID)を再利用。

コード例:UI分析用MCPサーバー

以下のMCPサーバーは、Figmaのノードデータから色やフォント情報を抽出し、アクセシビリティと一貫性を分析します。さらに、分析結果をコメントとして投稿します。

from mcp import MCPServer
import os
from dotenv import load_dotenv
import requests
import webcolors
from math import sqrt

class FigmaAnalysisServer(MCPServer):
    def __init__(self, host, port, figma_token, file_id):
        super().__init__(host, port)
        self.figma_token = figma_token
        self.file_id = file_id
        self.headers = {"X-Figma-Token": figma_token}
        self.register_resource("analyze_ui", self.analyze_ui)
        self.register_tool("add_comment", self.add_comment)

    def calculate_contrast(self, color1, color2):
        # 簡易的なコントラスト比計算(WCAG基準の近似)
        def luminance(rgb):
            r, g, b = [c / 255.0 for c in rgb]
            for c in (r, g, b):
                c = c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
            return 0.2126 * r + 0.7152 * g + 0.0722 * b
        rgb1 = webcolors.hex_to_rgb(color1)
        rgb2 = webcolors.hex_to_rgb(color2)
        l1, l2 = luminance(rgb1), luminance(rgb2)
        if l1 < l2:
            l1, l2 = l2, l1
        return (l1 + 0.05) / (l2 + 0.05)

    def analyze_ui(self, params):
        try:
            url = f"https://api.figma.com/v1/files/{self.file_id}"
            response = requests.get(url, headers=self.headers)
            response.raise_for_status()
            data = response.json()
            nodes = data.get("document", {}).get("children", [])

            issues = []
            colors = []
            font_sizes = []

            for node in nodes:
                if "fills" in node and node["fills"]:
                    color = node["fills"][0].get("color", {})
                    if color:
                        hex_color = webcolors.rgb_to_hex((
                            int(color["r"] * 255),
                            int(color["g"] * 255),
                            int(color["b"] * 255)
                        ))
                        colors.append(hex_color)
                if "style" in node and "fontSize" in node["style"]:
                    font_sizes.append(node["style"]["fontSize"])

                # コントラストチェック(例:背景とテキスト)
                if "fills" in node and "characters" in node:
                    bg_color = node["fills"][0].get("color", {})
                    text_color = node.get("style", {}).get("fill", {}).get("color", {})
                    if bg_color and text_color:
                        bg_hex = webcolors.rgb_to_hex((
                            int(bg_color["r"] * 255),
                            int(bg_color["g"] * 255),
                            int(bg_color["b"] * 255)
                        ))
                        text_hex = webcolors.rgb_to_hex((
                            int(text_color["r"] * 255),
                            int(text_color["g"] * 255),
                            int(text_color["b"] * 255)
                        ))
                        contrast = self.calculate_contrast(bg_hex, text_hex)
                        if contrast < 4.5:  # WCAG AA基準
                            issues.append({
                                "node_id": node["id"],
                                "issue": f"コントラスト比が低すぎます({contrast:.2f})。WCAG基準の4.5以上が必要です。"
                            })

            # フォントサイズの一貫性チェック
            if font_sizes:
                avg_font_size = sum(font_sizes) / len(font_sizes)
                for size in font_sizes:
                    if abs(size - avg_font_size) > 2:
                        issues.append({
                            "node_id": "",
                            "issue": f"フォントサイズ({size}px)が平均({avg_font_size:.1f}px)から大きく乖離しています。"
                        })

            return {"status": "success", "issues": issues}
        except Exception as e:
            return {"status": "error", "message": str(e)}

    def add_comment(self, params):
        try:
            message = params.get("message", "")
            node_id = params.get("node_id", "")
            if not message:
                return {"status": "error", "message": "コメントが必要です"}
            
            url = f"https://api.figma.com/v1/files/{self.file_id}/comments"
            payload = {
                "message": message,
                "client_meta": {"node_id": node_id} if node_id else None
            }
            response = requests.post(url, headers=self.headers, json=payload)
            response.raise_for_status()
            comment = response.json()
            return {"status": "success", "comment_id": comment["id"]}
        except Exception as e:
            return {"status": "error", "message": str(e)}

if __name__ == "__main__":
    load_dotenv()
    server = FigmaAnalysisServer(
        host="localhost",
        port=8107,
        figma_token=os.getenv("FIGMA_TOKEN"),
        file_id=os.getenv("FIGMA_FILE_ID")
    )
    print("Figma分析MCPサーバーを起動中: http://localhost:8107")
    server.start()

コードの説明

  • analyze_ui:Figmaファイルのノードを解析し、色やフォントサイズを抽出。コントラスト比(WCAG基準)とフォントサイズの一貫性を評価。
  • calculate_contrast:簡易的なコントラスト比を計算し、WCAG AA基準(4.5以上)をチェック。
  • add_comment:第2章から再利用し、分析結果をコメントとして投稿可能。
  • register_resource/tool:UI分析をリソース、コメント追加をツールとして登録。

前提条件

  • Figmaファイルに色やフォントを含むノードが存在。
  • .envファイルに正しいFIGMA_TOKENFIGMA_FILE_IDが設定済み。
  • APIトークンにファイルデータとコメントの読み書き権限がある。

サーバーのテスト

サーバーが正しく動作するか確認します:

  1. サーバー起動

    python figma_analysis_server.py
    

    コンソールに「Figma分析MCPサーバーを起動中: http://localhost:8107」と表示。

  2. UI分析のテスト
    Pythonでリクエストを送信:

    import requests
    import json
    
    url = "http://localhost:8107"
    payload = {
        "jsonrpc": "2.0",
        "method": "analyze_ui",
        "params": {},
        "id": 1
    }
    response = requests.post(url, json=payload)
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
    

    期待されるレスポンス:

    {
      "jsonrpc": "2.0",
      "result": {
        "status": "success",
        "issues": [
          {
            "node_id": "1:2",
            "issue": "コントラスト比が低すぎます(3.50)。WCAG基準の4.5以上が必要です。"
          },
          {
            "node_id": "",
            "issue": "フォントサイズ(14px)が平均(15px)から大きく乖離しています。"
          }
        ]
      },
      "id": 1
    }
    
  3. コメント追加のテスト

    payload = {
        "jsonrpc": "2.0",
        "method": "add_comment",
        "params": {
            "message": "コントラスト比を改善してください",
            "node_id": "1:2"
        },
        "id": 2
    }
    response = requests.post(url, json=payload)
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
    

Claude Desktopとの接続

サーバーをClaude Desktopに接続します:

  1. 設定ファイルの編集
    Claude Desktopの設定ファイル(例:claude_desktop_config.json)に以下を追加:

    {
      "mcp_servers": [
        {
          "name": "FigmaAnalysisServer",
          "url": "http://localhost:8107",
          "auth": "none"
        }
      ]
    }
    
  2. Claudeでテスト
    Claude Desktopを起動し、プロンプトを入力:

    デザインのUI問題を教えてください。
    

    レスポンス例:

    デザインのUI問題:
    - ボタン(ノード1:2):コントラスト比が3.50で、WCAG基準の4.5未満です。
    - フォントサイズ:14pxが平均15pxから乖離しています。
    

    別のプロンプト:

    ボタンのコントラスト問題をコメントしてください。
    

    レスポンス例:

    ボタンに「コントラスト比を改善してください」をコメントしました。
    

実装のコツと注意点

  • パフォーマンス:大量のノードを処理する場合、Figma APIのリクエストを最適化(例:特定ノードのみ取得)。
  • エラーハンドリング:ノードに色やフォント情報がない場合に対応。
  • レートリミティング:Figma APIの制限(通常30リクエスト/分)に注意。
  • セキュリティ:本番環境では、HTTPSとトークン認証を導入。
  • 拡張性:複雑な分析の場合、デザインシステムのルールを事前定義。

試してみよう:挑戦課題

以下の機能を追加して、エージェントを強化してみてください:

  • 色の多様性を分析し、ブランドカラーからの逸脱を検出。
  • レイアウトの整列(例:マージンやパディング)をチェック。
  • 分析結果を新しいFigmaファイルにエクスポートするツール。

まとめと次のステップ

この第3章では、Figmaのデザインデータを活用してUI分析エージェントを構築しました。色のコントラストやフォントサイズの分析により、AIがUIの品質を評価し、改善提案を生成できるようになりました。

次の第4章では、Figmaのバージョン管理を強化するバージョン管理AIを構築します。たとえば、AIがデザインの変更履歴を追跡し、変更点をコメントとして記録します。バージョン管理AIに興味がある方は、ぜひお楽しみに!


役に立ったと思ったら、「いいね」や「ストック」をしていただけると嬉しいです!次の章でまたお会いしましょう!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?