mcpField
C
creator-plugin-development

creator-plugin-development

github.com/lottiefiles開発152 回インストール3 週間前に更新
リポジトリ

creator-plugin-development について

LottieFiles Creator のプラグイン開発者向けスキルです。シーンを操作するサンドボックスと React UI の分離構成を説明し、API やメッセージ通信の実践方法を扱います。

主な機能

  1. 01サンドボックスと UI の構成
  2. 02シーン、レイヤー、シェイプ操作
  3. 03キーフレームアニメーションの手法
  4. 04アセットのインポート方法
  5. 05型付きメッセージ通信
  6. 06開発・検証コマンド

活用シーン

  1. 01Creator プラグインのひな形作成
  2. 02シーン要素の作成やアニメーション化
  3. 03SVG、画像、Lottie アセットの読み込み
  4. 04UI とプラグイン間の通信障害の調査

インストール

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

$npx skills add https://github.com/lottiefiles/creator-plugin-skills --skill creator-plugin-development

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
architecture-and-communication.md
importing-assets.md
network-and-libraries.md
scene-graph-and-nodes.md
shapes-styling-animation.md
storage-and-events.md

詳細

Creator プラグインの開発

Creator プラグインは、アニメーション作成アプリケーションの LottieFiles Creator を拡張します。2 部構成のサンドボックスアーキテクチャを採用しています。

  1. プラグインサンドボックス(plugin/plugin.ts)— creator グローバル API にアクセスできる分離環境で実行されます。シーン、レイヤー、シェイプ、キーフレームを操作できます。ネットワークリクエストは実行できません。
  2. UI(src/)— iframe 内でレンダリングされる標準的な React アプリケーションです。fetch でネットワークリクエストを実行できます。creator API にはアクセスできません。

2 つの部分は、メッセージの送受信のみで通信します。

プロジェクト構成

my-plugin/
├── plugin/
│   ├── manifest.json          # Plugin metadata (id, name, apiVersion, entry, ui)
│   ├── plugin.ts              # Sandbox code — has `creator` API access
│   └── [helpers].ts           # Optional helper modules
├── src/
│   ├── main.tsx               # React DOM entry point
│   ├── app.tsx                # Main UI component
│   └── components/            # React components
├── vite.config.ts             # Uses @lottiefiles/vite-plugin-creator
├── tsconfig.json              # Root config with references
├── tsconfig.plugin.json       # Plugin sandbox TypeScript config (no DOM)
├── tsconfig.app.json          # UI TypeScript config (DOM + JSX)
├── index.html                 # Vite app template
└── package.json

tsconfig.plugin.json はサンドボックスコードをコンパイルします(DOM ライブラリは含まれません)。tsconfig.app.json は UI コードをコンパイルします(DOM と JSX を含みます)。

プラグインマニフェスト(plugin/manifest.json)では、プラグインの識別情報とエントリーポイントを定義します。

{
  "id": "unique-uuid-v4",
  "name": "My Plugin",
  "apiVersion": "1",
  "entry": "plugin.js",
  "ui": "ui.html"
}

開発コマンド

npm create @lottiefiles/creator-plugin@latest my-plugin  # Scaffold a new plugin

# From the plugin directory (e.g., plugins/my-plugin/):
npm run dev                                      # Start dev server with HTTPS hot-reload
npm run build                                    # TypeScript check + Vite production build
npm exec tsc -- -b                               # Type check (run before completing any task)

Creator で読み込むには、プラグイン > 開発 > 新しいプラグインを選択し、npm run dev で表示された localhost URL を入力します。

通信パターン(重要)

これは最もよくあるバグの原因です。メッセージのラップ方法は非対称です。

UI からプラグインへ
// In UI code (src/app.tsx) — MUST wrap in pluginMessage object
parent.postMessage(
  { pluginMessage: { type: 'create-shape', color: '#ff0000' } },
  '*'
);
プラグインがメッセージを受信する
// In plugin sandbox (plugin/plugin.ts) — messages arrive unwrapped
creator.ui.onMessage((msg) => {
  if (msg.type === 'create-shape') {
    // Use creator API here
  }
});
プラグインから UI へ
// In plugin sandbox — no wrapping needed
creator.ui.postMessage({ type: 'shape-created', layerId: layer.id });
UI がメッセージを受信する
// In UI code — messages arrive wrapped in pluginMessage
window.addEventListener('message', (event) => {
  const message = event.data.pluginMessage;
  if (message?.type === 'shape-created') {
    // Handle response
  }
});
型安全なメッセージ

コンパイル時に不一致を検出できるよう、共有メッセージ型を定義します。

// shared/types.ts
export type PluginMessage =
  | { type: 'create-shape'; color: string }
  | { type: 'import-svg'; content: string }
  | { type: 'delete-selection' };

リクエストとレスポンスを追跡するには、messageId フィールドを含めます。

主な API パターン

プラグインを初期化する
creator.ui.show({ width: 300, height: 500 });
シーンへのアクセス
const scene = creator.activeScene;
scene.size;        // { width, height }
scene.duration;    // seconds
scene.framerate;   // FPS
scene.layers;      // ReadonlyArray<Layer>
シェイプの作成
const layer = creator.activeScene.createShapeLayer();
const rect = layer.createRectangle({ size: { width: 200, height: 150 } });
layer.createFill({ type: 'SOLID', color: { r: 66, g: 133, b: 244 } });
アセットのインポート
// From URL
const anim = await scene.import({ type: 'LOTTIE', url: 'https://...' });
const img = await scene.import({ type: 'IMAGE', url: 'https://...' });
const svg = await scene.import({ type: 'SVG', url: 'https://...' });

// From content string
const svgLayer = await scene.import({ type: 'SVG', content: svgString });

// Audio, from a URL or base64 content
const audio = await scene.import({ type: 'AUDIO', content: base64Audio });

LOTTIE と SVG のインポートでは SceneLayer が返されます。IMAGE のインポートでは ImageLayer が返されます。AUDIO のインポートでは AudioLayer が返されます。インポートに失敗すると拒否されるため、scene.import() は try/catch で囲んでください。

プロパティのアニメーション
layer.position.addKeyframes([
  { frame: 0, value: { x: 100, y: 100 } },
  { frame: 60, value: { x: 400, y: 100 } },
]);

// With easing
const easeInOut = { type: 'CUBIC_BEZIER', x1: 0.42, y1: 0, x2: 0.58, y2: 1 };
layer.position.addKeyframes([
  { frame: 0, value: { x: 50, y: 100 }, easing: easeInOut },
  { frame: 60, value: { x: 350, y: 100 } },
]);
選択
const selectedNodes = creator.selection.nodes;

creator.on('selection:nodes', (nodes) => {
  creator.ui.postMessage({ type: 'selection-changed', count: nodes.length });
});
ノード型の確認

操作の前に必ずノード型を確認し、サポートしていない型はスキップしてください。scene.layers、creator.selection.nodes、selection:nodes、shapes、creator.assets は、インストール済みの API 型より新しい型を含め、プラグインが認識しない型を返すことがあります。references/scene-graph-and-nodes.md の「Unknown Node Types」を参照してください。

const layers = creator.selection.nodes;
layers.forEach((node) => {
  if (node.type === 'SHAPE_LAYER') {
    // Shape layer operations (has .shapes, .fills, .strokes, .trimPaths)
  } else if (node.type === 'IMAGE_LAYER') {
    // Image layer operations (has .image)
  } else if (node.type === 'SCENE_LAYER') {
    // Scene layer operations (has .scene, .break())
  } else if (node.type === 'TEXT_LAYER') {
    // Text layer operations (has .text, .fontFamily, .fontStyle, .fontSize,
    // .alignment, .fill/.createFill, .stroke/.createStroke)
  } else if (node.type === 'NULL_LAYER') {
    // Null layer operations (transform only, has .layers)
  } else if (node.type === 'AUDIO_LAYER') {
    // Audio layer operations (has .audio, .muted, .volume; no transform)
  }
  // Any other type: skip it
});

オーディオレイヤーにはトランスフォームがありません。scene.layers または選択範囲から取得したレイヤーの position、opacity、その他のトランスフォームメンバーを読み取る前に、その型を確認するか、creator.utils.isTransformableLayer(layer) を使用してください。references/scene-graph-and-nodes.md を参照してください。

ネットワークリクエスト

プラグインサンドボックスでは fetch リクエストを実行できません。次のパターンを使用してください。

  1. UI が外部 API からデータを取得する
  2. UI が parent.postMessage({ pluginMessage: ... }, '*') でプラグインにデータを送信する
  3. プラグインがデータを処理してシーンに適用する

完全な例については、references/network-and-libraries.md を参照してください。

よくある落とし穴

  1. pluginMessage ラッパーがない — UI からプラグインへのメッセージは、必ず { pluginMessage: { ... } } でラップする必要があります。プラグインから UI へのメッセージはラップ不要です。
  2. プラグインのサンドボックスから取得する — ネットワークリクエストは UI コードからのみ実行できます。fetch の呼び出しは src/ に移してください。
  3. localStorage/sessionStorage を使用する — サンドボックス化された iframe では、ブラウザーのストレージ API がブロックされます。代わりにプラグインコードから creator.clientStorage を使用してください。
  4. ノードの種類を確認しない — 種類固有のプロパティにアクセスする前に、必ず node.type を確認してください。
  5. アニメーション中のプロパティに staticValue を設定する — キーフレームがあるときに staticValue を設定しても、アニメーションには反映されません。先にキーフレームをクリアするか、キーフレームの値を直接変更してください。
  6. 図形が表示されない — 図形を表示するには、塗りつぶしかストロークが必要です。createRectangle() の後に createFill() を呼び出してください。
  7. スケール値はパーセンテージ — 100 はスケール 100%(1.0 ではありません)です。通常のサイズには { x: 100, y: 100 } を使用してください。
  8. 不透明度は 0~100 — 0~1 ではありません。完全に不透明にするには 100 を使用してください。
  9. 色の値は 0~255 — RGB チャンネルには、範囲 { r: 0-255, g: 0-255, b: 0-255 } の値を使用します。
  10. creator.ui.show() を早い段階で呼び出さない — plugin.ts の先頭で、メッセージハンドラーを設定する前に呼び出してください。
  11. UI の準備が整う前にメッセージを送信する — creator.ui.show() の直後に creator.ui.postMessage() を呼び出すと、iframe の読み込みが完了していないため、メッセージが破棄されます。「ui-ready」ハンドシェイクを使用してください。UI のマウント時に { type: 'ui-ready' } を送信し、プラグインはそのメッセージを受信してからデータを送信します。
  12. すべてのレイヤーにトランスフォームがあると想定する — オーディオレイヤーには visible、position、scale、rotation、opacity がありません。scene.layers を走査してこれらのメンバーを読み取るコードはコンパイルに失敗し、オーディオを含むプロジェクトでは実行時にもエラーになります。先に種類でフィルタリングし、処理しない種類はスキップしてください。

検証チェックリスト

タスクを完了とする前に、次を確認してください。

  • npm exec tsc -- -b を実行し、すべての型エラーを修正する
  • メッセージの流れをテストする:UI が送信 > プラグインが受信 > プラグインが応答 > UI が受信
  • ネットワークリクエストがプラグインのサンドボックスではなく、UI コードから実行されていることを確認する
  • 双方向の pluginMessage ラッパーが正しいことを確認する

リファレンスガイド

詳しい情報は、必要に応じて次のリファレンスファイルを参照してください。

リファレンス参照するタイミング
references/architecture-and-communication.mdアーキテクチャ、メッセージパッシングの完全な例、UI API の詳細を確認するとき
references/scene-graph-and-nodes.mdシーン階層、ノードの種類、走査パターンを確認するとき
references/shapes-styling-animation.md図形の作成、塗りつぶし/ストローク/グラデーション、キーフレーム、イージングを確認するとき
references/importing-assets.mdLOTTIE/SVG/IMAGE/AUDIO のインポート形式とパターンを確認するとき
references/storage-and-events.mdclientStorage、ノードデータ、選択イベント、タイムライン API を確認するとき
references/network-and-libraries.mdUI から取得するパターン、npm パッケージの使用方法を確認するとき

コメント