プラグインについて
次にプラグインの作り方を解説していきます。
せっかくなので最近追加されたVariablesを操作するプラグインを作ってみましょう。
初めに、ちょっと座学ですが、Figmaプラグインを作る際には「サンドボックススレッド」と「UI スレッド」の2つのコードが走る環境があり、開発していく時にはこれらを使い分けていくことが必要になります。
UIを使わなくていいプラグインもありますが、UIが必要がなくても「UIスレッドでしか実行できない処理のために非表示で実行する」なんてこともあります。
前者のサンドボックススレッドではFigmaのデータに触ることができます。対してUIスレッドでは、Figmaのデータには直接触れないですが、プラグインのUI(HTML+CSSで作る)の表示や、外部にリクエストを送ったり、ブラウザのAPIを使えたりします。
それぞれ役割とアクセスできるデータ・APIが違うので、それぞれで必要なものを交換しつつプログラミングしていきます。
サンドボックスからUIへのデータの渡し方
このように送ります。
figma.ui.postMessage({
type: "event",
data: "これを受け取って!",
});
そしたらUI側ではonmessageという関数で受け取りを検知できます。
<html>
<body>
<script>
onmessage = (event) => {
if (event.data.pluginMessage.type === 'event') {
// これを受け取って! がログ出力
console.log(event.data.pluginMessage.data)
}
};
</script>
</body>
</html>
UIからサンドボックスへのデータの渡し方
UIからはparent.postMessageという関数を使います。
<script>
parent.postMessage({ pluginMessage: { type: "hoge", content: "aaaaa" } }, '*');
</script>
そしてサンドボックスでは figma.ui.onmessage を使って通知を受け取ります。
export type MessageType = 'notify-something';
figma.ui.onmessage = (msg: { type: MessageType, content?: string }) => {
if (msg.type === 'notify-something') {
figma.notify('受け取ったぜ!');
figma.closePlugin();
}
};
それぞれで何ができて何ができないのかを理解して適切なコーディングに繋げるのが肝要です!ぜひ覚えておきましょう。
重要なスレッドたちについて確認したところで、次に実際にプラグインを作成してみましょう。
プラグインを作り始める手段はいくつかあるのですが、最もベーシックなやり方としてはFigmaの中から作成することです。
Figmaで何かしらのデザインファイルを開いて右クリックし、「プラグイン>開発>プラグインの新規作成」を選んでいくとミニマルなプロジェクトを作ることができます。
今回は、最近会社でお手製のスタイルだったものをVariablesに付け替える必要があったので、それを自動化するために作ってみたプラグインを題材に紹介してみます。
上記のFigmaのスターターは作成しただけだと、パッケージがインストールされていないので、まずはnpm installをしてください。
またnpm scriptとしてbuildとwatchがあり、watchの方はファイルの変更を検知してリビルドしてくれるため便利なので、開発中はこちらを実行しましょう。
ビルドしたプラグインはメニューバーのこちらのなんと表現すべきか分からないアイコンをクリックすると実行することができます。
今回はスタイルをVariablesに置き換えたいので、以下の2つの処理を書いてみます。
- Variables を取得
- ページ内のnodeを全部見ていってスタイルが適用されていたら同じ名前の Vairable に付け替える
まずは付け替える先の色のVariableを一通り取得します。
const COLLECTION_NAME = “colors”
const colorCollection = figma.variables.getLocalVariableCollections().find(collection => collection.name === COLLECTION_NAME)
if (!colorCollection) {
figma.notify(COLLECTION_NAME + "が読み込まれていません", {error: true})
}
const colorVariables = colorCollection?.variableIds.map((variableId) => {
return figma.variables.getVariableById(variableId)
})
function replaceStyleToVariable(node: SceneNode, style: BaseStyle | null, type: "fills" | "strokes") {
if (!style || style.type !== "PAINT" || skipStyle(style.name)) return
// Variable とスタイルの名前が同じ前提のコードですが、違う場合は適宜書き換える関数を書きましょう
const variable = colorVariables?.find(variable => variable?.name === style.name)
if (!variable) {
console.error("matching variable not found, style name: ", style.name)
return
}
// 背景色を Variable に付け替えます
if (type === "fills" && ("fills" in node) && Array.isArray(node.fills)) {
const fillsCopy = [...node.fills]
fillsCopy[0] = figma.variables.setBoundVariableForPaint(fillsCopy[0], 'color', variable)
node.fills = fillsCopy
}
// ボーダーの色も Variable に付け替えます
if (type === "strokes" && ("strokes" in node) && Array.isArray(node.strokes)) {
const fillsCopy = [...node.strokes]
fillsCopy[0] = figma.variables.setBoundVariableForPaint(fillsCopy[0], 'color', variable)
node.strokes = fillsCopy
}
}
// Figma の node はツリー状になっているため再帰的に呼び出します
function travarseNode(node: SceneNode) {
if ("fillStyleId" in node && typeof node.fillStyleId === "string") {
const style = figma.getStyleById(node.fillStyleId) as PaintStyle
replaceToVariable(node, style, "fills")
}
if ("strokeStyleId" in node && typeof node.strokeStyleId === "string") {
const style = figma.getStyleById(node.strokeStyleId) as PaintStyle
replaceToVariable(node, style, "strokes")
}
if ("children" in node) {
node.children.forEach(replaceStyleToVariable)
}
}
// ページ全体のオブジェクトを渡します
replaceStyleToVariable(figam.currentPage)
これだけのコードで全てのスタイルをVariablesに置き換えることができるようになりました! 人力でポチポチする苦労を考えると大事ですね...。
今回はとりあえず最近ホットなVariablesを扱うものを書いてみましたが、それ以外にもFigma上に存在するものは大体読めたり、作れたりするのでぜひプラグインのAPIリファレンスも眺めてみてください。
