Figma プラグインを作る時の Tips

6 min read読了の目安(約5500字

Figma のプラグインを作る時の注意点や生産性を上げる方法についてまとめてみます。

ライブラリ使ってもいいけどバンドルサイズには気をつけよう

どうも Figma のプラグインは実行される度にキャッシュは保持してくれず毎回 JS を一から実行しているっぽいのでバンドルサイズが膨らみすぎないように気をつけましょう。
Figmotion みたいな一回動いたら長く使う系では問題にならないですが、何回も繰り返し実行するタイプでは問題になります。

VSCode だとこういったプラグインを入れておくと「あ、これやばそう」と気づくことができます。

https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost

Figma 内でも開発者ツールを立ち上げられる

ブラウザと一緒で Command + Option + I です。
プラグインのランタイム error とか console.log とかはここに出力されるので絶対に覚えておきましょう。

Command + Option + P で最後に使ったプラグインを走らせることができるぞ

動作確認を繰り返し行う際に必須のショートカットなので覚えましょう。

modd を使って hot reload!

ちょっと上級者向けですが modd というツールを使ってホットリロードを実現することもできます。

https://github.com/cortesi/modd
https://twitter.com/sekikazu01/status/1247108967970435074

こんな感じの applescript.sh を用意して(上記のショートカットを実行する命令です)

#!/usr/bin/env bash

osascript <<'EOF'
tell application "Figma" to activate
tell application "System Events" to tell process "Figma"
    keystroke "p" using {command down, option down}
end tell
EOF

ソースコードが変わったらビルドして上記スクリプトを実行するコンフィグ modd.conf を書きます。

** !dist/** !lib/** !node_modules/** {
    prep: yarn build
    prep: ./applescript.sh
}

あとは package.jsonmodd コマンド書いて実行してあげればOKです。

...
"scripts": {
	"dev": "modd"
},
...

require() とかエラーになるのでコード分割したかったら webpack 使おう

これの流れに沿ってコピペしていけば何とかなるはずです。

https://www.figma.com/plugin-docs/bundling-webpack/

Plugin の型定義は @figma/plugin-typings

なぜか Figma 内部からプラグイン作った時にデフォでインストールされていないのですが、型定義は @figma/plugin-typings として存在します。

https://www.npmjs.com/package/@figma/plugin-typings

ドキュメントを読もう!

figma というグローバルなオブジェクトがあるのですが、それにどんなメソッドが生えているのかはここを見れば大丈夫です。

https://www.figma.com/plugin-docs/api/figma/

figma オブジェクトの mock

単体テストとかで動作確認できた方が生産性が高くなる日も来るでしょう。そんな時は figma オブジェクトが mock できたら嬉しいものですがなんと作ってくれている人がいました。感謝しましょう。

https://twitter.com/sekikazu01/status/1366394878410645508?s=20

font のスタイルを当てたい場合は loadFontAsync を使う必要がある

https://www.figma.com/plugin-docs/api/properties/figma-loadfontasync/

ちなみに下記は 「style は何でもいいから font-family だけ指定したら node にフォントのスタイル当てる」スニペットです。

const loadFont = async (font, node) => {
  let fontStyles = ['Regular', 'Book', 'Plain', 'Normal', 'Roman', 'Mono', 'Medium', 'Light', 'Italic', 'Bold', 'Semi Bold', 'Heavy'];
  for (let index = 0; index < fontStyles.length; index++) {
    try {
      await figma.loadFontAsync({family: font, style: fontStyles[index]})
      node.fontName = { family: font, style: fontStyles[index]};
      index = fontStyles.length;
    } catch(error) {
      console.log(error);
    }
  }
}

色を当てたい時は直接いじるとエラーが出るので代入する必要があるぞ

少しめんどくさいのですが、fill や stroke などの色を変更したい時は node.fills[0].color.r = ... みたいに直接変更することはできません。

色関連のプロパティは Readonly なので // error: Cannot assign to read only property 'r' of object みたいなエラーが出てくることでしょう。

https://www.figma.com/plugin-docs/editing-properties/

詳しくは上記ドキュメントを読んでいただければと思いますが、次のように代入する必要があります。

const text = figma.createText()
text.fills = [{ type: "SOLID" as const, color: props.color}]

RGB の値は 0-1 で指定

上記のように色を指定する時は RGB 型の color オブジェクトを代入する必要があります。

interface RGB {
	readonly r: number
	readonly g: number
	readonly b: number
}

これに 1 以上の値を指定すると次のようなエラーが出ます。

Error: in set_strokes: Expected "strokes.[0].color.r" to have value <= 1

RGB は 0-255 で慣れ切っているため違和感を覚えますが、普段使っている値を 255 で割れば大丈夫です。

// #999 = rgb(153, 153, 153) を指定する場合です。
const grayVal = 153 / 255
text.fills = [{ type: "SOLID" as const, color: { r: grayVal, g: grayVal, b: grayVal }}]

SVG を Figma ドキュメントに貼り付けたい時は createNodeFromSvg を使う

Figma に画像を貼り付けたい場合は一工夫が必要ですが、SVG の場合は createNodeFromSvg という関数を使うと Frame Node が返ってくるので、それを append してあげれば大丈夫です。

https://www.figma.com/plugin-docs/api/figma/#createnodefromsvg
const checkboxVector = figma.createNodeFromSvg(`<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M12.75 0.75H1.25C0.973437 0.75 0.75 0.973437 0.75 1.25V12.75C0.75 13.0266 0.973437 13.25 1.25 13.25H12.75C13.0266 13.25 13.25 13.0266 13.25 12.75V1.25C13.25 0.973437 13.0266 0.75 12.75 0.75ZM9.86719 4.71406L6.57656 9.27656C6.53057 9.34076 6.46994 9.39306 6.3997 9.42914C6.32946 9.46523 6.25162 9.48405 6.17266 9.48405C6.09369 9.48405 6.01586 9.46523 5.94561 9.42914C5.87537 9.39306 5.81474 9.34076 5.76875 9.27656L3.82031 6.57656C3.76094 6.49375 3.82031 6.37813 3.92188 6.37813H4.65469C4.81406 6.37813 4.96562 6.45469 5.05937 6.58594L6.17188 8.12969L8.62813 4.72344C8.72188 4.59375 8.87187 4.51562 9.03281 4.51562H9.76562C9.86719 4.51562 9.92656 4.63125 9.86719 4.71406V4.71406Z" fill="black"/>
    </svg>`)

Constraint で Right や Bottom を指定したかったら MAX を指定する

Constraint に指定できる型は次のようになっている。

type ConstraintType = "MIN" | "CENTER" | "MAX" | "STRETCH" | "SCALE"

horizontal と vertical で同じものを使っているので分かりづらいのだが、
horizontal の場合 MIN = Left、 MAX = Right
vertical の場合 MIN = Top、MAX = Bottom と考えれば良い。

なので、例えば Top, Right な Constraint を指定したい場合には次のように書く。

item.constraints = { vertical: "MIN", horizontal: "MAX" }

他の人のレポジトリを参考にしよう!

すでに世に公開されているプラグインの中には GitHub にレポジトリがあることが多々あります。私もあるプラグインと似た処理を行いたい時に参考にするのですが非常に有用です。

以下に例として幾つか貼って行きます。ちなみに探す時は該当のプラグインのページに行って GitHub へのリンクがないか見るのと(Support のところに URL がよく書いてたりします)GitHub内でプラグインの名前を検索して見つけます。(プラグインの名前に加えて figma をクエリに含めるとヒットしやすいです)

https://github.com/feathericons/figma-feather
https://github.com/iconify/iconify-figma
https://github.com/coryetzkorn/figma-faker

外部にリクエストを飛ばしたい時

UI スレッドの中から実行する必要があり、Figma のサンドボックス環境からはできません。
また、どうも fetch API は動かないみたいなので、 XMLHttpRequest を使います。

https://www.figma.com/plugin-docs/making-network-requests/