【Figma Plugins】Figma エディタで取得できるイベントまとめ

## はじめに
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/7d9d0eff-12f7-60b6-295a-faa62e4a8f51.png)

FigmaのPluginを開発する際、Figma Pluginsでイベントを取得したいと思ったことはありますか？
この記事では、Figma Pluginsからイベントを取得する方法を解説します。



## イベントを取得する構文
イベントを取得するには、以下のように`figma.on()` を使うことで、イベントを取得することができます。

```ts
figma.on(type: Type, callback:(event) => void)

/* 例 */
figma.on('drop', (event) => { /* イベントを取得した時に実行する処理 */ })
```

イベントを削除するには、`figma.off()` を使うことで、イベントを削除することができます。

```ts
figma.off(type: Type, callback:(event) => void)

/* 例 */
const fn = () => { /* イベントを取得した時に実行する処理 */ }
figma.on('drop', fn)
figma.off('drop', fn)
```

## 利用可能なイベント
利用できるイベントは以下の通りです。

+ `figma.currentPage` の値が変わった時
+ 現在のページで選択している要素が変更された時
+ ドキュメントが変更された時
+ テキストノードに入力しているときに定期的に発火する
+ Figma外のオブジェクトがキャンバスにドロップされた時
+ プラグインが閉じた時
+ プラグインが開始した時
+ スタイルが変更された時
+ タイマーが開始した時 <font color="gray">（Figjamのみ）</font>
+ タイマーが一時停止した時 <font color="gray">（Figjamのみ）</font>
+ タイマーが停止した時 <font color="gray">（Figjamのみ）</font>
+ タイマーが終了した時 <font color="gray">（Figjamのみ）</font>
+ タイマーが再開した時 <font color="gray">（Figjamのみ）</font>
+ タイマーの合計時間が変化した時 <font color="gray">（Figjamのみ）</font>

### ⚪︎ `figma.currentPage` の値が変わった時
`figma.currentPage` の値が変わった時に処理を行いたい時は、typeに `'currentpagechange'` を指定します。

```ts
figma.on('currentpagechange', () => { /* 処理 */ })
```

### ⚪︎ 現在のページで選択している要素が変更された時
現在のページで選択している要素が変更された時に処理を行いたい時は、typeに `'selectionchange'` を指定します。

```ts
figma.on('selectionchange', () => { /* 処理 */ })
```

### ⚪︎ ドキュメントが変更された時
ドキュメントが変更された時に処理を行いたい時は、typeに `'documentchange'` を指定します。

```ts
figma.on('documentchange', (event) => { /* 処理 */ })
```

コールバックには、以下のようなインターフェースの `DocumentChangeEvent` が渡されます。
```ts
interface DocumentChangeEvent {
  documentChanges: DocumentChange[]
}
```

`DocumentChangeEvent` には、`DocumentChange`の配列を持っており、`DocumentChange`には、6種類あります。

1. `'CREATE'`：ドキュメントにノードが作成された時
1. `'DELETE'`：ドキュメントからノードが削除された時
1. `'PROPERTY_CHANGE'`：ノードのプロパティが変更された時
1. `'STYLE_CREATE'`：ドキュメントにスタイルが追加された時
1. `'STYLE_DELETE'`：ドキュメントにスタイルが削除された時
1. `'STYLE_PROPERTY_CHANGE'`：スタイルのプロパティが追加された時

以下のタイミングの時には、イベントが発火しないので、注意が必要です。

+ ❌ `documentchange` のコールバック内で、変更が行なった時
+ ❌ インスタンスが更新された時
+ ❌ スタイル変更によって、ノードが更新された時

```sample.ts
/* 例 */
figma.on('documentchange', (event) => {
  for (const change of event.documentChanges) {
    switch (change.type) {
      case 'CREATE': /* 処理 */; break;
      case 'DELETE': /* 処理 */; break;
      ...
    }
  }
})
```

### ⚪︎ テキストノードに入力しているときに定期的に発火する
テキストノードに入力しているときに定期的に発火させたい時は、typeに`'textreview'` を指定します。

```ts
figma.on('textreview', (event) => {
    return new Promise((textReview) => {
      /* 処理 */ 
    })
  })
```

コールバックには、以下のようなインターフェースの `TextReviewEvent` が渡されます。
`TextReviewEvent`の `text` はノードに入力したテキストです。

```ts
interface TextReviewEvent {
  text: string
}
```

また、`'textreview'`では、`TextReviewRange` の配列を解決する非同期処理を返す必要があります。
`TextReviewRange` は、以下のようなインターフェースで、エラーまたは提案としてマークされるテキストを表します。

```ts
type TextReviewRange = {
  start: number
  end: number
  suggestions: string[]
  color?: 'RED' | 'GREEN' | 'BLUE'
}
```

+ `start`：範囲内の最初の文字のインデックス
+ `end`：範囲の最後の文字のインデックス
+ `suggestions`：範囲の候補を表す文字列の配列
+ `color`：下線の色

```sample.ts
figma.on('textreview', (event) => {
  return new Promise((textReview) => {

  const type: TextReviewRange = {
    start: 8,
    end: 9,
    suggestions: ["hoge", "huga"],
    color: 'RED'
  }

  textReview([type])
})
```

### ⚪︎ Figma外のオブジェクトがキャンバスにドロップされた時
Figma外のオブジェクトがキャンバスにドロップされた時、処理を行いたい時は、typeに `'drop'` を指定します。

```ts
figma.on('drop', (event) => { /* 処理 */ })
```

コールバックには、以下のようなインターフェースの `DropEvent` が渡されます。

```ts
interface DropEvent {
  node: BaseNode | SceneNode
  x: number
  y: number
  absoluteX: number
  absoluteY: number
  items: DropItem[]
  files: DropFile[]
  dropMetadata?: any
}
```

+ `node`：着地したノード
    + キャンバス内のどこにも着地しなかった場合、ノードがロックされている場合、別のノードの親になれない場合は、PageNodeになる
+ `x`・`y`：着地したノードの相対座標
+ `absoluteX`・`absoluteY`：着地したノードの絶対座標
+ `DropItem`：ドロップしたアイテムの非ファイルデータ型
    + text/html・text/uri-list など
+ `DropFile`：ドロップしたアイテムのファイルデータ型
    + image/pngなど


`DropEvent`のitemsの `DropItem` と `DropFile`は以下のようなインターフェースです。
```ts
interface DropItem {
  type: string // ドロップしたアイテムのファイルタイプ
  data: string
}

interface DropFile {
  name: string // ドロップしたアイテムのファイルネーム
  type: string // ドロップしたアイテムのファイルタイプ
  getBytesAsync(): Promise<Uint8Array> // ドロップしたアイテムのファイルサイズ
  getTextAsync(): Promise<string> // ドロップしたアイテムのUTF8エンコードされたテキスト
}
```

### ⚪︎ プラグインが閉じた時
プラグインが閉じた時に処理を行いたい場合は、typeに`'close'` を指定します。

このイベントは、`figma.closePlugin()` 関数によって、プラグインが閉じられる直前に発火します。
そのため、本当に必要な場合にのみ使用し、処理部分を最小のコードで実行する必要があります。

```ts
figma.on('close', () => { /* 処理 */ })
```

### ⚪︎ プラグインが開始した時
プラグインが開始した時に処理を行いたい場合は、typeに`'run'` を指定します。

```ts
figma.on('run', (event) => { /* 処理 */ })
```

コールバックには、以下のようなインターフェースの `RunEvent` が渡されます。
```ts
interface RunEvent {
  parameters?: ParameterValues
  command: string
}
```

+ `parameters`： 各パラメータに入力された値
+ `command`： `figma.command` と同じだが、便宜上ここでも提供する

### ⚪︎ スタイルが変更された時
スタイルが変更された時に処理を行いたい時は、typeに`'stylechange'`を指定します。

```ts
figma.on('stylechange', (event) => { /* 処理 */ })
```

コールバックには、以下のようなインターフェースの `StyleChangeEvent` が渡されます。

```ts
interface StyleChangeEvent {
  styleChanges: StyleChange[]
}
```

`StyleChangeEvent` には、`StyleChange` の配列を持っており、`StyleChange` には3種類あります。

1. `'STYLE_CREATE'`：ドキュメントにスタイルが追加された時
1. `'STYLE_DELETE'`：ドキュメントからスタイルが削除された時
1. `'STYLE_PROPERTY_CHANGE'`：スタイルのプロパティが変更された時


### ⚪︎ タイマーが開始した時 <font color="gray">（Figjamのみ）</font>
タイマーが開始した時に処理を行いたい場合、typeに`'timerstart'`を指定します。
このイベントは、ドキュメント内で誰かがタイマーを開始したときに実行されます。

```ts
figma.on('timerstart', () => { /* 処理 */ })
```

### ⚪︎ タイマーが一時停止した時 <font color="gray">（Figjamのみ）</font>
タイマーが一時停止した時に処理を行いたい場合、typeに`'timerpause'`を指定します。
このイベントは、実行中のタイマーが一時停止されたときに実行されます。

```ts
figma.on('timerpause', () => { /* 処理 */ })
```

### ⚪︎ タイマーが停止した時 <font color="gray">（Figjamのみ）</font>
タイマーが停止した時に処理を行いたい場合、typeに`'timerstop'`を指定します。
このイベントは、ドキュメント内で誰かがタイマーを開始したときに実行されます。

```ts
figma.on('timerstop', () => { /* 処理 */ })
```

### ⚪︎ `'timerdone'`：タイマーが終了した時 <font color="gray">（Figjamのみ）</font>
タイマーが終了した時に処理を行いたい場合、typeに`'timerdone'`を指定します。
このイベントは、タイマーが実行中で残り時間が 0 になると実行されます。

```ts
figma.on('timerdone', () => { /* 処理 */ })
```

### ⚪︎ タイマーが再開した時 <font color="gray">（Figjamのみ）</font>
タイマーが再開した時に処理を行いたい場合、typeに`'timerresume'`を指定します。
このイベントは、一時停止されたタイマーが再開されたときに実行されます。

```ts
figma.on('timerresume', () => { /* 処理 */ })
```

### ⚪︎ タイマーの合計時間が変化した時 <font color="gray">（Figjamのみ）</font>
タイマーの合計時間が変化した時に処理を行いたい場合、typeに`'timeradjust'`を指定します。
このイベントは、タイマーの合計時間が変化したときに実行されます。

```ts
figma.on('timeradjust', () => { /* 処理 */ })
```

## まとめ

この記事では、Figma Pluginsからイベントを取得する方法を解説しました。

ぜひこの記事を参考にFigma Pluginsからイベントを取得してみてください。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaで記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510