Help us understand the problem. What is going on with this article?

Sketch Plugin についての要約とメモ。あるいは Sketch Plugin の始め方。

More than 5 years have passed since last update.

これは、 Sketch 3 のプラグインに未来を見た男の物語である。つまり Sketch Developer の要約とメモ。

プラグインで何ができるのか

  • 複雑なルールに基づいて、ドキュメント内のものを選択する
  • レイヤーのプロパティを操作する
  • 新しいレイヤーを作成する
  • サポートされている全てのフォーマットでアセットを出力する
  • ユーザからの入力を受け付けたり、ユーザへ示すことができる
  • 外部ファイルやウェブサービスからデータを取得することができる
  • クリップボードを使うことができる
  • Sketch の環境を操作することができる (ガイド、ズームなど)
  • プラグインからメニューを呼び出すことにより、既存の機能を自動化する

ちなみに例えば、こんなプラグインがある

イントロダクション

プラグインの動かしかた

インストールする方法で変わるので、 Sketch > Plugins > Reveal Plugins Folder からパスを確認する。基本的にここに置いておけば自動認識して Plugins の中に表示される

JSTalk

SketchPlguin を記述する言語は JSTalk です。 JavaScript と Obj-C を混ぜて2で割って全部捨てた感じがする。

拡張子は、プラグイン本体は .sketchplugin。外部ファイルとして .jstalk, .js が使える。

注意
  • 3.0.2 で YES, NO が消えた

    何か元々 true, false の alias だったらしいですがそれが消えました。なので、サンプルコードとかで YES, NO が使われてても使えません。もしくは自分で alias 貼ってください。

標準変数

Sketch Plugin からアクセスできるグローバルな標準変数

  • doc : MSDocument のインスタンス。現在のドキュメントへの参照を持つ。
  • selection : NSArray のインスタンス。現在選択しているレイヤーたち
  • scriptPath : NSString のインスタンス。現在のプラグインへのパス。

Cocoa へのアクセス

JSTalk スクリプトから Cocoa API へアクセスできる。以下は、 File Picker panel を開く例である。

// NSOpenPanel クラスを使う
var openPanel = [NSOpenPanel openPanel]

[openPanel setCanChooseDirectories:false]
[openPanel setCanChooseFiles:true]
[openPanel setCanCreateDirectories:false]
[openPanel setDirectoryURL:[NSURL fileURLWithPath:"~/Documents/"]]

[openPanel setTitle:@"Choose a file"]
[openPanel setPrompt:@"Choose"]
[openPanel runModal]

デバッグ

基本的に以下のようなコードを埋め込むと、 system.log へ出力してくれる。らしい。

log(SOME_VALUE);
  • Console.app で拾う ← まちがい
  • tail で拾う ← せいかい

    $ tail -f /var/log/system.log|grep Sketch
    
おまけ

何か適当に alert 出したりしたかったら

  • alert, [doc showMessage], Cocoa dialogs 何かが使える
  • もしくは Sam Deane’s log panel こういう感じのテクを使う

基本情報

Plugin をまたいだ共通のコードの作り方

#import 'path/to/file'

のように、 #import 文が使えるので、それで共通のファイルを読み込む。

  • 読み込むファイルは jstalk, js のどちらでも読める
  • #import 文は必ずシングルクォートで囲む
  • インポートされたファイル内の検索パスは、現在のフォルダ, プラグインのルートフォルダ の順になる

選択対象に対して Plugin を動作させる

上にかいた selection を使います。現在選択されてるオブジェクトたちが入った NSArray

[selection count] で現在の選択数が取れる

// count を使ってみる
if ([selection count] == 0) {
    // nothing is selected 
}

// 回してみる
for (var i = 0; i < [selection count]; i++) {
    // do something with item
    var item = selection[i] 
}

// Obj-C みたいに回すこともできる
var loop = [selection objectEnumerator]

while (item [loop nextObject]) {
    // dosomething with item 
}

選択解除

[page deselectAllLayers] をつかう

// 現在のページで選択しているアイテムを解除する
[[doc currentPage] deselectAllLayers]

アイテムを選択する

コードから指定したアイテムを洗濯する場合は、 MSLayer がもつ select:byExpandingSelection を使う

// 全選択解除
[[doc currentPage] deselectAllLayers]

var allLayers = [[doc currentPage] layers]

for (var i = 0; i < [allLayers length]; i++) {
    var layer = allLayers[i]

    if ([layer name] == "Rectangle") {
        [layer select:false byExpandingSelection:true]
    }
}

ユーザ入力を取得する

[doc askForUserInput] を使って、ユーザからの値を得ることができる。また、 initialValue でデフォルトの値を入れておくこともできる。

var name = [doc askForUserInput:"What is your name?" initialValue:""]

Note initialValue は必須の引数。"" (空文字) を指定すれば空にできる。

より複雑なユーザ入力を行う場合は NSAlert クラスを用いる。

function createSelect(msg, items, selectedItemIndex) {
    selectedItemIndex = selectedItemIndex || 0

    var accessory = [[NSComboBox alloc] initWithFrame:NSMakeRect(0, 0, 200, 25)

    [accessory addItemsWithObjectValues:items]
    [accessory selectItemAtIndex:selectedItemIndex]

    var alert = [[NSAlert alloc] init]

    [alert setMessageText:msg]
    [alert addButtonWithTitle:'OK']
    [alert addButtonWithTitle:'CANCEL']
    [alert setAccessoryView:accessory]

    var responseCode = [alert runModel]
    var sel = [accessory indexOfSelectedItem]

    return [responseCode, sel]
}

var options = ['None', 'One', 'Two', 'Three']
var choice = createSelect('Choose an option', options, 1)

log(choice)

フィードバック

ユーザに対して何らかのフィードバックを返す場合、 [doc showMessage] もしくは [NSApplication displayDialog] を使う。前者は一行のメッセージが表示でき、後者はタイトルと内容付きのアラートダイアログが表示できる

// [doc showMessage]
[doc showMessage:"The operation is complete"]

// NSApplication
var app = [NSApplication sharedApplication]

[app displayDialog:"The operation is complete" withTitle:"We're done"]
damele0n
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした