AdobeXDで要素のカラーコードを取得するプラグインを作ったときの備忘録

# はじめに
AdobeXDでプラグインを作成した際の手順を備忘録として残します。

# 仕様
以下仕様を満たすものを作成しました。

- 選択中の要素の塗りまたは境界線の色情報を取得し、クリップボードにコピーする
- 要素が選択されていない場合はアラートを表示し、以降の処理を停止する
- 複数の要素が選択されていた場合はアラートを表示し、以降の処理を停止する

# 成果物
ソースとプラグインはGithubで公開しているので、ご自由に参考にしてください。

- [ソース](https://github.com/InumberX/adobexd-plugin-get-element-color/tree/master/xdGetElementColor)
- [プラグイン](https://github.com/InumberX/adobexd-plugin-get-element-color/tree/master/plugin)

# 手順

## 開発準備

1. [こちらの記事](https://blogs.adobe.com/creativestation/web-getting-started-with-xd-plugin-development)の「3. 開発に必要なファイルを作成する」まで手順を実施し、プラグインを開発するための準備を整えます。

2. アラートを表示させるためのライブラリを[こちら](https://github.com/AdobeXD/plugin-samples/tree/master/how-to-display-an-alert)からダウンロードします。
手順1で作成したフォルダ内に「lib」フォルダを保存してください。

3. プラグインにアイコンを設定したい場合は、手順1で作成したフォルダ内に「images」フォルダを作成し、その中にアイコン画像を作成してください。

ここまでで、以下のようなディレクトリ構成になっていると思います。

```text
[手順1で作成したフォルダ]
  ∟[images]
  ∟[lib]
  ∟main.js
  ∟manifest.json
```

## 開発

1. manifest.jsonを以下のように記述します。

```json:manifest.json
{
  "name": "xdGetElementColor",
  "id": "XD_GET_ELEMENT_COLOR",
  "version":"1.0.0",
  "description":"選択中の要素のカラーコードを取得するプラグインです。",
  "icons":[
    {
      "width": 96,
      "height": 96,
      "path":"images/icon.png"
    }
  ],
  "host":{
    "app": "XD",
    "minVersion":"13.0.0"
  },
  "uiEntryPoints":[
    {
      "type":"menu",
      "label":"getElementColor",
      "commandId":"getElementColor",
      "shortcut": {
        "mac": "Cmd+Shift+O",
        "win": "Ctrl+Shift+O"
      }
    }
  ]
}
```

2. main.jsを以下のように記述します。

```js:main.js
/*
 * API・ライブラリ読み込み
 ****************************************/
// クリップボード
let clipboard = require('clipboard');
// dialogs.js
const { alert, error } = require('./lib/dialogs.js');

/*
 * 各処理
 ****************************************/
// 選択中の要素のカラーコードをコピーする処理
function getElementColor(selection) {

  // 選択中の要素
  const items = selection.items;

  // エラー時に表示されるダイアログのタイトル
  const errorAlertTitle = '処理に失敗しました';

  // 要素を1つだけ選択していた場合
  if(items.length === 1) {
    items.forEach(item => {
      let colorInfo;
      // 塗りの情報が取得できる場合
      if(item.fill !== null) {
        // カラーコードを16進数で取得
        colorInfo = item.fill.value.toString(16);
      } else if(item.stroke !== null) {
        // 境界線の情報が取得できる場合
        // カラーコードを16進数で取得
        colorInfo = item.fill.stroke.toString(16);
      } else {
        // 色の情報が取得できなかった場合
        showError(errorAlertTitle, '色情報の取得が取得できませんでした。')
        return false;
      }
      const colorCode = '#' + colorInfo.slice(2);
      // クリップボードにコピーする
      clipboard.copyText(colorCode);
    });
  } else if(items.length < 1) {
    // 要素を選択していなかった場合
    showError(errorAlertTitle, '要素が選択されていません。');
  } else if(items.length > 1) {
    // 複数の要素が選択されていた場合
    showError(errorAlertTitle, '複数の要素が選択されています。');
  }

}

// エラー用のダイアログを表示する処理
async function showError(title, text) {
  // ダイアログを表示する
  await error(title, text);
}

// manifest.jsonで定義したcommandIdとfunctionの紐付けを行なう
module.exports = {
    commands: {
        getElementColor: getElementColor
    }
};
```

**以下、各処理の説明**

まず初めに処理に必要なAPIやライブラリを読み込みます。

```js:main.js
/*
 * API・ライブラリ読み込み
 ****************************************/
// クリップボード
let clipboard = require('clipboard');
// dialogs.js
const { alert, error } = require('./lib/dialogs.js');
```

XDではプラグインを実行するときにselectionという変数が渡されます。
selection.itemの中に選択中の要素が配列で格納されているので、こちらを使用していきます。

```js:main.js
/*
 * 各処理
 ****************************************/
// 選択中の要素のカラーコードをコピーする処理
function getElementColor(selection) {

  // 選択中の要素
  const items = selection.items;

  // エラー時に表示されるダイアログのタイトル
  const errorAlertTitle = '処理に失敗しました';

  // 要素を1つだけ選択していた場合
  if(items.length === 1) {
    items.forEach(item => {
      let colorInfo;
      // 塗りの情報が取得できる場合
      if(item.fill !== null) {
        // カラーコードを16進数で取得
        colorInfo = item.fill.value.toString(16);
      } else if(item.stroke !== null) {
        // 境界線の情報が取得できる場合
        // カラーコードを16進数で取得
        colorInfo = item.fill.stroke.toString(16);
      } else {
        // 色の情報が取得できなかった場合
        showError(errorAlertTitle, '色情報の取得が取得できませんでした。')
        return false;
      }
      const colorCode = '#' + colorInfo.slice(2);
      // クリップボードにコピーする
      clipboard.copyText(colorCode);
    });
  } else if(items.length < 1) {
    // 要素を選択していなかった場合
    showError(errorAlertTitle, '要素が選択されていません。');
  } else if(items.length > 1) {
    // 複数の要素が選択されていた場合
    showError(errorAlertTitle, '複数の要素が選択されています。');
  }

}
```

アラート表示用のメソッドです。
第1引数がアラートの見出し、第2引数がアラートの本文になります。

```js:main.js
// エラー用のダイアログを表示する処理
async function showError(title, text) {
  // ダイアログを表示する
  await error(title, text);
}
```

このようなデザインで表示されました。

![xd_001.jpg](https://qiita-image-store.s3.amazonaws.com/0/191403/4211b362-6d7a-9953-27b4-a67d0b1eb483.jpeg)

manifest.jsonで定義した「commandId」で実行したいメソッドを紐付けます。

```js:main.js
// manifest.jsonで定義したcommandIdとfunctionの紐付けを行なう
module.exports = {
    commands: {
        getElementColor: getElementColor
    }
};
```

# 実行

1. [こちらの記事](https://blogs.adobe.com/creativestation/web-getting-started-with-xd-plugin-development)の「4. XDのプラグインメニューから実行する」から手順を実施することで、プラグインを実行できるようになるかと思います。

# 関連リンク
作成にあたり、以下サイトを参考にさせていただきました。
- [AdobeXDでCSSグラデーションを書き出すプラグインを作ってみた](https://qiita.com/amotarao/items/34eac3103f0c55b36233)
- [Adobe MAX 2018 XD Plugin API Labsでプラグインを作ってきた！](https://medium.com/@risayuguchi/max-2018-xd-plugin-api-lab-report-61b430e6b75e)
- [はじめてのAdobe XDプラグイン開発！定番のHello Worldを表示させてみよう](https://blogs.adobe.com/creativestation/web-getting-started-with-xd-plugin-development)
- [Adobe XD Platform](https://adobexdplatform.com)