1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FigmaプラグインAdvent Calendar 2019

Day 9

Instanceを全て選択するFigmaプラグインを作ろう

Last updated at Posted at 2019-12-09

#はじめに
Figmaには特定のオブジェクトをライブラリ化するComponentという機能があります。
Componentを複製するとInstanceとなり、Componentに加えられた変更はInstanceにも反映されます。
progateの教材スライド制作では下図のようにスライドや画像のフォーマットなどをComponentにしています。
スクリーンショット 2019-12-09 21.52.18.png

Componentは効率が大きく上がる反面、リリース後の修正時に意図しない変更を取り込んでしまう可能性がありました。
Instanceを1つずつ選択してdetach(切り離し)を実行すれば良いのですが、数が多く諦めていました...がプラグインなら簡単にできます!

#やりたいことの確認
プラグイン開発においてdetach instance機能はComing Soonとのことでした(2019/12/9 現在)
▽Figma - What's Supported
https://www.figma.com/plugin-docs/whats-supported/
そこで、Instanceを全て選択状態にするプラグインを作ることにしました。

#コード

const selectedNodes: SceneNode[] = [];

figma.currentPage.children.forEach((item) => {
  findInstanceRecursively(item);
});

function findInstanceRecursively(item: SceneNode) {
  debugger;
  if (item.type === "INSTANCE") {
    // 本来はここでDetach Instanceを実行したいが、機能が提供されていないので選択する配列に追加するだけ
    selectedNodes.push(item);
  }
  // "INSTANCE"とその子の"INSTANCE"を選択しても親しか選択状態にできないが、
  // Detach Instance機能が提供されるようになる想定で再帰処理に含めておく
  if (item.type === "INSTANCE" || item.type === "GROUP" || item.type === "FRAME" || item.type === "BOOLEAN_OPERATION") {
    item.children.forEach((child) => {
      findInstanceRecursively(child);
    });
  }
}

figma.currentPage.selection = selectedNodes;

figma.closePlugin();

これを実行すると今のページのInstanceを全て選択できます。
スクリーンショット 2019-12-08 21.57.17.png
この状態でいつもどおり右クリックメニューからDetach InstanceをポチッとすればOKです。

#解説
##全レイヤーを検索するには再帰処理を使う
レイヤーは多重階層構造なので、どれだけ階層が深くなっても検索できるようにfindInstanceRecursively内でfindInstanceRecursivelyを呼び出す再起処理を行うようにしました。全レイヤー対象の検索系プラグインであれば大体必要になってくる処理だと思います。

開発中、間違えてitem自身を再起処理の対象にして無限ループを発生させてしまったのですが、スタックオーバーフローのエラーとなり止まってくれました。(どれだけスタックできるんだろう?)

##子を持ちうるレイヤーを再帰処理にかける
子要素を持つかどうかはChildrenMixin interfaceを実装しているかどうかで判断しました。
▽Figma - The Typings File
https://www.figma.com/plugin-docs/api/typings/
該当した下記4つのinterfaceが持つtypeを再起処理にかける条件としています。(2019/12/9 現在)

  if (item.type === "INSTANCE" || item.type === "GROUP" || item.type === "FRAME" || item.type === "BOOLEAN_OPERATION") {

##Instance内のInstanceは選択できない
Figmaの仕様で親要素が選択されていると子要素を選択できません。
Componentの作りが複雑で多重にComponentを含んでいると一回では選択しきれなので、一度detach instance実行後に再度プラグインを実行して選択しなければなりません。

detach instance機能がプラグインで使えるようになれば解決するので、それまでは待ちですね

#おわりに
Typescriptを初めて書きましたが、型が明確になっているので実装しやすいですね。
FigmaがThe Typings Fileを提供してくれているので、Figma固有の補完も効いて良い感じ!

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?