Cara Membuat Plugin Sketch Dengan JavaScript, HTML, dan CSS (Bagian 1)
Diterbitkan: 2022-03-10Tutorial ini ditujukan untuk orang yang mengetahui dan menggunakan aplikasi Sketch dan tidak takut mencoba-coba kode. Untuk mendapatkan keuntungan maksimal, Anda harus memiliki setidaknya beberapa pengalaman dasar menulis JavaScript (dan, opsional, HTML/CSS).
Plugin yang akan kita buat disebut "Mosaic". Di bagian pertama, kita akan mempelajari tentang file dasar yang membentuk plugin Sketch; kami akan menulis beberapa JavaScript dan membuat antarmuka pengguna untuk plugin kami dengan bantuan beberapa HTML dan CSS. Artikel selanjutnya adalah tentang cara menghubungkan antarmuka pengguna ke kode plugin inti, cara menerapkan fitur utama plugin, dan di bagian akhir, Anda juga akan belajar cara mengoptimalkan kode dan cara kerja plugin.
Saya juga akan membagikan kode plugin (JS, HTML, CSS) dan file yang dapat Anda periksa dan gunakan untuk tujuan pembelajaran.
Apa Itu Plugin Sketch, Dan Bagaimana Cara Kerjanya?
Di Sketch, plugin adalah cara untuk menambahkan fitur dan fungsionalitas yang tidak ada di Sketch "di luar kotak". Mempertimbangkan bahwa hampir selalu akan ada beberapa fitur atau integrasi yang hilang dalam program apa pun (terutama mengingat banyaknya kebutuhan yang mungkin dimiliki oleh setiap desainer!), orang dapat mulai membayangkan bagaimana plugin mungkin sangat berguna dan kuat. Plugin Sketch dapat melakukan hampir semua yang Anda harapkan, seperti memanipulasi warna, bentuk, ukuran, urutan, gaya, pengelompokan, dan efek lapisan, tetapi juga dapat melakukan hal-hal seperti membuat permintaan ke sumber daya internet, menghadirkan pengguna antarmuka, dan banyak lagi!
Di sisi pemrograman, semua plugin Sketch ditulis dalam kode JavaScript. Sebenarnya, itu tidak sepenuhnya benar. Lebih akurat untuk mengatakan bahwa sebagian besar plugin Sketch ditulis dalam JavaScript, karena juga memungkinkan untuk menulis plugin Sketch di salah satu bahasa pemrograman Apple, Objective-C dan Swift, meskipun mereka memerlukan sedikit pengetahuan JavaScript.
Jangan khawatir. Pada artikel ini, kami akan fokus pada cara membuat plugin Sketch menggunakan JavaScript, HTML, dan CSS saja . Kami tidak akan membahas dasar-dasar HTML, CSS, atau JavaScript — artikel ini mengasumsikan setidaknya beberapa pengetahuan dan pengalaman dengan ketiganya. Situs web pengembang MDN menyediakan tempat yang tepat untuk mempelajari lebih lanjut tentang pengembangan web.
Ayo Mulai!
Pertama, Apa Yang Kami Buat?
Dalam tutorial ini, saya akan mengajari Anda cara membuat plugin dasar yang ramah bagi pemula yang dapat membuat, menggandakan, dan memodifikasi lapisan, serta menghadirkan antarmuka pengguna yang bagus kepada pengguna. Dengan melakukan itu, tujuan saya adalah membangun pengetahuan dasar yang dapat Anda gunakan untuk membangun dan menggunakannya untuk membuat plugin Anda sendiri.
Plugin yang akan kita bangun disebut Mosaic, dan secara efektif merupakan "generator pola". Beri makan layer Anda, atur beberapa pengaturan, dan itu akan membuat pola:

Jika Anda ingin menginstal dan bermain-main dengan Mosaic, Anda dapat mengunduh plugin yang sudah selesai dari GitHub.
Sedikit sejarah: Mosaic sebagian besar terinspirasi oleh plugin Adobe Fireworks jadul yang disebut Twist-and-Fade . Twist-and-Fade cukup kuat, mampu menduplikasi layer beberapa kali sambil menyesuaikan rona, posisi, rotasi, ukuran, dan opacity. Plugin ini bahkan mampu menghasilkan GIF animasi, seperti ini, di mana ia membuat bingkai untuk dua elemen berputar dalam kaset:

(Ini adalah video demo Twist and Fade jika Anda tertarik untuk melihat cara kerjanya.)
Untuk keperluan tutorial ini, kami akan membuat plugin yang agak mirip untuk Sketch, meskipun sengaja disederhanakan agar tutorial tetap dapat diakses semaksimal mungkin. Secara khusus, plugin kami akan dapat:
- Gandakan layer Sketch (bitmap atau vektor) dan atur posisi, rotasi, dan opacity layer duplikat. Ini akan memberi kita pengantar untuk memanipulasi lapisan menggunakan API JavaScript Sketch.
- Menampilkan antarmuka pengguna yang dibuat menggunakan HTML, CSS, dan JS, yang akan mengajarkan Anda tentang cara mudah membuat antarmuka untuk plugin, dengan menggunakan teknologi web yang mungkin sudah Anda kenal. Antarmuka plugin cukup penting karena itulah cara kami mengumpulkan masukan pengguna tentang bagaimana pengguna ingin gambar mosaik yang dihasilkan terlihat.
Membuat Plugin Dasar Kami Dalam Sepuluh Detik Tetap
Pertama, kita akan membuat "dasar" (atau template) untuk plugin yang ingin kita buat. Kita dapat membuat semua file dan folder yang diperlukan yang membentuk plugin secara manual, tetapi untungnya kita tidak perlu melakukannya — karena Sketch dapat melakukannya untuk kita. Setelah kami membuat plugin template, kami akan dapat menyesuaikannya sesuai keinginan kami.
Ada teknik yang sangat cepat dan mudah yang dapat kita gunakan untuk membuat plugin template, yang merupakan metode utama saya ketika saya perlu menggabungkan plugin untuk memecahkan masalah apa pun yang saya hadapi pada saat tertentu. Berikut cara kerjanya:
Dengan Sketch terbuka, periksa bilah menu di bagian atas layar dan klik Plugins -> Run Script
. Ini akan membuka kotak dialog yang dapat kita gunakan untuk menguji dan menjalankan kode. Kami juga dapat menyimpan kode apa pun yang kami masukkan ke dalamnya sebagai plugin, yang merupakan bagian yang kami minati saat ini.
Hapus kode apa pun yang sudah ada dalam dialog ini dan ganti dengan kode demo berikut:
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!");
Selanjutnya, tekan Save Script as Plugin
di kiri bawah jendela, masukkan nama apa pun yang Anda inginkan untuk plugin ini (dalam kasus kami, ini adalah "Mosaic"), lalu Save Script as Plugin
sekali lagi.

Percaya atau tidak, kita sudah selesai — yang tersisa hanyalah memakan kue yang baru saja kita panggang. Inilah bagian yang menyenangkan. Membuka menu Plugin sekali lagi, Anda akan melihat sesuatu seperti ini: plugin baru Anda terdaftar sebagai "Mosaik"! Klik di atasnya!

Selamat, Anda baru saja menulis plugin Sketch pertama Anda!
Apa yang akan Anda lihat setelah mengklik "Mosaik" seharusnya seperti video singkat di atas, dengan pesan tooltip yang tidak mencolok muncul di bagian bawah layar yang dimulai dengan kata-kata "Hei di sana ..." — yang persis seperti yang dikatakan oleh kode yang kami tempel. melakukan. Inilah yang membuat teknik ini begitu hebat: membuatnya mudah untuk menempel, memodifikasi, dan menguji kode tanpa harus membuat plugin dari awal. Jika Anda terbiasa atau pernah bermain dengan konsol web browser Anda, ini pada dasarnya. Memiliki alat ini di saku belakang Anda saat Anda membuat dan menguji kode adalah hal yang harus dimiliki.
Mari kita lakukan ikhtisar singkat tentang apa yang dilakukan kode yang Anda tambahkan:
Pertama, itu mengimpor modul sketch/ui
dari perpustakaan JS bawaan Sketch, dan menetapkannya ke variabel UI
. Modul ini berisi beberapa metode terkait antarmuka yang berguna, salah satunya akan kita gunakan:
const UI = require("sketch/ui");
Selanjutnya, ia memanggil metode message
(yang merupakan bagian dari modul sketch/ui
) dengan string teks yang ingin kita tampilkan di tooltip yang kita lihat:
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!");
Metode message()
menyediakan cara yang bagus untuk menyajikan pesan yang tidak mengganggu kepada pengguna; itu bagus untuk kasus di mana Anda tidak perlu mencuri fokus (non-modal) dan tidak memerlukan tombol mewah atau bidang teks. Ada juga cara lain untuk menampilkan elemen UI umum seperti peringatan, perintah, dan semacamnya, beberapa di antaranya akan kita gunakan saat kita membangun Mosaic.
Menyesuaikan Metadata Plugin Kami
Kami sekarang memiliki plugin dasar untuk memulai, tetapi kami masih perlu mengubahnya lebih lanjut dan menjadikannya benar-benar milik kami. Langkah kita selanjutnya adalah mengubah metadata plugin.
Untuk langkah ini, kita perlu mengintip apa yang disebut bundel plugin . Ketika Anda menekan simpan di jendela 'Run Script', Sketch menyimpan plugin Anda sebagai folder bernama Mosaic.sketchplugin
yang dapat Anda temukan di direktori ~/Library/Application Support/com.bohemiancoding.sketch3/Plugins
. Itu agak panjang dan menjengkelkan untuk diingat; sebagai jalan pintas, Anda juga dapat menariknya melalui Plugins -> Manage Plugins -> (right-click your plugin) -> Reveal Plugins Folder
. Meskipun muncul di Finder sebagai satu file, itu sebenarnya folder yang berisi semua yang dibutuhkan plugin kami untuk Sketch untuk menjalankannya. Alasan munculnya sebagai satu file meskipun merupakan folder adalah karena ketika Anda pertama kali menginstal Sketch, Sketch mendaftarkan ekstensi .sketchplugin
sebagai "bundel" (jenis folder khusus yang muncul sebagai file) dan memintanya untuk terbuka secara otomatis di Sketch saat dibuka.
Mari kita intip ke dalam. Klik kanan Mosaic.sketchplugin
, lalu klik “Show Package Contents”. Di dalam, Anda akan melihat struktur direktori berikut:
Contents/ └ Resources/ └ Sketch/ └ manifest.json └ script.cocoascript
Anda mungkin bertanya-tanya mengapa ada file di sana dengan ekstensi .cocoascript
. Jangan khawatir — ini hanya file JavaScript biasa, dan hanya berisi kode yang kita masukkan sebelumnya. Silakan dan ganti nama file ini menjadi index.js
, yang akan mengubah struktur direktori agar terlihat seperti di bawah ini:
Contents/ └ Resources/ └ Sketch/ └ manifest.json └ index.js
Cara paling umum untuk mengatur file di dalam bundel plugin adalah sebagai berikut: kode Anda (JavaScript) dan manifest.json
termasuk dalam Sketch/
, dan sumber daya (pikirkan gambar, file audio, file teks, dll.) milik Resources/
.
Mari kita mulai dengan mengutak-atik file bernama manifest.json
. Buka di dalam editor kode favorit Anda, seperti Visual Studio Code atau Atom.
Anda akan melihat bahwa saat ini hanya ada sedikit di dalam sini, tetapi kami akan segera menambahkan lebih banyak lagi. Manifes plugin melayani dua tujuan utama:
- Pertama, ia menyediakan metadata yang menjelaskan plugin kepada pengguna — hal-hal seperti nama, versi, nama penulis, dan sebagainya. Sketch menggunakan informasi ini dalam dialog
Sketch -> Preferences -> Plugins
untuk membuat daftar dan deskripsi plugin Anda. - Kedua, ini juga memberi tahu Sketch tentang cara memulai bisnis Anda; yaitu, ia memberi tahu Sketch bagaimana Anda ingin menu plugin Anda terlihat, hotkey apa yang akan ditetapkan ke plugin Anda, dan di mana kode plugin Anda berada (sehingga Sketch dapat menjalankannya).
Mengingat tujuan #1, menjelaskan plugin kepada pengguna, Anda mungkin akan melihat bahwa saat ini tidak ada deskripsi atau penulis yang diberikan, yang akan membingungkan pengguna dan membuat plugin sulit untuk diidentifikasi. Mari kita perbaiki dengan menyesuaikan nilai kunci yang relevan ke:
{ "description": "Generate awesome designs and repeating patterns from your layers!", "author": "=> Your name here <=" }
Selanjutnya, mari kita sesuaikan pengenal plugin. Pengidentifikasi ini menggunakan apa yang disebut "notasi domain terbalik" yang merupakan cara yang sangat ringkas (atau membosankan, silakan pilih) untuk mengatakan "ambil domain situs Anda, balikkan urutannya, lalu masukkan nama produk Anda di akhir". Ini akan keluar seperti: com.your-company-or-your-name-its-not-that-big-a-deal.yourproduct
.
Anda tidak harus mengikuti konvensi penamaan ini — Anda dapat meletakkan apa pun yang Anda inginkan di sini, asalkan cukup unik untuk menghindari konflik dengan plugin lain (walaupun mungkin ide yang baik untuk tetap menggunakan format RDN, terutama karena menyediakan sistem sederhana yang dapat digunakan kembali untuk pengidentifikasi plugin Anda).
Untuk itu, ubah pengenal Anda menjadi com.your-name.mosaic
:
{ "identifier": "com.your-name.mosaic" }
Saya pribadi suka mengambil semua kunci terkait metadata (judul, penulis, pengidentifikasi, dll.) dan mengelompokkannya di dekat bagian atas manifes sehingga tidak tersebar di semua tempat dan membantu menjaga kewarasan saya ketika saya perlu menemukannya .
Selanjutnya, mari kita lihat tombol menu
dan commands
. Keduanya bertanggung jawab untuk memberi tahu Sketch kode apa yang harus dipanggil dan sebagai tanggapan atas apa.
Jika Anda melihat tombol menu
, Anda akan melihatnya berisi kunci title
, yang nilainya adalah nama plugin kami yang akan muncul di menu Plugins
. Ini juga memiliki kunci items
, yang merupakan daftar pengidentifikasi perintah :
{ "menu": { "title": "Mosaic", "items": [ "com.bohemiancoding.sketch.runscriptidentifier" ] } }
Saat ini hanya ada satu pengenal perintah dalam daftar ini, "com.bohemiancoding.sketch.runscriptidentifier"
. Pengidentifikasi perintah selalu menunjuk ke perintah dalam daftar commands
. Saat ini plugin kami hanya memiliki satu perintah, yaitu perintah dengan pengenal ini:
{ "commands": [ { "script" : "script.cocoascript", "name" : "Mosaic", "handlers" : { "run" : "onRun" }, "identifier" : "com.bohemiancoding.sketch.runscriptidentifier" } ] }
Setiap kali Anda menambahkan pengenal perintah ke entri menu
, Sketch akan mencari entri perintah yang memiliki pengenal itu dan akan menampilkan nilai kunci name
(yang dalam hal ini adalah "Mosaik") dan akan menampilkannya di menu plugin Anda. dari pengidentifikasi.
Adapun peran perintah bermain, kita dapat memikirkan entri perintah sebagai cara untuk memberi tahu Sketch fungsi apa dalam kode JavaScript plugin kita yang ingin kita jalankan ketika perintah itu dipanggil, "doa" biasanya menjadi klik pengguna pada menu terkait barang. Entri perintah tidak melakukan apa pun sendiri, itu hanya JSON — itu hanya memberikan deskripsi ke Sketch di mana mencari JavaScript yang perlu dijalankan ketika perintah dipanggil.
Sejauh ini, kita telah berbicara tentang apa yang dilakukan oleh name
perintah dan kunci identifier
, tetapi ada dua kunci lain dalam perintah yang perlu ditangani: script
dan handlers
.
Kunci script
memberi tahu Sketch di mana file JavaScript yang harus dijalankan. Perhatikan bagaimana Sketch mengasumsikan bahwa file skrip yang dimaksud ada di folder Sketch/
, itulah sebabnya demi kesederhanaan Anda harus memastikan semua kode JavaScript Anda berada di suatu tempat di bawah folder Sketch/
. Sebelum kita beralih dari kunci ini, penting bagi Anda untuk memastikan bahwa Anda mengubah nilai kunci ini menjadi index.js
, sama seperti kita menamai file sebelumnya. Jika tidak, Sketch tidak akan dapat menemukan dan menjalankan file JavaScript Anda.
Nilai kunci handlers
adalah apa yang dilihat Sketch untuk menentukan fungsi apa dalam JavaScript Anda yang akan dipanggil. Di sini, kami hanya memiliki satu set handler: run
, dengan nilai onRun
. run
adalah nama dari tindakan Sketsa bawaan yang telah ditentukan sebelumnya. Tindakan run
ini akan selalu dipanggil saat pengguna mengklik item menu yang mereferensikan perintah ini. onRun
adalah nama fungsi dalam file script.cocoascript
yang dibuat secara otomatis (yang kami ubah namanya menjadi index.js
), dan fungsi yang ingin kami panggil saat peristiwa run
terjadi, yaitu, saat pengguna mengklik item menu.
Dalam contoh yang kita miliki sejauh ini, proses ini memainkan sesuatu seperti ini:
- Pengguna mengklik item menu kami.
- Sketch menemukan perintah yang terkait dengan item menu tersebut.
- Sketch menemukan file skrip yang dirujuk oleh perintah dan menjalankannya (yang dalam hal ini berarti menjalankan JavaScript di
index.js
). - Karena perintah ini dipanggil oleh klik item menu, itu dianggap sebagai tindakan yang
run
. Itu berarti Sketch akan melihat nilai perintahhandlers.run
untuk fungsi yang akan dipanggil berikutnya, yang dalam hal ini adalahonRun
. - Sketch memanggil fungsi
onRun
.
Perintah paling sering dipanggil sebagai respons terhadap pengguna yang mengklik salah satu item menu Anda, tetapi mereka juga dapat dipanggil sebagai respons terhadap tindakan pengguna lain, seperti pengguna mengubah pilihan atau properti pada lapisan. Namun, untuk plugin ini, kami tidak akan menggunakan tindakan lain ini. (Anda dapat mempelajari lebih lanjut tentang tindakan dan cara kerjanya di halaman bantuan Action API.)
Sebelum kita beralih dari manifes ini, kita ingin membuat dua penyesuaian lainnya. Saat ini, menu kami memiliki struktur:
Mosaic └ Mosaic

…yang agak berlebihan karena plugin kami hanya memiliki satu item menu. Itu juga menambahkan sedikit gesekan yang tidak perlu bagi pengguna kami karena plugin kami sekarang membutuhkan dua klik untuk dipanggil daripada satu. Kami dapat memperbaikinya dengan menambahkan isRoot: true
ke menu
kami :

{ "menu": { "title" : "Mosaic", "items" : [ "com.bohemiancoding.sketch.runscriptidentifier" ], "isRoot": true } }
Ini memberi tahu Sketch untuk menempatkan item menu tingkat pertama langsung di bawah menu Plugins
, daripada menumpuknya di bawah title
menu .
Tekan simpan dan kembali ke Sketch. Anda akan melihat bahwa sekarang Mosaic -> Mosaic
telah digantikan oleh hanya Mosaic
— sempurna!

Adapun tweak kedua kita, mari kita lanjutkan dan ganti nama pengenal perintah ini menjadi sesuatu yang kurang berat. Karena pengenal perintah hanya perlu unik dalam konteks masing-masing plugin, kita dapat dengan aman mengganti namanya menjadi sesuatu yang lebih ringkas dan jelas, seperti "open"
:
{ "commands": [ { ... "identifier" : "open" } ], "menu": { ... "items" : [ "open" ] } }
Sebelum kita melanjutkan, perlu diperhatikan bahwa menu juga dapat berisi menu lain. Anda dapat dengan mudah membuat sub-menu dengan membuat entri { title: ..., items: ... }
lain di dalam daftar items
menu lain:
{ "menu": { "title" : "Mosaic", "items" : [ "open", { "title" : "I'm a sub-menu!", "items" : [ "another-command-identifier" ] } ] } }
Membangun Antarmuka Pengguna Plugin
Sejauh ini, kami telah menulis beberapa kode demo dan menyesuaikan manifes plugin kami. Sekarang kita akan beralih ke pembuatan antarmuka penggunanya, yang pada dasarnya adalah halaman web yang disematkan di jendela (mirip dengan browser yang biasa Anda gunakan):


Jendela
Desain antarmuka pengguna Mosaic memiliki jendelanya sendiri, yang dapat kita anggap sebagai komponen paling dasar; kita akan mulai dengan itu. Untuk membuat dan menampilkan jendela, kita harus menggunakan kelas yang dibangun ke dalam macOS secara default, yang disebut NSWindow
. Selama sisa tutorial ini, kita sebenarnya akan melakukan ini sedikit (menggunakan API bawaan seperti NSWindow
) yang mungkin tampak sedikit menakutkan jika Anda tidak terbiasa dengannya, tetapi jangan khawatir — saya akan menjelaskannya semuanya di sepanjang jalan!
Catatan: Saat kita berbicara tentang API bawaan, alasan kami dapat menggunakan kelas ini sama sekali adalah berkat adanya jembatan di runtime JavaScript yang digunakan oleh plugin Sketch. Bridge ini secara otomatis mengimpor kelas, metode, dan fungsi bawaan yang biasanya hanya tersedia untuk aplikasi asli.
Buka Sketch/index.js
di editor kode Anda, hapus apa yang sudah ada di sana, dan rekatkan berikut ini:
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); };
Mari kita lihat apa yang dilakukan bit pertama kode ini:
function onRun(context){
Ingat sebelumnya ketika kita berbicara tentang perintah dan bagaimana fungsinya, dan kita memberi tahu Sketch untuk memanggil sebagai tanggapan terhadap klik menu disebut onRun
? (Jika Anda membutuhkan penyegaran, kunjungi kembali bagian di atas, lalu kembalilah.) Yang dilakukan bit ini hanyalah membuat fungsi itu. Anda juga akan melihat fungsi onRun
kami mengambil argumen context
. Ini adalah argumen yang akan dipanggil oleh Sketsa perintah penangan Anda yang dapat memberi kami informasi tertentu. Nanti, kami akan menggunakannya untuk mendapatkan URL bundel plugin kami di komputer pengguna.
const window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer( NSMakeRect(0, 0, 145, 500), NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false );
Di sini kita sebenarnya melakukan beberapa hal:
- Pertama, kita panggil
alloc()
diNSWindow
; ini pada dasarnya berarti "menyisihkan beberapa memori untuk instance NSWindow". Cukup mengetahui bahwa Anda harus melakukan ini untuk setiap instance kelas asli yang ingin Anda buat. Metodealloc
tersedia di setiap kelas asli. - Selanjutnya, kita memanggil metode penginisialisasi
NSWindow
(yaitu, metode yang benar-benar membuat turunanNSWindow
), yang diberi namainitWithContentRect:styleMask:backing:defer:
. Anda akan melihat bahwa itu berbeda dari apa yang kami sebut dalam kode kami di atas — ada banyak titik dua (:
) di antara setiap argumen. Karena kita tidak dapat menggunakan sintaks itu dalam JavaScript, Sketch dengan mudah mengganti namanya menjadi sesuatu yang benar-benar dapat kita gunakan dengan mengganti titik dua dengan garis bawah, begitulah cara kita mendapatkan nama JS-nya:initWithContentRect_styleMask_backing_defer
. - Selanjutnya, kami memberikan setiap argumen yang dibutuhkan metode. Untuk argumen pertama,
contentRect
, kami menyediakan persegi panjang dengan ukuran yang cukup besar untuk antarmuka pengguna kami. - Untuk
styleMask
, kami menggunakan bitmask yang mengatakan bahwa kami ingin jendela kami memiliki tombol tutup, bilah judul, dan dapat diubah ukurannya. - Dua argumen berikutnya,
backing
dandefer
, akan selalu disetel keNSBackingStoreBuffered
danfalse
, jadi kita tidak perlu mengkhawatirkannya. (Dokumentasi untuk metode ini menjelaskan lebih lanjut mengapa ini terjadi.)
window.releasedWhenClosed = false; window.makeKeyAndOrderFront(null);
Di sini kita menyetel properti releasedWhenClosed
NSWindow
menjadi false
, yang artinya: “Hei! jangan hapus jendela ini dari memori hanya karena pengguna menutupnya.” Kemudian kita panggil makeKeyAndOrderFront
(null)
yang artinya: “Pindahkan jendela ini ke depan, dan berikan fokus keyboard.”
Tampilan Web: Antarmuka
Untuk mempermudah, saya telah menulis kode HTML dan CSS dari antarmuka pengguna web plugin yang akan kita gunakan; satu-satunya kode yang tersisa yang harus kita tambahkan ke dalamnya akan memastikan bahwa kita dapat berkomunikasi antara kode itu dan kode plugin Sketch kita.
Selanjutnya, unduh kode HTML dan CSS. Setelah Anda mengunduhnya, ekstrak, lalu pindahkan folder bernama "web-ui" ke folder Sumberdaya plugin kami.
Catatan : Menulis dan mengoptimalkan kode HTML/CSS yang sebenarnya berada di luar cakupan tutorial ini, karena fokusnya adalah pada JavaScript yang mendukung fitur inti plugin; tetapi ada banyak sekali tutorial di web tentang topik ini, jika Anda ingin mempelajari lebih lanjut.
Jika Anda menjalankan plugin kami sekarang, Anda akan melihat bahwa itu menunjukkan jendela — yay, kemajuan! Tapi itu kosong, tanpa judul, dan belum terlalu berguna. Kita perlu mendapatkannya untuk menunjukkan antarmuka web kita. Untuk melakukan itu, kita perlu menggunakan kelas asli lain, WKWebView
, yang merupakan tampilan yang dibuat khusus untuk menampilkan konten web.
Kami akan menambahkan kode yang diperlukan untuk membuat WKWebView
kami di bawah kode yang kami tulis untuk jendela kami:
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); };
Jika kita menjalankan plugin kita sekarang, kita akan melihat bahwa sekarang kita memiliki jendela terbuka yang menampilkan antarmuka pengguna web kita. Kesuksesan!
Sekali lagi, sebelum melanjutkan, mari kita periksa apa yang dilakukan kode yang kita tambahkan:
const webView = WKWebView.alloc().init();
Ini akan terlihat familier — pada dasarnya sama dengan apa yang kita lakukan ketika kita membuat NSWindow
: mengalokasikan memori untuk tampilan web, lalu menginisialisasinya.
window.contentView = webView;
Baris kode ini memberitahu jendela kita untuk menampilkan tampilan web yang baru saja kita buat.
const webUIFolderURL = context.scriptURL .URLByDeletingLastPathComponent() .URLByAppendingPathComponent("../Resources/web-ui/");
Disini tujuan kita adalah membuat URL yang mengarah ke folder web-ui
yang kita buat tadi. Untuk mendapatkan URL itu, kita perlu beberapa cara untuk mencari tahu di mana bundel plugin kita berada di sistem file pengguna. Di sini kita menggunakan properti context.scriptURL
, yang memberi kita URL dari skrip yang sedang berjalan . Namun, ini tidak memberi kami String
JavaScript seperti yang Anda harapkan, tetapi turunan dari kelas asli, NSURL
, yang memiliki beberapa metode di dalamnya yang membuat manipulasi string URL menjadi lebih mudah.
Kita perlu mengubah apa yang diberikan context.scriptURL
kepada kita —
file://path-to-your-plugin/Contents/Sketch/index.js
- ke dalam:
file://path-to-your-plugin/Contents/Resources/web-ui/
Selangkah demi selangkah:
- Memanggil
URLByDeletingLastPathComponent()
pertama kali memberi kitafile://path-to-your-plugin/Contents/Sketch/
- Memanggil
URLByDeletingLastPathComponent()
lagi memberi kamifile://path-to-your-plugin/Contents/
- Dan terakhir, menambahkan
Resources/web-ui/
ke akhir menggunakanURLByAppendingPathComponent
("Resources/web-ui/")
memberi kitafile://path-to-your-plugin/Contents/Resources/web-ui/
Kita juga perlu membuat URL kedua yang mengarah langsung ke file index.html
:
const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html");
Terakhir, kami memberi tahu tampilan web kami untuk memuat index.html
dan memberinya akses ke konten folder web-ui
:
webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL);
Baik. Sejauh ini, kami memiliki jendela yang menampilkan antarmuka pengguna web kami, seperti yang kami inginkan. Namun, ini belum sepenuhnya lengkap — desain asli kami tidak memiliki bilah judul (atau "chrome"), tetapi jendela kami saat ini memilikinya. Ada juga fakta bahwa ketika kita mengklik di dalam dokumen Sketch, dokumen itu bergerak di depan jendela kita, yang bukan itu yang kita inginkan — kita ingin pengguna dapat berinteraksi dengan jendela plugin dan dokumen Sketch tanpa harus terus-menerus memfokuskan kembali dari satu jendela ke jendela lainnya.
Untuk memperbaikinya, pertama-tama kita harus menyingkirkan chrome jendela default dan hanya menyimpan tombolnya. Menambahkan dua baris kode di bawah ini akan menghilangkan bilah judul.
Catatan: Seperti sebelumnya, semua properti dan metode yang kami gunakan di bawah ini didokumentasikan di halaman dokumentasi NSWindow
.
window.titlebarAppearsTransparent = true; window.titleVisibility = NSWindowTitleHidden;
Dua baris kode berikutnya akan menghapus tombol jendela (juga dikenal sebagai "lampu lalu lintas" dalam istilah MacOS) yang tidak kita butuhkan — "zoom" dan "minimize" — hanya menyisakan tombol "close":
window.standardWindowButton(NSWindowZoomButton).hidden = true; window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;
Sementara kita melakukannya, mari lanjutkan dan ubah warna latar belakang jendela agar sesuai dengan UI web kita:
window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);
Selanjutnya, kita perlu melakukan sesuatu untuk menjaga jendela plugin mengambang kita di atas jendela lain, sehingga pengguna dapat berinteraksi dengan dokumen Sketch mereka tanpa harus khawatir jendela Mosaic menghilang. Kita dapat menggunakan jenis NSWindow
khusus untuk ini, yang disebut NSPanel
, yang mampu "tetap di atas" jendela lain. Yang diperlukan untuk ini adalah mengubah NSWindow
menjadi NSPanel
, yang merupakan perubahan kode satu baris:
const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(
Sekarang kami memberi tahu jendela panel kami untuk mengapung (tetap di atas semua yang lain), dan hanya mengambil fokus keyboard/mouse bila perlu:
window.floatingPanel = true; window.becomesKeyOnlyIfNeeded = true;
Kami juga dapat mengubah jendela kami sehingga secara otomatis membuka kembali di posisi terakhir di:
window.frameAutosaveName = "mosaic-panel-frame";
Baris ini pada dasarnya mengatakan "ingat posisi jendela ini dengan menyimpannya dengan preferensi Sketch di bawah mosaic-panel-frame
kunci".
Semua bersama-sama, kita sekarang memiliki kode berikut:
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); };
Mengatur Kode
Sebelum kita pindah ke bagian berikutnya, ada baiknya untuk mengatur kode kita agar lebih mudah untuk dinavigasi dan diubah. Karena kita masih memiliki lebih banyak kode untuk ditambahkan dan kita ingin menghindari index.js
menjadi tempat pembuangan yang berantakan untuk semua kode kita, mari kita pisahkan sedikit dan pindahkan kode khusus UI kita ke dalam file bernama ui.js
, di bawah folder Sketch
. Kami juga akan mengekstrak beberapa tugas UI yang kami lakukan, seperti membuat tampilan web dan jendela, ke dalam fungsinya sendiri.
Buat file baru bernama ui.js
dan masukkan kode di bawah ini di dalamnya:
// 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 };
Ada beberapa perubahan penting yang kami buat di sini yang penting untuk diperhatikan. Selain fakta bahwa kami telah membuat fungsi khusus untuk membuat, menyembunyikan, dan menampilkan jendela kami dan tampilan webnya, kami juga telah memodulasi kode antarmuka pengguna kami.
Perhatikan baris module.exports = { loadAndShow, cleanup }
di bagian bawah? Ini adalah cara bagi kami untuk menentukan dengan tepat objek dan fungsi apa yang dapat digunakan skrip yang mengimpor kode UI ini (dan menyembunyikan yang tidak ingin mereka khawatirkan), yang berarti kami sekarang memiliki API yang lebih terorganisir untuk berinteraksi, menampilkan dan menghancurkan UI kami.
Bacaan yang disarankan : Melepaskan Potensi Penuh Simbol Dalam Sketsa
Mari kita lihat seperti apa ini dalam praktiknya. Kembali ke index.js
, hapus kode lama dan tambahkan berikut ini:
const UI = require("./ui"); function onRun(context){ UI.loadAndShow(context.scriptURL); };
Kami menggunakan fungsi khusus yang secara otomatis disediakan oleh Sketch untuk kami, require
, untuk mengimpor kode ui.js
kami dan menetapkan modul yang dikembalikan ke variabel UI
. Ini memberi kami akses ke API yang disederhanakan untuk memicu antarmuka pengguna kami. Segalanya jauh lebih rapi sekarang dan mudah ditemukan!
Kesimpulan
Bagus sekali — Anda telah melangkah jauh! 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!