mcpField
U
ui-screenshots

ui-screenshots

github.com/githubデザイン・UI40.5k210 回インストール1 日前に更新
リポジトリ

ui-screenshots について

ui-screenshotsは、開発中のWebやグラフィカルなUIを撮影し、見た目の変化を記録するスキルです。全ページや操作状態の撮影に加え、画像を切り出して部分表示を作れます。

主な機能

  1. 01Webページ全体の撮影
  2. 02変更前後のUI記録
  3. 03操作状態の撮影
  4. 04PILによる画像切り出し
  5. 05Web、Electron、デスクトップ撮影の案内

活用シーン

  1. 01コード変更前後のUIを記録
  2. 02ツールチップや選択状態を撮影
  3. 03全ページ画像から一部を切り出し

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/github/awesome-copilot --skill ui-screenshots

インストール後、Claude Code で/ui-screenshotsを入力して読み込まれたか確認します。

詳細

UI スクリーンショット

開発中に Web アプリやグラフィカル UI のスクリーンショットを撮影し、視覚的な変更を記録します。

このスキルを使用する場面

次のような場合にこのスキルを使用します。

  • 実行中の Web アプリの現在の状態を撮影する
  • コード変更の前後で UI を記録する
  • ツールチップ、ホバー、選択された要素など、インタラクティブな状態を撮影する
  • 再撮影せずにページの特定のセクションを撮影する

前提条件

pip install playwright Pillow -q
playwright install chromium

基本的なワークフロー

1. フルページのスクリーンショットをそのまま撮影する
from playwright.async_api import async_playwright

async def capture(url="http://localhost:3000", out="screenshot-raw.png", width=1400, height=5000):
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page(viewport={"width": width, "height": height})
        await page.goto(url, wait_until="networkidle")
        await page.wait_for_timeout(4000)  # let charts/animations render
        await page.screenshot(path=out, full_page=True)
        await browser.close()
  • ページをスクロールせずにすべて表示するため、高さのあるビューポート(height=5000)を使用します
  • wait_until="networkidle" と wait_for_timeout(4000) を指定すると、非同期のグラフが確実に読み込まれます
  • full_page=True を指定すると、スクロール可能なコンテンツ全体を撮影できます
2. 元画像を確認してから、PIL で切り抜く

Playwright の clip パラメーターで正確に切り抜こうとしないでください。 フルページの撮影では信頼性に欠けます。

from PIL import Image

img = Image.open("screenshot-raw.png")
cropped = img.crop((left, top, right, bottom))  # adjust based on what you see
cropped.save("screenshot-final.png")
  1. 元のスクリーンショットを撮影します
  2. 表示して実際のピクセル位置を確認します
  3. 確認した位置を基に PIL で切り抜きます
  4. 結果を確認し、適切でなければ再度切り抜きます(すぐにでき、再撮影は不要です)
3. 撮影ではなく切り抜きを繰り返す
  • 再撮影には時間がかかります(ブラウザーの起動+ページの読み込み+描画待ち)
  • 再度の切り抜きはすぐにできます(PIL のみ)
  • 元画像を一度きれいに撮影し、必要に応じて何通りにも切り分けます
4. インタラクティブな状態
element = page.locator("selector").first
await element.hover()
await page.wait_for_timeout(1000)  # let tooltip appear
await page.screenshot(path="screenshot-hover.png", full_page=True)

ホバー効果のない「選択済み」状態にするには、クリック後にマウスを移動します。

await element.click()
await page.mouse.move(300, 300)  # move away so hover doesn't show
await page.wait_for_timeout(500)
await page.screenshot(path="screenshot-selected.png", full_page=True)
5. 特定セクションの撮影

1 枚のフルページスクリーンショットから、異なるセクションを切り抜きます。

img.crop((0, 200, 920, 900)).save("screenshot-header.png")
img.crop((0, 900, 920, 1600)).save("screenshot-main.png")

ガイドライン

  1. 変更を加える前の状態を必ず撮影してください — 撮り忘れると、変更前の画像を得るためにコードを元に戻す必要があります
  2. 変更前後の画像には同じビューポート幅と切り抜きを使用してください — そうでないと比較に意味がありません
  3. コードを変更した後に「変更前」の画像を撮るには、git checkout HEAD~1 -- <files> で元に戻して撮影し、その後 git checkout HEAD -- <files> で復元します
  4. インタラクティブな状態では、各状態について変更前と変更後の両方を撮影してください — 通常状態の変更前の画像ですべてのケースをカバーできると思い込まないでください
  5. Playwright では device_scale_factor=1 を使用して 1x ピクセルを強制し、スクリーンショットがユーザーの 100% ズーム時の表示と一致するようにします
  6. グラフの描画には追加の待ち時間が必要です — Plotly、D3 などは非同期で描画されるため、networkidle 後に最低 4 秒待ちます
  7. 狭いビューポートにすると描画上のバグが見つかります — 枠線や配置の問題は、特定の幅でのみ発生することがあります

Web アプリ以外のスクリーンショット

Playwright では操作できないデスクトップアプリ(VS、WPF、WinForms、コンソールアプリ、ターミナル)の場合に使用します。

mss + ctypes(デスクトップウィンドウに推奨)

Win32 API でタイトルからウィンドウを検索し、mss でその領域を撮影します。撮影速度は約 33ms です。

import ctypes
from ctypes import c_int, Structure, byref, windll
import mss
from PIL import Image

user32 = windll.user32

def find_window(title_contains):
    """Find visible windows matching a title substring."""
    results = []
    WNDENUMPROC = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_void_p)
    def cb(hwnd, _):
        if user32.IsWindowVisible(hwnd):
            buf = ctypes.create_unicode_buffer(256)
            user32.GetWindowTextW(hwnd, buf, 256)
            if title_contains.lower() in buf.value.lower():
                results.append((hwnd, buf.value))
        return True
    user32.EnumWindows(WNDENUMPROC(cb), 0)
    return results

def capture_window(title_contains, output_path):
    """Capture a window by title substring."""
    windows = find_window(title_contains)
    if not windows:
        raise ValueError(f"No window matching '{title_contains}'")
    hwnd = windows[0][0]

    class RECT(Structure):
        _fields_ = [('left', c_int), ('top', c_int), ('right', c_int), ('bottom', c_int)]
    rect = RECT()
    user32.GetWindowRect(hwnd, byref(rect))
    w, h = rect.right - rect.left, rect.bottom - rect.top

    with mss.mss() as sct:
        shot = sct.grab({'left': rect.left, 'top': rect.top, 'width': w, 'height': h})
        img = Image.frombytes('RGB', shot.size, shot.rgb)
        img.save(output_path)
        return img

# Usage:
capture_window('Visual Studio Code', 'vscode-capture.png')

前提条件: pip install mss pillow 制限: ウィンドウが表示されている必要があります(ほかのウィンドウの背後に隠れていたり、最小化されていたりしてはいけません)。

Electron アプリ(VS Code など)

Node.js 版 Playwright のみ — Python 版 Playwright には electron API がありません。画面ではなく CDP(Chrome DevTools Protocol)経由で撮影するため、最小化中でも動作します。

const { _electron: electron } = require('playwright');
const app = await electron.launch({
    executablePath: 'C:\\Program Files\\Microsoft VS Code\\Code.exe',
    args: ['--new-window', '--disable-extensions', '--user-data-dir=' + tmpDir]
});
const window = await app.firstWindow();
await window.waitForLoadState('domcontentloaded');

// Minimize immediately — captures still work via CDP
await app.evaluate(({ BrowserWindow }) => {
    BrowserWindow.getAllWindows()[0].minimize();
});

await window.screenshot({ path: 'capture.png' }); // works while minimized!
await app.close();

重要: --user-data-dir=<temp> が必要です。これを指定しないと、VS Code は既存のインスタンスに処理を引き渡し、起動したプロセスがすぐに終了します。

判断の目安
シナリオツール備考
Web アプリ(localhost)Playwright実績があり、DOM 全体にアクセス可能
Electron アプリ(VS Code)Playwright Electron(Node.js)CDP 経由で最小化中も動作
デスクトップアプリ、ウィンドウが表示されているmss + ctypes(タイトルで検索)撮影速度は約 33ms
デスクトップアプリ、ウィンドウがほかのウィンドウの背後にあるWindows Graphics Capture API設定が複雑、Win10 1903 以降
すばやく全画面を撮影mss撮影速度は約 68ms

制限事項

  • Web の撮影には、ローカルで実行中のアプリか、アクセス可能な URL が必要です
  • デスクトップの撮影(mss)では、ウィンドウが表示され、遮られていない必要があります
  • Electron の撮影には Python ではなく Node.js 版 Playwright が必要です
  • クライアント側の描画が多い SPA では、networkidle 以外の独自の待機処理が必要になることがあります

コメント