モダンなjsを使ってPhotoshopUXPサンプルコード書いた
PhotoshopUXPでサンプルプラグイン作りました。モダンなコードで書くとどんな感じのコードになるかのサンプルになります。内容はPhotoshopの雛形となるドキュメントを自動で生するプラグインです。ドキュメントを作成した後にレイヤーを作成したりガイドを引いたりしてドキュメントの雛形を作ってくれます。コード全体はこちらからご覧ください。
プラグインの概要
classからインスタンスを作成するとドキュメントを作成します。以下のようになります。
DocumentPreset classのコンストラクターに雛形の名前、幅、高さ、解像度、カラーモード、土台となるレイヤーの種類、ドキュメント作成後に配置するレイヤー群の配列(後に説明するがレイヤーの情報もclass化している),ガイドを引くピクセルの位置(配列)、各雛形の名前はhtml上でselectのoptionとして登録されます。
createボタンを押すとドキュメント作成が実行されます。なおご覧の通りhtmlとcssは最低限の構成になっています。
DocumentPreset class
最初にドキュメントの情報を保持するclassから。
コンストラクターで雛形となるドキュメントの情報を受け取ってcreateDocumentメソッドでドキュメントを作成します。なお実際にPhotoshopを動かすメソッドはUXPの場合ほとんどが非同期で処理され、Promiseを返す仕様となっているのでasync,awaitで処理しています。なおdocumentを作成するUXPのネイティブメソッドのcreateDocumentですが公式サイトを見るとオプションをオブジェクト形式で渡せます、が、オプションに関する詳細な記述がどこを見ても見当たらないためデフォルトのレイヤーの塗りのオプション、fillとカラーモードを指定するmodeプロパティはそれぞれ”transparent”と”RGBColorMode”以外にどのような値を渡せばいいかわかりませんでした。どうしてもという場合はBatchPlayで動かした方が早そう。createLayersメソッドは配列形式で渡されたレイヤー情報を元にそのまま再帰的にレイヤーを作成してゆきます。レイヤー情報もclass化しているのでまずはレイヤーのclassから説明します。
LayerObj classのコンストラクターはそれぞれlayer名、不透明度(デフォルト100%)をオプションとして受け取ります。typeはレイヤーのタイプ、createLayerメソッドで実際にレイヤーを作成します。この時Photoshop上で作成したレイヤーそのものの情報を後から使用するのでitSelfプロパティにPhotoshopのcreateLayerメソッドから返ってきたレイヤーオブジェクトを格納します。LayerSetObj classはLayerObjから継承されたgroup layerの情報を保持するclassです。group layerには子レイヤーの存在が必要なのでlayersプロパティに子レイヤーを配列受け取ります。尚LayerSetObjのlayersプロパティにLayerSetObjを入れてゆくとグループレイヤーを再起的にネスト化して作成し続けます。typeプロパティはオーバーライドして”layerSet”に、createLayerメソッドもオーバーライドしてグループレイヤーを作成するメソッドにしています。尚ネイティブのPhotoshopのcreateLayerメソッドのオプションも公式サイトで確認できます。これらのクラスを配列でDocumentPreset classに渡すのですが以下のようになります。
LayerObjとLayerSetObj classのインスタンスを配列に入れています。LayerSetObjの場合グループレイヤーに格納する子レイヤーが必要なのでさらにコンストラクターにLayerObj,LayerSetObjインスタンスを配列で渡しています。これを元にレイヤーを作成すると以下のようになります。
DocumentPreset classのcreateLayersメソッドに戻ります。
引数で受け取ったlayerの配列を元にPromiseAllで非同期でlayerをPhotoshop上に作成します。レイヤーのtypeが普通のlayerの場合はレイヤーを作成するだけですがlayerSetの場合はlayerSetの子レイヤーを先に作成、その後にlayerSet、それ自身を作成して作成する際のオプションのオブジェクトのfromLayersプロパティに引数のlayer配列を渡してレイヤーセットに格納するようにしています。ややこしいですが一応UXPの場合こういったやり方でないとネスト化したlayerを作成できませんでした、この辺jsxの方がわかりやすかった気がします。layerSetのcreateLayerのメソッドには作成したレイヤー自身のオブジェクトの配列を渡さないといけないのでmapメソッドでlayersのオブジェクトのitSelfプロパティを配列として渡すようにしています。次にcreateGuidesメソッドですがUXPには現状ガイドを引くメソッドはありません。なのでPhotoshopのDOMのprototypeを拡張したいと思います。詳しくはこちら。Photoshopのネイティブのメソッドはbatch Playで登録します。batch Playに関しては詳しくはこちら。batch Playには実際に登録したいPhotoshopのメソッドを配列、オブジェクトとして渡します。私の過去の記事も参照してください。とりあえず拡張したメソッドが以下になります。
引数に”vertical”か”horizontal”(縦か横)か指定してガイドを引く場所をnumber型で渡します。勿論非同期で実行。これをDocumentPresetのcreateGuidesメソッドで使います。
DocumentPresetのguidesプロパティには[[20,100],[40,50]]のように多重配列でガイドを引く位置が渡されます。最初の配列が縦位置、二つ目の配列が横位置なのでforのindexの値が0の場合は”vertical”を1の場合は”horizontal”を渡します。これが大体のPhotoshop側のコードになります。最後にhtmlのイベントのコードに移ります。
htmlは至ってシンプルです。
BatchPlayのコードやDocumentPresetのコード等もインポートしています。まずDocumentPresetインスタンスの格納されたdocs配列をforEachで各種オブジェクトのnameプロパティを取得してselectorのoptionとしてhtml要素を作成して配置しています。なので雛形のオブジェクトデータをdocs配列に格納すると自動でselectorに登録されます。create buttonを押した時にselectorで選んだ名前のオブジェクトからコードを実行してドキュメントを作成するようにしています。ButtonイベントはButtonElement classを作ってインスタンスを作成した瞬間にelmプロパティにクリックイベントを登録するようにしています。イベントの関数ではselectorのvalueを取得して取得した雛形の名前と同じオブジェクトをfindメソッドで探します。万が一見つからなかった場合はreturnで中止します。その後、ドキュメント作成、レイヤー作成、ガイド作成メソッドを順番に実行します。
コード全体はgit hubからご確認ください、