JavaScript、HTML、CSSを使用してSketchプラグインを作成する方法(パート1)

公開: 2022-03-10
簡単なまとめ↬Sketchを使用したことがある場合は、次のように考えた瞬間がたくさんある可能性があります。「Sketchだけがこの特定のことを実行できれば、手元のタスクを実行できるでしょう。はるかに速く、簡単に、そしてより良くなりました。」 さて、もうフレットはありません! この2部構成の記事では、独自のSketchプラグインを最初から作成する方法を学び、これらの種類の問題を正確に解決するために必要なスキルを習得します。

このチュートリアルは、Sketchアプリを知っていて使用していて、コードに手を出すことを恐れない人を対象としています。 それを最大限に活用するには、JavaScript(および、オプションでHTML / CSS)を作成するための基本的な経験が少なくともある程度必要です。

作成するプラグインは「モザイク」と呼ばれます。 パート1では、Sketchプラグインを構成する基本的なファイルについて学習します。 JavaScriptを記述し、HTMLとCSSを使用してプラグインのユーザーインターフェイスを作成します。 次の記事では、ユーザーインターフェイスをコアプラグインコードに接続する方法、プラグインの主な機能を実装する方法について説明します。最後に、コードを最適化する方法とプラグインの動作についても学習します。

また、プラグインのコード(JS、HTML、CSS)と、学習目的で調べて使用できるファイルを共有します。

スケッチプラグインとは何ですか、そしてそれらはどのように機能しますか?

Sketchでは、プラグインは「箱から出して」Sketchにはない機能を追加する方法です。 特定のプログラムにはほとんどの場合、機能や統合が欠けていることを考えると(特に、個々の設計者が持つ可能性のある膨大な数のニーズを考えると)、プラグインが特に便利で強力であることが想像できます。 スケッチプラグインは、レイヤーの色、形、サイズ、順序、スタイル、グループ化、効果の操作など、期待するほとんどすべてのことを実行できますが、インターネットリソースへのリクエスト、ユーザーの提示なども実行できます。インターフェイス、およびはるかに!

プログラミング側では、すべてのSketchプラグインはJavaScriptコードで記述されています。 まあ、実際には、それは完全に真実ではありません。 ほとんどのSketchプラグインはJavaScriptで記述されていると言った方が正確です。これは、JavaScriptの知識が少し必要な場合でも、Appleのプログラミング言語の1つであるObjective-CとSwiftでSketchプラグインを記述できるためです。

でも心配しないでください。 この記事では、JavaScript、HTML、およびCSSのみを使用してSketchプラグインを構築する方法に焦点を当てます。 HTML、CSS、またはJavaScriptの基本については説明しません。この記事では、これら3つすべてに関する知識と経験が少なくともある程度あることを前提としています。 MDN開発者のWebサイトは、Web開発についてさらに学ぶのに最適な場所です。

ジャンプした後もっと! 以下を読み続けてください↓

始めましょう!

まず、私たちは何を作っていますか?

このチュートリアルでは、レイヤーを作成、複製、変更できる基本的な初心者向けのプラグインを作成する方法と、ユーザーに優れたユーザーインターフェイスを提供する方法を説明します。 そうすることで、私の目標は、独自のプラグインを作成するために構築および使用できる基本的な知識を確立することです。

構築するプラグインはMosaicと呼ばれ、事実上「パターンジェネレーター」です。 レイヤーをフィードし、いくつかの設定を微調整すると、パターンが作成されます。

MosaicプラグインのUIを示す画像と、いくつかのパターン例。
MosaicのUI、およびそれを使用して作成されたパターンのいくつかの例。 (大プレビュー)

Mosaicをインストールして試してみたい場合は、完成したプラグインをGitHubからダウンロードできます。

ちょっとした歴史:Mosaicの大部分は、 Twist-and-Fadeと呼ばれる昔ながらのAdobeFireworksプラグインに触発されています。 ツイストアンドフェードは非常に強力で、色相、位置、回転、サイズ、不透明度を調整しながら、レイヤーを何度でも複製できました。 プラグインは、このようなアニメーションGIFを生成することもでき、カセットテープ内の2つの回転要素のフレームを作成しました。

回転ドラム付きの音楽カセットテープを示す画像
アニメーションカセットテープ(ソース)。 (大プレビュー)

(これがどのように機能するかを正確に確認したい場合は、ツイストとフェードのデモビデオをご覧ください。)

このチュートリアルの目的のために、Sketch用のやや類似したプラグインを構築しますが、チュートリアルにできるだけアクセスできるように意図的に簡略化しています。 具体的には、プラグインは次のことができるようになります。

  • スケッチレイヤー(ビットマップまたはベクター)を複製し、複製したレイヤーの位置、回転、不透明度を微調整します。 これにより、SketchのJavaScriptAPIを使用してレイヤーを操作する方法を紹介します。
  • HTML、CSS、およびJSを使用して作成されたユーザーインターフェイスを表示します。これにより、既に使い慣れているWebテクノロジを使用して、プラグインのインターフェイスを簡単に作成する方法がわかります。 プラグインインターフェイスは、ユーザーが結果のモザイク画像をどのように表示するかに関するユーザーの入力を収集する方法であるため、非常に重要です。

10秒フラットでベースプラグインを作成する

まず、構築するプラグインの「ベース」(またはテンプレート)を作成します。 プラグインを構成する必要なすべてのファイルとフォルダーを手動で作成できますが、幸いなことに、Sketchで作成できるため、作成する必要はありません。 テンプレートプラグインを生成した後、適切と思われるようにカスタマイズできるようになります。

テンプレートプラグインを作成するために使用できる非常に迅速で簡単な手法があります。これは、特定の瞬間に対処している問題を解決するためにプラグインをまとめる必要がある場合に、ほとんど私の頼りになる方法です。 仕組みは次のとおりです。

Sketchを開いた状態で、画面上部のメニューバーを確認し、[ Plugins -> Run Script ]をクリックします。 これにより、コードのテストと実行に使用できるダイアログボックスが開きます。 入力したコードをプラグインとして保存することもできます。これは、現在特に関心のある部分です。

このダイアログに既にあるコードをすべてクリアし、次のデモコードに置き換えます。

 const UI = require("sketch/ui"); UI.message(" Hey there, you fantastic plugin developer you! This is your plugin! Talking to you from the digital computer screen! In Sketch! Simply stupendous!");

次に、ウィンドウの左下にある[ Save Script as Plugin ]をクリックし、このプラグインに付ける名前(この場合は「モザイク」)を入力してから、もう一度[ Save Script as Plugin ]をクリックします。

ウィンドウの左下にある[保存]を押して、このプラグインに付ける名前を入力します。 (大プレビュー)

信じられないかもしれませんが、これで完了です。あとは、焼きたてのケーキを食べるだけです。 ここに楽しい部分があります。 プラグインメニューをもう一度開くと、次のようなものが表示されます。ブランドスパンキングの新しいプラグインが「モザイク」としてリストされています。 クリックして!

(大プレビュー)

おめでとうございます。最初のSketchプラグインを作成しました。

「モザイク」をクリックした後に表示されるのは、上の短いビデオのようになります。画面の下部に「Hey there…」という単語で始まる目立たないツールチップメッセージが表示されます。これは、貼り付けたコードが正確に示しているものです。やること。 これが、この手法を非常に優れたものにしている理由です。プラグインを最初から作成しなくても、コードの貼り付け、変更、テストが簡単になります。 ブラウザのWebコンソールに精通している、またはこれまでに遊んだことがある場合、これは基本的にそれです。 コードをビルドしてテストするときに、このツールをバックポケットに入れることは必須です。

追加したコードの機能を簡単に説明してみましょう。

まず、Sketchの組み込みJSライブラリのsketch/uiモジュールをインポートし、それをUI変数に割り当てます。 このモジュールには、いくつかの便利なインターフェイス関連のメソッドが含まれています。そのうちの1つを使用します。

 const UI = require("sketch/ui");

次に、 messageメソッド( sketch/uiモジュールの一部)を呼び出し、表示したいツールチップに表示したいテキストの文字列を使用します。

 UI.message(" Hey there, you fantastic plugin developer you! This is your plugin! Talking to you from the digital computer screen! In Sketch! Simply stupendous!");

message()メソッドは、目立たないメッセージをユーザーに提示するための優れた方法を提供します。 フォーカスを盗む必要がなく(非モーダル)、派手なボタンやテキストフィールドが必要ない場合に最適です。 アラートやプロンプトなどの一般的なUI要素を表示する方法は他にもあります。これらのいくつかは、Mosaicを構築するときに使用します。

プラグインのメタデータのカスタマイズ

これで基本的なプラグインから始めることができますが、それでもさらに微調整して、本当に私たちのものにする必要があります。 次のステップは、プラグインのメタデータを変更することです。

このステップでは、プラグインバンドルと呼ばれるものを確認する必要があります。 [スクリプトの実行]ウィンドウで[保存]をクリックすると、SketchはプラグインをMosaic.sketchpluginという名前のフォルダーとして保存しました。このフォルダーは~/Library/Application Support/com.bohemiancoding.sketch3/Pluginsディレクトリにあります。 それは少し長く、覚えておくのが面倒です。 ショートカットとして、 Plugins -> Manage Plugins -> (right-click your plugin) -> Reveal Plugins Folderからプルアップすることもできます。 Finderでは単一のファイルとして表示されますが、実際には、プラグインがSketchで実行するために必要なすべてのものを含むフォルダーです。 フォルダであるにもかかわらず単一のファイルとして表示される理由は、Sketchを最初にインストールしたときに、Sketchが.sketchplugin拡張子を「バンドル」(ファイルとして表示される特殊な種類のフォルダ)として登録し、自動的に開くように要求したためです。開いたときにSketchで。

中を覗いてみましょう。 Mosaic.sketchpluginを右クリックし、[パッケージの内容を表示]をクリックします。 内部には、次のディレクトリ構造が表示されます。

 Contents/ └ Resources/ └ Sketch/ └ manifest.json └ script.cocoascript

拡張子が.cocoascriptのファイルがそこにあるのはなぜか疑問に思われるかもしれません。 心配しないでください。これは通常のJavaScriptファイルであり、前に入力したコードのみが含まれています。 先に進み、このファイルの名前をindex.jsに変更します。これにより、ディレクトリ構造が次のように変更されます。

 Contents/ └ Resources/ └ Sketch/ └ manifest.json └ index.js

プラグインバンドル内のファイルを整理する最も一般的な方法は次のとおりです。コード(JavaScript)とmanifest.jsonSketch/に属し、リソース(画像、オーディオファイル、テキストファイルなど)はResources/に属します。

まず、 manifest.jsonという名前のファイルを微調整しましょう。 Visual StudioCodeやAtomなどのお気に入りのコードエディター内で開きます。

現時点では、ここの内部は比較的少ないことがわかりますが、すぐに追加します。 プラグインマニフェストは、主に2つの目的を果たします。

  1. まず、プラグインを説明するメタデータ(名前、バージョン、作成者の名前など)をユーザーに提供します。 Sketchは、 Sketch -> Preferences -> Plugins ]ダイアログでこの情報を使用して、プラグインのリストと説明を作成します。
  2. 第二に、それはまたあなたのビジネスに取り掛かる方法についてスケッチに伝えます。 つまり、プラグインのメニューをどのように表示するか、プラグインに割り当てるホットキー、およびプラグインのコードが存在する場所(Sketchが実行できるようにするため)をSketchに指示します。

プラグインをユーザーに説明する目的#1を考えると、現時点では説明作成者が指定されていないことに気付くでしょう。これはユーザーを混乱させ、プラグインの識別を困難にします。 関連するキーの値を次のように調整して、これを修正しましょう。

 { "description": "Generate awesome designs and repeating patterns from your layers!", "author": "=> Your name here <=" }

次に、プラグインの識別子を調整しましょう。 この識別子は、「サイトのドメインを取得し、順序を逆にして、最後に製品名を付ける」という非常に簡潔な(または退屈な、選択した)方法である、いわゆる「逆ドメイン表記」を使用します。 これはcom.your-company-or-your-name-its-not-that-big-a-deal.yourproductます。

この命名規則に固執する必要はありません。他のプラグインとの競合を回避するのに十分な一意性がある限り、ここに好きなものを置くことができます(ただし、特にRDN形式に固執することをお勧めします。プラグイン識別子用のシンプルで再利用可能なシステム)。

そのためには、識別子をcom.your-name.mosaicに変更します。

 { "identifier": "com.your-name.mosaic" }

私は個人的に、メタデータに関連するすべてのキー(タイトル、作成者、識別子など)を取得し、マニフェストの上部近くにグループ化して、それらがいたるところに広がらないようにし、必要なときに正気を保つのに役立てたいと思っています。 。

次に、 menucommandsキーを見てみましょう。 これら2つは、Sketchにどのコードを呼び出すか、そして何に応答するかを指示する責任があります。

menuキーを見ると、 titleキーが含まれていることがわかります。その値は、プラグインがPluginsメニューに表示される名前です。 また、コマンド識別子のリストであるitemsキーもあります。

 { "menu": { "title": "Mosaic", "items": [ "com.bohemiancoding.sketch.runscriptidentifier" ] } }

現在、このリストには"com.bohemiancoding.sketch.runscriptidentifier" 1つのコマンド識別子しかありません。 コマンドIDは、常にcommandsリスト内のコマンドを指します。 現在、プラグインには1つのコマンドしかありません。これは、次の識別子を持つコマンドです。

 { "commands": [ { "script" : "script.cocoascript", "name" : "Mosaic", "handlers" : { "run" : "onRun" }, "identifier" : "com.bohemiancoding.sketch.runscriptidentifier" } ] }

menuエントリにコマンド識別子を追加するたびに、Sketchはその識別子を持つコマンドエントリを検索し、そのnameキー(この場合は「Mosaic」)の値を表示し、代わりにプラグインのメニューに表示します識別子の。

コマンドが果たす役割については、コマンドエントリは、プラグインのJavaScriptコードで、そのコマンドが呼び出されたときに実行する関数をSketchに指示する方法と考えることができます。「呼び出し」は通常、ユーザーが関連メニューをクリックすることです。アイテム。 コマンドエントリはそれ自体では何もしません。JSONだけです。コマンドが呼び出されたときに実行する必要のあるJavaScriptを探す場所をSketchに説明するだけです。

これまで、コマンドのnameキーとidentifierキーの機能について説明してきましたが、コマンドには、 scripthandlersという2つのキーを指定する必要があります。

scriptキーは、実行するJavaScriptファイルの場所をSketchに指示します。 問題のスクリプトファイルがSketch/フォルダーにあると、Sketchがどのように想定しているかに注意してください。そのため、簡単にするために、すべてのJavaScriptコードがSketch/フォルダーの下にあることを確認する必要があります。 このキーから先に進む前に、前にファイルの名前を変更したのと同じように、このキーの値をindex.jsに変更することを確認することが重要です。 そうしないと、SketchはJavaScriptファイルを見つけて実行できません。

handlersキーの値は、JavaScriptで呼び出す関数を決定するためにSketchが調べるものです。 ここでは、ハンドラーセットが1つだけありますrun 、値はonRunです。 runは、事前定義された組み込みのSketchアクションの名前です。 このrunアクションは、ユーザーがこのコマンドを参照するメニュー項目をクリックすると常に呼び出されます。 onRunは、自動生成されたscript.cocoascriptファイル( index.jsに名前を変更)内の関数の名前であり、 runイベントが発生したとき、つまりユーザーがメニュー項目をクリックしたときに呼び出される関数です。

これまでの例では、このプロセスは次のようになります。

  1. ユーザーがメニュー項目をクリックします。
  2. Sketchは、そのメニュー項目に関連付けられているコマンドを見つけます。
  3. Sketchは、コマンドが参照するスクリプトファイルを見つけて実行します(この場合、 index.jsでJavaScriptを実行します)。
  4. このコマンドはメニュー項目のクリックによって呼び出されたため、 runアクションと見なされます。 つまり、Sketchは、次に呼び出す関数(この場合はonRun )のコマンドのhandlers.run値を調べます。
  5. SketchはonRun関数を呼び出します。

コマンドは、ユーザーがメニュー項目の1つをクリックしたことに応答して呼び出されるのが最も一般的ですが、ユーザーが選択範囲やレイヤーのプロパティを変更するなど、他のユーザーアクションに応答して呼び出すこともできます。 ただし、このプラグインでは、これらの他のアクションは使用しません。 (アクションとその動作について詳しくは、Action APIヘルプページをご覧ください。)

このマニフェストから先に進む前に、他に2つの調整を行います。 現在、メニューの構造は次のとおりです。

 Mosaic └ Mosaic 
Mosaicという名前の別のメニュー内に冗長にネストされたMosaicメニュー項目を示す画像
かなり冗長ですよね? (大プレビュー)

…プラグインにはメニュー項目が1つしかないため、これは少し冗長です。 また、プラグインを呼び出すのに1回ではなく2回クリックするようになったため、ユーザーに少し不必要な摩擦が加わります。 これを修正するには、 menuisRoot: trueを追加します。

 { "menu": { "title" : "Mosaic", "items" : [ "com.bohemiancoding.sketch.runscriptidentifier" ], "isRoot": true } }

これにより、Sketchは、メニューのtitleの下にネストするのではなく、 Pluginsメニューのすぐ下に最初のレベルのメニュー項目を配置するように指示されます。

保存を押してSketchに戻ります。 これで、 Mosaic -> MosaicMosaicだけに置き換えられたことがわかります。完璧です。

MosaicプラグインのUIを示す画像
MosaicのUI。 (大プレビュー)

2番目の調整については、先に進んで、このコマンド識別子の名前を扱いにくいものに変更しましょう。 コマンド識別子は個々のプラグインのコンテキスト内で一意である必要があるだけなので、 "open"のように、より簡潔でわかりやすい名前に安全に名前を変更できます。

 { "commands": [ { ... "identifier" : "open" } ], "menu": { ... "items" : [ "open" ] } }

先に進む前に、メニューに他のメニューも含めることができることに注意してください。 別のメニューのitemsリスト内に別の{ title: ..., items: ... }エントリをネストすることで、サブメニューを簡単に作成できます。

 { "menu": { "title" : "Mosaic", "items" : [ "open", { "title" : "I'm a sub-menu!", "items" : [ "another-command-identifier" ] } ] } }

プラグインのユーザーインターフェイスの構築

これまでに、いくつかのデモコードを記述し、プラグインのマニフェストをカスタマイズしました。 次に、ユーザーインターフェイスの作成に移ります。これは、基本的にウィンドウに埋め込まれたWebページです(使い慣れたブラウザーと同様)。

プラグインのウィンドウ。 (大プレビュー)
プラグインのインターフェースを構成するコンポーネントを示す画像:ウィンドウとWebビュー
プラグインを構成するコンポーネント。 (大プレビュー)

Mosaicのユーザーインターフェイスデザインには独自のウィンドウがあり、これを最も基本的なコンポーネントと見なすことができます。 それから始めましょう。 ウィンドウを作成して表示するには、デフォルトでmacOSに組み込まれているNSWindowというクラスを使用する必要があります。 このチュートリアルの残りの部分では、実際にこれをかなり実行します( NSWindowなどの組み込みAPIを使用)。これは、慣れていない場合は少し気が遠くなるように思えるかもしれませんが、心配しないでください。説明します。途中ですべて!

注:組み込みのAPIについて話している間、このクラス使用できる理由は、Sketchプラグインで使用されるJavaScriptランタイムに存在するブリッジのおかげです。 このブリッジは、通常はネイティブアプリケーションでのみ使用できるこれらの組み込みクラス、メソッド、および関数を自動的にインポートします。

コードエディタでSketch/index.jsを開き、すでに存在するものを削除して、次のように貼り付けます。

 function onRun(context){ const window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_( NSMakeRect(0, 0, 145, 500), NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false ); window.releasedWhenClosed = false; window.makeKeyAndOrderFront(nil); };

コードのこの最初のビットが何をするかを見てみましょう:

 function onRun(context){

コマンドとその機能について話し、メニュークリックに応答して呼び出すようにonRunに指示したときのことを覚えていますか? (復習が必要な場合は、上記の部分に戻ってから戻ってください。)このビットが行うのは、その関数を作成することだけです。 また、 onRun関数がcontext引数を取ることに気付くでしょう。 これは、Sketchがコマンドハンドラーを呼び出す引数であり、特定の情報を提供できます。 後で、ユーザーのコンピューターでプラグインバンドルのURLを取得するために使用します。

 const window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer( NSMakeRect(0, 0, 145, 500), NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false );

ここでは、実際にいくつかのことを行っています。

  1. まず、 NSWindowalloc()を呼び出します。 これは基本的に「NSWindowのインスタンス用にメモリを確保する」ことを意味します。 作成するネイティブクラスのすべてのインスタンスに対してこれを行う必要があることを知っておくだけで十分です。 allocメソッドは、すべてのネイティブクラスで使用できます。
  2. 次に、 NSWindowの初期化メソッド(つまり、 NSWindowのインスタンスを実際に作成するメソッド)を呼び出します。このメソッドは、 initWithContentRect:styleMask:backing:defer:という名前です。 上記のコードで呼び出すものとは異なることに気付くでしょう—すべての引数の間にコロン( :がたくさんあります。 JavaScriptではその構文を使用できないため、Sketchは、コロンをアンダースコアに置き換えることで実際に使用できるものに名前を変更します。これにより、JS名がinitWithContentRect_styleMask_backing_deferになります。
  3. 次に、メソッドに必要な各引数を渡します。 最初の引数contentRectには、ユーザーインターフェイスに十分なサイズの長方形を指定します。
  4. styleMaskの場合、ウィンドウに閉じるボタンとタイトルバーを設定し、サイズを変更できるようにすることを示すビットマスクを使用します。
  5. 次の2つの引数、 backingdeferは、常にNSBackingStoreBufferedfalseに設定されるため、これらについて心配する必要はありません。 (このメソッドのドキュメントでは、これがなぜであるかについてさらに詳しく説明しています。)
 window.releasedWhenClosed = false; window.makeKeyAndOrderFront(null);

ここでは、 NSWindowreleasedWhenClosedプロパティをfalseに設定します。これは、次のことを意味します。 ユーザーがウィンドウを閉じたからといって、このウィンドウをメモリから削除しないでください。」 次に、 makeKeyAndOrderFront (null)を呼び出します。これは、「このウィンドウを最前面に移動し、キーボードフォーカスを与える」ことを意味します。

Webビュー:インターフェイス

簡単にするために、使用するプラグインのWebユーザーインターフェイスのHTMLおよびCSSコードをすでに作成しました。 追加する必要がある残りのコードは、Sketchプラグインコードと通信できるようにすることだけです。

次に、HTMLおよびCSSコードをダウンロードします。 ダウンロードしたら、解凍して、「web-ui」という名前のフォルダーをプラグインのResourcesフォルダーに移動します。

実際のHTML / CSSコードの記述と最適化は、プラグインのコア機能を強化するJavaScriptに焦点を当てているため、このチュートリアルの範囲外です。 しかし、もっと知りたい場合は、このトピックに関するチュートリアルがWeb上にたくさんあります。

今すぐプラグインを実行すると、ウィンドウが表示されます。 しかし、それは空で、タイトルがなく、まだ特に有用ではありません。 Webインターフェイスを表示するために取得する必要があります。 そのためには、別のネイティブクラスであるWKWebViewを使用する必要があります。これは、Webコンテンツを表示するために特別に作成されたビューです。

ウィンドウ用に作成したコードの下に、 WKWebViewを作成するために必要なコードを追加します。

 function onRun(context){ // Create window const window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer( NSMakeRect(0, 0, 145, 500), NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false ); window.releasedWhenClosed = false; // Create web view, and set it as the view for our window to display const webView = WKWebView.alloc().init(); window.contentView = webView; // Load our UI into the web view const webUIFolderURL = context.scriptURL .URLByDeletingLastPathComponent() .URLByAppendingPathComponent("../Resources/web-ui/"); const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html"); webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL); // Make window key and move to front window.makeKeyAndOrderFront(nil); };

プラグインを実行すると、Webユーザーインターフェイスを表示するウィンドウが開いていることがわかります。 成功!

繰り返しますが、先に進む前に、追加したコードが何をするかを調べてみましょう。

 const webView = WKWebView.alloc().init();

これは見覚えがあるはずです。基本的には、 NSWindowを作成したときと同じです。Webビューにメモリを割り当ててから、初期化します。

 window.contentView = webView;

このコード行は、作成したWebビューを表示するようにウィンドウに指示します。

 const webUIFolderURL = context.scriptURL .URLByDeletingLastPathComponent() .URLByAppendingPathComponent("../Resources/web-ui/");

ここでの目標は、前に作成したweb-uiフォルダーを指すURLを作成することです。 そのURLを取得するには、プラグインのバンドルがユーザーのファイルシステムのどこにあるかを把握する方法が必要です。 ここでは、現在実行中のスクリプトのURLを提供するcontext.scriptURLプロパティを使用します。 ただし、これでは期待どおりのJavaScript Stringは得られませんが、URL文字列の操作を容易にするいくつかのメソッドを持つネイティブクラスNSURLのインスタンスが提供されます。

context.scriptURLが提供するものを変える必要があります—

 file://path-to-your-plugin/Contents/Sketch/index.js

- の中へ:

 file://path-to-your-plugin/Contents/Resources/web-ui/

ステップバイステップ:

  1. 初めてURLByDeletingLastPathComponent()を呼び出すと、 file://path-to-your-plugin/Contents/Sketch/が得られます。
  2. URLByDeletingLastPathComponent()を再度呼び出すとfile://path-to-your-plugin/Contents/が得られます。
  3. 最後に、 URLByAppendingPathComponent ("Resources/web-ui/")を使用してResources/web-ui/を最後に追加すると、 file://path-to-your-plugin/Contents/Resources/web-ui/が得られます。

また、 index.htmlファイルを直接指す2番目のURLを作成する必要があります。

 const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html");

最後に、Webビューにindex.htmlをロードして、 web-uiフォルダーのコンテンツへのアクセスを許可するように指示します。

 webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL);

大丈夫。 これまでのところ、必要に応じてWebユーザーインターフェイスを表示するウィンドウがあります。 ただし、まだ完全ではありません。元のデザインにはタイトルバー(または「クローム」)がありませんが、現在のウィンドウにはあります。 また、Sketchドキュメント内をクリックすると、そのドキュメントがウィンドウの前に移動するという事実もありますが、これは私たちが望んでいることではありません。ユーザーがプラグインウィンドウSketchドキュメントを操作しなくても操作できるようにする必要があります。常に1つのウィンドウから別のウィンドウに焦点を合わせ直します。

これを修正するには、最初にデフォルトのウィンドウクロームを削除し、ボタンのみを保持する必要があります。 以下の2行のコードを追加すると、タイトルバーが削除されます。

注:以前と同様に、以下で使用しているすべてのプロパティとメソッドは、 NSWindowのドキュメントページに記載されています。

 window.titlebarAppearsTransparent = true; window.titleVisibility = NSWindowTitleHidden;

次の2行のコードでは、不要なウィンドウボタン(MacOS用語では「信号機」とも呼ばれます)が削除され、「ズーム」と「最小化」が削除され、「閉じる」ボタンのみが残ります。

 window.standardWindowButton(NSWindowZoomButton).hidden = true; window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;

その間、ウィンドウの背景色をWebUIの背景色と一致するように変更してみましょう。

 window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);

次に、フローティングプラグインウィンドウを他のウィンドウの上に保持するために何かを行う必要があります。これにより、ユーザーはMosaicのウィンドウが消えることを心配せずにSketchドキュメントを操作できます。 これには、 NSPanelと呼ばれる特別なタイプのNSWindowを使用できます。これは、他のウィンドウの「上にとどまる」ことができます。 これに必要なのは、 NSWindowNSPanelに変更することだけです。これは、1行のコード変更です。

 const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(

次に、パネルウィンドウをフロートさせ(他のすべての上にとどまる)、必要な場合にのみキーボード/マウスのフォーカスを取得するように指示します。

 window.floatingPanel = true; window.becomesKeyOnlyIfNeeded = true;

ウィンドウを微調整して、最後の位置で自動的に再び開くようにすることもできます。

 window.frameAutosaveName = "mosaic-panel-frame";

この行は基本的に、「キーmosaic-panel-frame下にSketchの設定で保存して、このウィンドウの位置を覚えておいてください」と言っています。

これで、次のコードが完成しました。

 function onRun(context){ // Create window const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer( NSMakeRect(0, 0, 145, 500), NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false ); window.becomesKeyOnlyIfNeeded = true; window.floatingPanel = true; window.frameAutosaveName = "mosaic-panel-frame"; window.releasedWhenClosed = false; window.standardWindowButton(NSWindowZoomButton).hidden = true; window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true; window.titlebarAppearsTransparent = true; window.titleVisibility = NSWindowTitleHidden; window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1); // Create web view, and set it as the view for our window to display const webView = WKWebView.alloc().init(); window.contentView = webView; // Load our UI into the webview const webUIFolderURL = context.scriptURL .URLByDeletingLastPathComponent() .URLByAppendingPathComponent("../Resources/web-ui/"); const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html"); webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL); // Make window key and move to front window.makeKeyAndOrderFront(nil); };

コードの整理

次のパートに進む前に、コードを整理して、ナビゲートや調整が簡単になるようにすることをお勧めします。 追加するコードはまだたくさんあり、 index.jsがすべてのコードの厄介なダンプグラウンドになるのを避けたいので、少し分割して、UI固有のコードをui.jsという名前のファイルに移動しましょう。 Sketchフォルダの下。 また、Webビューやウィンドウの作成など、実行するUIタスクの一部を独自の関数に抽出します。

ui.jsという名前の新しいファイルを作成し、その中に以下のコードを挿入します。

 // Private var _window; function createWebView(pageURL){ const webView = WKWebView.alloc().init(); webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent()); return webView; }; function createWindow(){ const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer( NSMakeRect(0, 0, 420, 646), NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false ); window.becomesKeyOnlyIfNeeded = true; window.floatingPanel = true; window.frameAutosaveName = "mosaic-panel-frame"; window.releasedWhenClosed = false; window.standardWindowButton(NSWindowZoomButton).hidden = true; window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true; window.titlebarAppearsTransparent = true; window.titleVisibility = NSWindowTitleHidden; window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1); return window; }; function showWindow(window){ window.makeKeyAndOrderFront(nil); }; // Public function loadAndShow(baseURL){ if(_window){ showWindow(_window); return; } const pageURL = baseURL .URLByDeletingLastPathComponent() .URLByAppendingPathComponent("../Resources/web-ui/index.html"); const window = createWindow(); const webView = createWebView(pageURL); window.contentView = webView; _window = window; showWindow(_window); }; function cleanup(){ if(_window){ _window.orderOut(nil); _window = null; } }; // Export module.exports = { loadAndShow, cleanup };

ここで行った重要な変更点がいくつかありますが、注意が必要です。 ウィンドウとそのWebビューの作成、非表示、表示のための特定の関数を作成したという事実に加えて、ユーザーインターフェイスコードもモジュール化しました。

下部にあるmodule.exports = { loadAndShow, cleanup }行に注意してください。 これは、このUIコードをインポートするオブジェクトと関数スクリプトが使用できるオブジェクトと関数を正確に指定する方法です(そして、心配したくないものを非表示にします)。つまり、対話するためのより組織化されたAPIがあります。 UIの表示と破棄。

推奨読書スケッチのシンボルの可能性を最大限に引き出す

これが実際にどのように見えるか見てみましょう。 index.jsに戻り、古いコードを削除して、以下を追加します。

 const UI = require("./ui"); function onRun(context){ UI.loadAndShow(context.scriptURL); };

requireコードをインポートし、 ui.jsれたモジュールをUI変数に割り当てるために、Sketchが自動的に使用可能にする特別な関数を使用しています。 これにより、ユーザーインターフェイスをトリガーするための簡略化されたAPIにアクセスできます。 物事は今でははるかに整頓されており、簡単に見つけることができます!

結論

よくやった-あなたは遠くに来ました! In the next part of this tutorial, we'll give our web UI the ability to send us a message when the “Apply” button is clicked, and we'll focus on the main plugin functionality: actually generating layer mosaics!