🦔

Figma Plugin イメージと違う「PostMessage」と「messageイベント」を理解して、処理とUIで情報を橋渡しする

2022/07/12に公開

はじめに

FigmaのPluginを作成していく中で、名称と実際の動作イメージ勝ちがう概念がありました。
それが、「PostMessage」と「messageイベント」です。この概念について、簡単にまとめていこうと思います。

用語定義

  • 処理 = code.ts
  • UI = ui.html etc... 表示用のHTML側のScriptタグ

勘違いしていた点

名称から僕は以下のように、勝手なイメージを持っていました。

勘違いイメージ
「処理からpostMessageでUIに情報を送る」

しかし、実際にPluginを作っていくと、UIから処理に情報を渡したい状況も出てきました。
必要になって初めて自分の勘違いに気づきました。

実際は、以下が概念の理解として正解でした。

正解イメージ
「処理からもUIからも、postMessageで情報を投げることができて、処理もUIもmessageイベントでMessageを取得できる」

実際にMessage周りのコードの書き方

では、処理とUIそれぞれで、Messageを投げる・取得をどのように行うかを紹介します。

処理

メッセージをUIに送る

code.ts
/* figma限定を前提として */
if (figma.editorType === 'figma') {// postMessageよりも前に、UIを表示していないとErrorがThrowされる
    figma.showUi(__html__)
    ︙
    figma.ui.postMessage({type: "testMessage", body: "Hello World!"})}

メッセージをUIから受け取る

code.ts
/* figma限定を前提として */
if (figma.editorType === 'figma') {// おすすめは、Switch文
    // 今回は1例だが、何個も増えてくると効果大
    figma.ui.onmessage = message => {
        switch (message.type) {
            case 'inputHogeHoge':
	        console.log(message.body)
		break
        }
    }}

UI

処理からメッセージを受け取る

ui.html
<main>
    <p>My Plugin</p>
</main>

<script>
    window.addEventListener("message", (event) => {
        const message = event.data.pluginMessage
        
	// こちらもSwitch文おすすめ
	switch (message.type) {
	    case 'submitHogeHoge':
	        console.log(message.body) // Hello World!
		break
	}
    })
</script>

処理にメッセージを送る

ui.html
<main>
    <button onclick="submit()">送信!</button>
</main>

<script>
    const submit = () => {
	parent.postMessage({pluginMessage: {type: "submitHogeHoge", body: "hogehoge"}}, "*")
    }
</script>

ポイント

処理とUIでは、型の共有ができません(UIは純粋なJS)。したがってやり取りするメッセージの形式を型では制御できません。
また、UIから処理へpostMessageする際のオブジェクトは、pluginMessageというKeyに対してデータを定義する必要がありますが、処理からUIへpostMessageをする際は不要です。

まとめ

処理とUIでの双方向のデータのやりとりが理解できたことで、かなりスムーズに開発をすることができました。

関連記事
https://zenn.dev/takeru0430/articles/cd52887603d58e

Discussion