JavaScript、HTML、CSSを使用してSketchプラグインを作成する方法(パート2)
公開: 2022-03-10パート1で説明したように、このチュートリアルは、Sketchアプリを知っていて使用していて、コードに手を出すことを恐れない人を対象としています。 それを最大限に活用するには、JavaScript(および、オプションでHTML / CSS)を作成するための基本的な経験が少なくともある程度必要です。
このチュートリアルの前の部分では、プラグインを構成する基本的なファイルと、プラグインのユーザーインターフェイスを作成する方法について学習しました。 この2番目の最後の部分では、ユーザーインターフェイスをコアプラグインコードに接続する方法と、プラグインの主な機能を実装する方法を学習します。 最後になりましたが、コードを最適化する方法とプラグインの動作方法についても学びます。
プラグインのユーザーインターフェイスの構築:WebインターフェイスとSketchプラグインコードを相互に「対話」させる
次に行う必要があるのは、WebインターフェイスとSketchプラグインの間の通信を設定することです。
Webインターフェイスの[適用]ボタンがクリックされたときに、WebインターフェイスからSketchプラグインにメッセージを送信できる必要があります。 このメッセージは、ステップ数、回転量、作成する複製の数など、ユーザーが入力した設定について通知する必要があります。
WKWebView
を使用すると、このタスクが少し簡単になりますwindow.webkit.messageHandlers
を使用して、WebインターフェイスのJavaScriptコードからSketchプラグインにメッセージを送信できます。
Sketchコード側では、別のメソッドaddScriptMessageHandler:name:
またはaddScriptMessageHandler_name
)を使用して、プラグインWebインターフェイスから送信されたメッセージを受信するたびに呼び出されるメッセージハンドラーを登録できます。
WebUIからメッセージを受信できることを確認することから始めましょう。 ui.js
ファイルのcreateWebView
関数に移動し、以下を追加します。
function createWebView(pageURL){ const webView = WKWebView.alloc().init(); // Set handler for messages from script const userContentController = webView.configuration().userContentController(); const ourMessageHandler = ... userContentController.addScriptMessageHandler_name( ourMessageHandler, "sketchPlugin" ); // Load page into web view webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent()); return webView; };
ここでは、WebビューのuserContentController
プロパティを使用して、「sketchPlugin」という名前のメッセージハンドラーを追加します。 この「ユーザーコンテンツコントローラー」は、メッセージがWebビューから確実に伝わるようにするためのブリッジです。
上記のコードについて奇妙なことに気付いたかもしれません。メッセージハンドラーとして追加しているオブジェクトourMessageHandler
はまだ存在していません。 残念ながら、このメソッドは特定の種類のネイティブオブジェクトを想定しているため、通常のJavaScriptオブジェクトまたは関数をハンドラーとして使用することはできません。
幸いなことに、私が書いたミニライブラリであるMochaJSDelegate
を使用することで、この制限を回避できます。これにより、通常の古いJavaScriptを使用して必要な種類のネイティブオブジェクトを作成できます。 手動でダウンロードして、 Sketch/MochaJSDelegate.js
の下のプラグインバンドルに保存する必要があります。
これを使用するには、最初にui.js
にインポートする必要があります。 ファイルの先頭に以下を追加します。
const MochaJSDelegate = require("./MochaJSDelegate");
これで、MochaJSDelegateを使用して、次のタイプのメッセージハンドラーを作成できますMochaJSDelegate
addScriptMessageHandler:name:
is expected:
function createWebView(pageURL){ const webView = WKWebView.alloc().init(); // Set handler for messages from script const userContentController = webView.configuration().userContentController(); const scriptMessageHandler = new MochaJSDelegate({ "userContentController:didReceiveScriptMessage:": (_, wkMessage) => { /* handle message here */ } }).getClassInstance(); userContentController.addScriptMessageHandler_name( scriptMessageHandler, "sketchPlugin" ); // Load page into web view webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent()); return webView; };
追加したコードは、必要なネイティブオブジェクトを作成します。 また、 userContentController:didReceiveScriptMessage:
という名前のオブジェクトのメソッドも定義します。—このメソッドは、2番目の引数として必要なメッセージを使用して呼び出されます。 実際にはまだメッセージを送信していないため、後でここに戻って、受信したメッセージを実際に解析して処理するためのコードを追加する必要があります。
次に、これらのメッセージを送信するために、Webインターフェイスにコードを追加する必要があります。 /Resources/web-ui/script.js
にアクセスします。 ユーザーがオプションを入力するHTML <inputs />
の値の取得を処理するコードのほとんどをすでに記述していることがわかります。
まだやらなければならないことは、実際に値をSketchコードに送信するコードを追加することです。
apply
関数を見つけて、その最後に以下を追加します。
// Send user inputs to sketch plugin window.webkit.messageHandlers.sketchPlugin.postMessage(JSON.stringify({ stepCount, startingOptions, stepOptions }));
ここでは、前述のwindow.webkit.messageHandlers
APIを使用して、 sketchPlugin
として上記で登録したメッセージハンドラーにアクセスします。 次に、ユーザーの入力を含むJSON文字列を含むメッセージを送信します。
すべてが正しく設定されていることを確認しましょう。 /Sketch/ui.js
に戻ります。 期待どおりにメッセージを受信できるようにするために、メッセージを受信したときにダイアログが表示されるように、前に定義したメソッドを変更します。
function createWebView(pageURL){ // ... const scriptMessageHandler = new MochaJSDelegate({ "userContentController:didReceiveScriptMessage:": (_, wkMessage) => { const UI = require("sketch/ui"); UI.alert("Hey, a message!", wkMessage.body()); } }).getClassInstance(); userContentController.addScriptMessageHandler_name( scriptMessageHandler, "sketchPlugin" ); // ... };
次に、プラグインを実行し(最初に開いた既存のモザイクウィンドウを閉じる必要がある場合があります)、いくつかの値を入力して、[適用]をクリックします。 以下のようなアラートが表示されます。これは、すべてが正しく接続され、メッセージが正常に送信されたことを意味します。 そうでない場合は、前の手順に戻り、すべてが説明どおりに行われたことを確認します。
インターフェイスからプラグインにメッセージを送信できるようになったので、その情報を実際に使用してレイヤーモザイクを生成するコードの記述に進むことができます。
レイヤーモザイクの生成
これを実現するために必要なものを検討しましょう。 少し単純化すると、コードで行う必要があるのは次のとおりです。
- 現在のドキュメントを検索します。
- 現在のドキュメントで選択されているレイヤーを検索します。
- 選択したレイヤー(これをテンプレートレイヤーと呼びます)をx回複製します。
- 複製ごとに、ユーザーが設定した特定の値(量)によって、その位置、回転、不透明度などを微調整します。
合理的な計画ができたので、書き続けましょう。 コードをモジュール化するパターンに固執して、 Sketch/
フォルダーに新しいファイルmosaic.js
を作成し、それに次のコードを追加しましょう。
function mosaic(options){ }; module.export = mosaic;
この関数は、インポート後に使用するAPIが簡単になるため、このモジュールの唯一のエクスポートとして使用します。Webインターフェイスから取得したオプションを使用してmosaic()
を呼び出すことができます。
最初の2つの手順は、現在のドキュメントを取得してから、選択したレイヤーを取得することです。 Sketch APIには、 sketch/dom
モジュールをインポートすることでアクセスできるドキュメント操作用の組み込みライブラリがあります。 現在必要なのはDocument
オブジェクトだけなので、明示的に引き出します。 ファイルの先頭に、次を追加します。
const { Document } = require("sketch/dom");
Document
オブジェクトには、 getSelectedDocument()
と呼ばれる、使用可能な現在のドキュメントにアクセスするための特別なメソッドがあります。 現在のドキュメントインスタンスを取得すると、ユーザーがドキュメントのselectedLayers
プロパティを介して選択したすべてのレイヤーにアクセスできます。 ただし、この場合は単一レイヤーの選択のみを考慮しているため、ユーザーが選択した最初のレイヤーのみを取得します。
function mosaic(options){ const document = Document.getSelectedDocument(); const selectedLayer = document.selectedLayers.layers[0]; }; module.export = mosaic;
注: selectedLayers
自体が配列であると期待していたかもしれませんが、そうではありません。 代わりに、これはSelection
クラスのインスタンスです。 これには理由がありますSelection
クラスには、clear、map、reduce、forEachなどの選択を操作するための便利なヘルパーメソッドが多数含まれています。 layer
プロパティを介して実際のレイヤー配列を公開します。
また、ユーザーがドキュメントを開くのを忘れたり、何かを選択したりするのを忘れた場合に備えて、警告フィードバックを追加しましょう。
const UI = require("sketch/ui"); function mosaic(options){ const document = Document.getSelectedDocument(); // Safety check: if(!document){ UI.alert("Mosaic", "️ Please select/focus a document."); return; } // Safety check: const selectedLayer = document.selectedLayers.layers[0]; if(!selectedLayer){ UI.alert("Mosaic", "️ Please select a layer to duplicate."); return; } }; module.export = mosaic;
手順1と2(現在のドキュメントと選択したレイヤーを見つける)のコードを記述したので、手順3と4に対処する必要があります。
- テンプレートレイヤーをx回複製します。
- 複製ごとに、ユーザーが設定した特定の値によって、その位置、回転、不透明度などを微調整します。
options
から必要なすべての関連情報を引き出すことから始めましょう:複製する回数、開始オプション、およびステップオプション。 もう一度、デストラクチャリングを使用して(以前にDocument
で行ったように)、これらのプロパティをoptions
から引き出すことができます。
function mosaic(options) { // ... // Destructure options: var { stepCount, startingOptions, stepOptions } = options; }
次に、入力をサニタイズし、ステップ数が常に少なくとも1になるようにします。
function mosaic(options) { // ... // Destructure options: var { stepCount, startingOptions, stepOptions } = options; stepCount = Math.max(1, stepCount); }
次に、テンプレートレイヤーの不透明度、回転などがすべて、ユーザーの希望する開始値と一致していることを確認する必要があります。 ユーザーのオプションをレイヤーに適用することは、私たちが多く行うことになるので、この作業を独自のメソッドに移動します。
function configureLayer(layer, options, shouldAdjustSpacing){ const { opacity, rotation, direction, spacing } = options; layer.style.opacity = opacity / 100; layer.transform.rotation = rotation; if(shouldAdjustSpacing){ const directionAsRadians = direction * (Math.PI / 180); const vector = { x: Math.cos(directionAsRadians), y: Math.sin(directionAsRadians) }; layer.frame.x += vector.x * spacing; layer.frame.y += vector.y * spacing; } };
また、間隔は複製の間にのみ適用する必要があり、テンプレートレイヤーには適用する必要がないため、特定のフラグshouldAdjustSpacing
を追加しました。これは、テンプレートレイヤーにオプションを適用するか、テンプレートレイヤーにオプションを適用するかに応じてtrue
またはfalse
に設定できます。いいえ。 そうすれば、回転と不透明度がテンプレートに適用されるが、間隔は適用されないようにすることができます。
mosaic
メソッドに戻って、開始オプションがテンプレートレイヤーに適用されていることを確認しましょう。
function mosaic(options){ // ... // Configure template layer var layer = group.layers[0]; configureLayer(layer, startingOptions, false); }
次に、複製を作成する必要があります。 まず、現在の複製のオプションを追跡するために使用できる変数を作成しましょう。
function mosaic(options){ // ... var currentOptions; // ... }
すでに開始オプションをテンプレートレイヤーに適用しているので、次のレイヤーに適用するオプションを取得するには、適用したオプションを取得し、 stepOptions
の相対値を追加する必要があります。 ループ内でこれをさらに数回実行するため、この作業を特定のメソッドstepOptionsBy
に移動します。
function stepOptionsBy(start, step){ const newOptions = {}; for(let key in start){ newOptions[key] = start[key] + step[key]; } return newOptions; };
その後、前のレイヤーを複製するループを作成し、現在のオプションをそのレイヤーに適用してから、次の複製のオプションを取得するために現在のオプションをオフセット(または「ステップ」)する必要があります。
function mosaic(options) { // ... var currentOptions = stepOptionsBy(startingOptions, stepOptions); for(let i = 0; i < (stepCount - 1); i++){ let duplicateLayer = layer.duplicate(); configureLayer(duplicateLayer, currentOptions, true); currentOptions = stepOptionsBy(currentOptions, stepOptions); layer = duplicateLayer; } }
すべて完了しました—プラグインが行うことになっていることのコアを正常に記述しました! 次に、ユーザーが実際に[適用]ボタンをクリックしたときにモザイクコードが呼び出されるように、接続する必要があります。
ui.js
に戻って、メッセージ処理コードを調整しましょう。 実行する必要があるのは、取得したオプションのJSON文字列を解析して、実際に使用できるオブジェクトに変換することです。 これらのオプションを取得したら、それらを使用してmosaic
関数を呼び出すことができます。
まず、構文解析。 取得したJSONメッセージを解析するには、メッセージ処理関数を更新する必要があります。
function createWebView(pageURL){ // ... const scriptMessageHandler = new MochaJSDelegate({ "userContentController:didReceiveScriptMessage:": (_, wkMessage) => { const message = JSON.parse(wkMessage.body()); } }); }
次に、これをmosaic
関数に渡す必要があります。 ただし、これは実際にはui.js
のコードが実行する必要のあることではありません。モザイク自体を作成するのではなく、主にインターフェイス関連のものを画面に表示するために必要なものに関係しているはずです。 これらの責任を分離するために、関数をcreateWebView
に2番目の引数を追加し、Webインターフェイスからオプションを受け取るたびにその関数を呼び出します。
この引数onApplyMessage
という名前を付けましょう:
function createWebView(pageURL, onApplyMessage){ // ... const scriptMessageHandler = new MochaJSDelegate({ "userContentController:didReceiveScriptMessage:": (_, wkMessage) => { const message = JSON.parse(wkMessage.body()); onApplyMessage(message); } }); }
また、エクスポートされたメソッドloadAndShow
を変更して、このonApplyMessage
引数も取得し、 createWebView
に渡す必要があります。
function loadAndShow(baseURL, onApplyMessage){ // ... const webView = createWebView(pageURL, onApplyMessage); }
最後に、 main.js
に移動します。 次に、 mosaic
関数をインポートし、プラグインのユーザーインターフェイスから受け取ったオプションを使用して呼び出す必要があります。
const mosaic = require("./mosaic"); function onRun(context){ UI.loadAndShow(context.scriptURL, options => { mosaic(options); }); };
ほぼ完了です。
ただし、ここでコードを実行し、プラグインインターフェイスの[適用]ボタンをクリックしても、何も起こりません。 なんで? その理由は、Sketchスクリプトの実行方法によるものです。デフォルトでは、スクリプトはスクリプトの最後に到達するまで「存続」し、その後、Sketchはスクリプトを破棄し、使用していたリソースを解放します。
これは、スクリプトが破棄されているため、メッセージの受信など、非同期で発生する必要があるすべてのこと(この場合、コードの最後に到達した後)では発生しないことを意味するため、私たちにとって問題です。 これは、メッセージを受信して応答するために周りにいないため、Webインターフェイスからメッセージを取得しないことを意味します。
Fibers
を使用して、このポイントを超えてスクリプトを存続させる必要があることをSketchに通知する方法があります。 ファイバーを作成することで、非同期の何かが起こっていることと、スクリプトを維持する必要があることをSketchに伝えます。 その後、Sketchは、絶対に必要な場合(ユーザーがSketchを閉じるとき、またはMosaicプラグインを更新する必要があるときなど)にのみスクリプトを破棄します。
// ... const Async = require("sketch/async"); var fiber; function onRun(context){ if(!fiber){ fiber = Async.createFiber(); fiber.onCleanup(() => { UI.cleanup(); }); } UI.loadAndShow(context.scriptURL, options => { mosaic(options); }); };
出来上がり! プラグインを試してみましょう。 Sketchでレイヤーを選択した状態で、いくつかの設定を入力し、[適用]をクリックします。
最終的な改善
プラグインの機能の大部分が実装されたので、少し「ズームアウト」して全体像を見てみましょう。
ユーザーエクスペリエンスの向上
プラグインを現在の状態で試してみた場合、モザイクを編集しようとすると、最大の摩擦点の1つが現れることに気付いたかもしれません。 作成したら、元に戻すを押してオプションを調整し、[適用]をクリックする(またはEnterキーを押す)必要があります。 また、元にした/やり直しの履歴が消去され、重複したレイヤーを手動で削除する必要があるため、ドキュメントを残して後で戻った後のモザイクの編集が難しくなります。
より理想的なフローでは、ユーザーはMosaicグループを選択し、オプションを調整して、探している正確な配置が得られるまでMosaicの更新を見ることができます。 これを実装するには、解決すべき2つの問題があります。
- まず、モザイクを構成する複製をグループ化する方法が必要です。 Sketchは、この問題を解決するために使用できるグループの概念を提供します。
- 次に、通常のユーザー作成グループとMosaicグループの違いを区別する方法が必要になります。 SketchのAPIは、特定のレイヤーに情報を保存する方法も提供します。これをウェイタグとして使用し、後でグループを「特別な」モザイクグループの1つとして識別できます。
これに対処するために、前のセクションで作成したロジックを再検討してみましょう。 元のコードは次の手順に従います。
- 現在のドキュメントを検索します。
- 現在のドキュメントで選択されているレイヤーを検索します。
- 選択したレイヤー(これをテンプレートレイヤーと呼びます)をx回複製します。
- 複製ごとに、ユーザーが設定した特定の値(量)によって、その位置、回転、不透明度などを微調整します。
新しいユーザーフローを可能にするには、次の手順を変更する必要があります。
- 現在のドキュメントを取得します。
- 現在のドキュメントで選択したレイヤーを取得します。
- 選択したレイヤーがモザイクグループであるかどうかを確認します。
- 他のレイヤーの場合は、テンプレートレイヤーとして使用し、手順4に進みます。
- モザイクグループの場合は、その最初のレイヤーをテンプレートレイヤーと見なし、手順5に進みます。
- テンプレートレイヤーをグループ内にラップし、そのグループをモザイクグループとしてマークします。
- テンプレートレイヤーを除く、グループ内のすべてのレイヤーを削除します。
- テンプレートレイヤーをx回複製します。
- 複製ごとに、ユーザーが設定した特定の値によって、その位置、回転、不透明度などを微調整します。
3つの新しいステップがあります。 最初の新しいステップであるステップ3では、 findOrMakeSpecialGroupIfNeeded
という名前の関数を作成します。この関数は、渡されたレイヤーを調べて、それがMosaicグループであるかどうかを判断します。 もしそうなら、私たちはそれを返すだけです。 ユーザーはMosaicグループの奥深くにネストされたサブレイヤーを選択できる可能性があるため、選択したレイヤーの親もチェックして、それらがMosaicグループの1つであるかどうかを確認する必要があります。
function findOrMakeSpecialGroupIfNeeded(layer){ // Loop up through the parent hierarchy, looking for a special group var layerToCheck = layer; while(layerToCheck){ if(/* TODO: is mosaic layer? */){ return layerToCheck; } layerToCheck = layerToCheck.parent; } };
モザイクグループが見つからなかった場合は、渡されたレイヤーをGroup
内にラップし、モザイクグループとしてタグ付けします。
ファイルの先頭に戻って、Groupクラスも引き出す必要があります。
const { Document, Group } = require("sketch/dom");
function findOrMakeSpecialGroupIfNeeded(layer){ // Loop up through the parent hierarchy, looking for a special group var layerToCheck = layer; while(layerToCheck){ if(/* TODO: is mosaic layer? */){ return layerToCheck; } layerToCheck = layerToCheck.parent; } // Group const destinationParent = layer.parent; const group = new Group({ name: "Mosaic Group", layers: [ layer ], parent: destinationParent }); /* TODO: mark group as mosaic layer */ return group; };
次に、ギャップ(todo)を埋める必要があります。 まず、グループが私たちに属する特別なグループの1つであるかどうかを識別する手段が必要です。 ここで、SketchライブラリのSettings
モジュールが役に立ちます。 これを使用して、特定のレイヤーにカスタム情報を保存したり、読み戻したりすることができます。
ファイルの先頭にあるモジュールをインポートしたら、次のようにします。
const Settings = require("sketch/settings");
次に、それが提供する2つの主要なメソッドsetLayerSettingForKey
とlayerSettingForKey
を使用して、レイヤーからデータを設定および読み取ることができます。
function findOrMakeSpecialGroupIfNeeded(layer){ const isSpecialGroupKey = "is-mosaic-group"; // Loop up through the parent hierarchy, looking for a special group var layerToCheck = layer; while(layerToCheck){ let isSpecialGroup = Settings.layerSettingForKey(layerToCheck, isSpecialGroupKey); if(isSpecialGroup) return layerToCheck; layerToCheck = layerToCheck.parent; } // Group const destinationParent = layer.parent; layer.remove(); // explicitly remove layer from it's existing parent before adding it to group const group = new Group({ name: "Mosaic Group", layers: [ layer ], parent: destinationParent }); Settings.setLayerSettingForKey(group, isSpecialGroupKey, true); return group; };
モザイクグループ内のレイヤーのラップを処理するメソッドができたので(または、既にモザイクグループの場合は、それを返すだけです)、安全性チェックの直後にメインのmosaic
メソッドにプラグインできます。
function mosaic(options){ // ... safety checks ... // Group selection if needed: const group = findOrMakeSpecialGroupIfNeeded(selectedLayer); }
次に、ループを追加して、テンプレートレイヤー(最初のレイヤー)を除くすべてのレイヤーをグループから削除します。
function mosaic(options) { // ... // Remove all layers except the first: while(group.layers.length > 1){ group.layers[group.layers.length - 1].remove(); } }
最後に、ユーザーが古いグループ内にネストされたレイヤー(削除した可能性のあるレイヤー)を最初に選択した可能性があるため、グループのサイズが新しいコンテンツに適合していることを確認します。
また、現在の選択をモザイクグループ自体に設定する必要があります。 これにより、ユーザーが同じモザイクグループに大量の変更を加えている場合でも、選択が解除されないようになります。 レイヤーを複製するためにすでに作成したコードの後に、次を追加します。
function mosaic(options) { // ... // Fit group to duplicates group.adjustToFit(); // Set selection to the group document.selectedLayers.clear(); group.selected = true; }
プラグインをもう一度試してください。 モザイクの編集がはるかにスムーズになったことに気付くはずです。
インターフェースの改善
もう1つ気付くかもしれないのは、表示ウィンドウとその中のインターフェイスが同期していないことです。両方が同時に表示されるようになります。 これは、ウィンドウを表示するときにWebインターフェイスの読み込みが完了するとは限らないため、後で「ポップ」または「フラッシュイン」することがあるためです。
これを修正する1つの方法は、Webインターフェイスの読み込みが完了したことをリッスンしてから、ウィンドウを表示することです。 現在のページの読み込みが完了したときにWKWebViewが呼び出すメソッドwebView:didFinishNavigation:
があります。 これを使用して、探している通知を正確に取得できます。
ui.js
に戻って、このメソッドを実装するために作成したMochaJSDelegate
インスタンスを拡張します。これにより、createWebViewに渡すonLoadFinish
引数がcreateWebView
れます。
function createWebView(pageURL, onApplyMessage, onLoadFinish){ const webView = WKWebView.alloc().init(); // Create delegate const delegate = new MochaJSDelegate({ "webView:didFinishNavigation:": (webView, navigation) => { onLoadFinish(); }, "userContentController:didReceiveScriptMessage:": (_, wkMessage) => { const message = JSON.parse(wkMessage.body()); onApplyMessage(message); } }).getClassInstance(); // Set load complete handler webView.navigationDelegate = delegate; // Set handler for messages from script const userContentController = webView.configuration().userContentController(); userContentController.addScriptMessageHandler_name(delegate, "sketchPlugin"); // Load page into web view webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent()); return webView; };
そして、 loadAndShow
メソッドに戻って、Webビューがロードされた後にのみウィンドウが表示されるように調整します。
function loadAndShow(baseURL, onApplyMessage){ // ... const window = createWindow(); const webView = createWebView(pageURL, onApplyMessage, () => { showWindow(window); }); window.contentView = webView; _window = window; };
ビンゴ! これで、ウィンドウはWebビューの読み込みが完了したときにのみ表示され、煩わしい視覚的なちらつきを回避できます。
結論
おめでとうございます。最初のSketchプラグインを作成しました。
Mosaicをインストールして試してみたい場合は、GitHubから完全なプラグインをダウンロードできます。 そして、行く前に、残りの旅の間に役立つかもしれないいくつかのリソースがあります:
- developer.sketchapp.comSketchプラグイン開発に関する公式リソース。 いくつかの便利なガイドと、SketchJavaScriptライブラリのAPIリファレンスが含まれています。
- Sketchplugins.comSketchプラグイン開発者の素晴らしくて役立つコミュニティ。 燃えている質問すべてに答えてもらうのに最適です。
- github.com/sketchplugins/plugin-directorySketchプラグインの公式の中央GitHubリポジトリ。 ここでプラグインを送信して、Sketchコミュニティの他のメンバーと共有できます。