JavaScript, HTML ve CSS ile Eskiz Eklentisi Nasıl Oluşturulur (Bölüm 1)

Yayınlanan: 2022-03-10
Kısa özet ↬ Daha önce Sketch ile çalıştıysanız, "Keşke Sketch bunu belirli bir şeyi yapabilseydi, elimdeki görevi başarabilirdim" diye düşündüğünüz birçok an olmuştur. çok daha hızlı, daha kolay ve daha iyi.” Pekala, artık üzülme! Bu iki bölümden oluşan makalede, kendi Sketch eklentilerinizi sıfırdan nasıl oluşturacağınızı öğreneceksiniz - bu tür sorunları tam olarak çözmek için gereken becerileri size verecek.

Bu eğitim, Sketch uygulamasını bilen ve kullanan ve kodla uğraşmaktan korkmayan kişiler için hazırlanmıştır. Bundan en iyi şekilde yararlanmak için JavaScript (ve isteğe bağlı olarak HTML/CSS) yazma konusunda en azından bazı temel deneyime sahip olmanız gerekir.

Oluşturacağımız eklentinin adı “Mozaik”. Birinci bölümde, bir Sketch eklentisini oluşturan temel dosyalar hakkında bilgi edineceğiz; Biraz JavaScript yazacağız ve eklentimiz için HTML ve CSS yardımıyla bir kullanıcı arayüzü oluşturacağız. Bir sonraki makale, kullanıcı arayüzünü çekirdek eklenti koduna nasıl bağlayacağınız, eklentinin ana özelliklerinin nasıl uygulanacağı hakkında olacak ve bunun sonunda, kodun nasıl optimize edileceğini ve eklentinin çalışma şeklini de öğreneceksiniz.

Ayrıca eklentinin kodunu (JS, HTML, CSS) ve inceleyebileceğiniz ve öğrenme amaçlı kullanabileceğiniz dosyaları da paylaşacağım.

Sketch Eklentileri Nelerdir ve Nasıl Çalışırlar?

Sketch'te eklentiler, Sketch'te "kutudan çıktığı gibi" bulunmayan özellikler ve işlevler eklemenin bir yoludur. Herhangi bir programda hemen hemen her zaman bazı eksik özellikler veya entegrasyonlar olacağı düşünüldüğünde (özellikle herhangi bir tasarımcının sahip olabileceği çok sayıda ihtiyaç göz önüne alındığında!), Eklentilerin nasıl özellikle yararlı ve güçlü olabileceğini hayal etmeye başlayabilirsiniz. Sketch eklentileri, renk, şekil, boyut, düzen, stil, gruplama ve katmanların efektlerini değiştirmek gibi beklediğiniz hemen hemen her şeyi yapabilir, ancak aynı zamanda internet kaynaklarına istekte bulunmak, bir kullanıcıyı sunmak gibi şeyler de yapabilir. arayüz ve çok daha fazlası!

Programlama tarafında, tüm Sketch eklentileri JavaScript kodunda yazılmıştır. Aslında, bu tamamen doğru değil. Çoğu Sketch eklentisinin JavaScript ile yazıldığını söylemek daha doğru olur, çünkü az miktarda JavaScript bilgisi gerektirmelerine rağmen Apple'ın programlama dillerinden biri olan Objective-C ve Swift'de bir Sketch eklentisi yazmak da mümkündür.

Yine de endişelenme. Bu makalede, yalnızca JavaScript, HTML ve CSS kullanarak Sketch eklentilerinin nasıl oluşturulacağına odaklanacağız. HTML, CSS veya JavaScript'in temellerinin üzerinden geçmeyeceğiz - bu makale, bu üçüyle ilgili en azından biraz bilgi ve deneyime sahip olduğunu varsaymaktadır. MDN geliştirici web sitesi, web geliştirme hakkında daha fazla bilgi edinmek için harika bir yer sağlar.

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Başlayalım!

Öncelikle Ne Yapıyoruz?

Bu eğitimde, katmanları oluşturabilecek, çoğaltabilecek ve değiştirebilecek ve ayrıca kullanıcıya güzel bir kullanıcı arayüzü sunabilecek, başlangıç ​​seviyesindekilere uygun basit bir eklentinin nasıl oluşturulacağını öğreteceğim. Bunu yaparak amacım, üzerine inşa edebileceğiniz ve kendi eklentilerinizi oluşturmak için kullanabileceğiniz temel bir bilgi oluşturmaktır.

İnşa edeceğimiz eklentinin adı Mosaic ve etkili bir şekilde bir “kalıp oluşturucu”. Katmanlarınızı besleyin, birkaç ayar yapın ve bir desen oluşturacaktır:

Mozaik eklentisinin kullanıcı arayüzünü ve birkaç örnek kalıbı gösteren resim.
Mozaik'in kullanıcı arayüzü ve onunla yapılan bazı desen örnekleri. (Büyük önizleme)

Mosaic'i kurmak ve onunla oynamak isterseniz, tamamlanmış eklentiyi GitHub'dan indirebilirsiniz.

Biraz tarih: Mosaic, büyük ölçüde Twist-and-Fade adlı eski bir Adobe Fireworks eklentisinden esinlenmiştir. Twist-and-Fade oldukça güçlüydü; tonunu, konumunu, dönüşünü, boyutunu ve opaklığını ayarlarken bir katmanı herhangi bir sayıda çoğaltabiliyordu. Eklenti, kasetteki iki dönen öğe için çerçeveler oluşturduğu bunun gibi animasyonlu GIF'ler bile oluşturabildi:

Dönen tamburlu bir müzik kasetini gösteren resim
Animasyonlu kaset (kaynak). (Büyük önizleme)

(Tam olarak nasıl çalıştığını görmek istiyorsanız, Twist and Fade'in tanıtım videosunu burada bulabilirsiniz.)

Bu öğreticinin amaçları doğrultusunda, öğreticiyi olabildiğince erişilebilir tutmak için kasıtlı olarak basitleştirilmiş olsa da, Sketch için biraz benzer bir eklenti oluşturacağız. Özellikle, eklentimiz şunları yapabilecektir:

  • Herhangi bir Sketch katmanını (bitmap veya vektör) çoğaltın ve kopyaların katmanının konumunu, dönüşünü ve opaklığını değiştirin. Bu bize Sketch'in JavaScript API'lerini kullanarak katmanları manipüle etmeye bir giriş sağlayacaktır.
  • Hâlihazırda aşina olabileceğiniz web teknolojilerini kullanarak eklenti için nasıl kolayca bir arayüz oluşturacağınızı öğretecek olan HTML, CSS ve JS kullanılarak oluşturulmuş bir kullanıcı arayüzü görüntüleyin. Eklenti arayüzü oldukça önemlidir, çünkü kullanıcının ortaya çıkan mozaik görüntüsünün nasıl görünmesini istediğine ilişkin kullanıcı girdilerini bu şekilde toplayacağız.

Temel Eklentimizi On Saniyede Oluşturma Düz

İlk olarak, oluşturmak istediğimiz eklenti için “temel” (veya şablon) oluşturacağız. Bir eklenti oluşturan tüm gerekli dosya ve klasörleri manuel olarak oluşturabiliriz, ancak neyse ki buna gerek yok - çünkü Sketch bunu bizim için yapabilir. Şablon eklentisini oluşturduktan sonra, uygun gördüğümüz şekilde özelleştirebileceğiz.

Şablon eklentisini oluşturmak için kullanabileceğimiz gerçekten hızlı ve kolay bir teknik var; bu, belirli bir anda uğraştığım herhangi bir sorunu çözmek için bir eklentiyi bir araya getirmem gerektiğinde hemen hemen benim başvurduğum yöntem. İşte nasıl çalıştığı:

Sketch açıkken, ekranın üst kısmındaki menü çubuğunu kontrol edin ve Plugins -> Run Script öğesine tıklayın. Bu, kodu test etmek ve çalıştırmak için kullanabileceğimiz bir iletişim kutusu açacaktır. Ayrıca içine girdiğimiz herhangi bir kodu, şu anda özellikle ilgilendiğimiz kısım olan bir eklenti olarak kaydedebiliriz.

Bu iletişim kutusundaki kodu temizleyin ve aşağıdaki demo koduyla değiştirin:

 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!");

Ardından, pencerenin sol alt tarafındaki Save Script as Plugin basın, bu eklentinin sahip olmasını istediğiniz adı girin (bizim durumumuzda bu “Mozaik”), ardından Save Script as Plugin .

Pencerenin sol alt köşesindeki "Kaydet"e basın ve bu eklentinin sahip olmasını istediğiniz adı girin. (Büyük önizleme)

İster inanın ister inanmayın, işimizi çoktan bitirdik - geriye kalan tek şey az önce pişirdiğimiz pastayı yemek. İşte eğlenceli kısım geliyor. Eklentiler menüsünü bir kez daha açtığınızda, şunun gibi bir şey görmelisiniz: yepyeni eklentiniz “Mozaik” olarak listeleniyor! Üstüne tıkla!

(Büyük önizleme)

Tebrikler, az önce ilk Sketch eklentinizi yazdınız!

“Mozaik”e tıkladıktan sonra görmeniz gereken şey yukarıdaki kısa video gibi olmalı, ekranın altında “Hey orada…” kelimeleriyle başlayan göze batmayan bir araç ipucu mesajı görünmelidir - işte yapıştırdığımız kod tam olarak bunu söylüyor. yapmak. Bu tekniği bu kadar harika yapan şey budur: sıfırdan bir eklenti oluşturmaya gerek kalmadan kodu yapıştırmayı, değiştirmeyi ve test etmeyi kolaylaştırır. Tarayıcınızın web konsoluna aşina iseniz veya daha önce oynadıysanız, bu temelde budur. Kodu oluştururken ve test ederken bu aracın arka cebinizde olması bir zorunluluktur.

Eklediğiniz kodun ne yaptığını kısaca gözden geçirelim:

İlk olarak, Sketch'in yerleşik JS kitaplığının sketch/ui modülünü içe aktarır ve onu UI değişkenine atar. Bu modül, birisini kullanacağımız arayüzle ilgili birkaç kullanışlı yöntem içerir:

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

Ardından, gördüğümüz araç ipucunda görüntülenmesini istediğimiz metin dizisiyle ( sketch/ui modülünün bir parçası olan) message yöntemini çağırır:

 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() yöntemi, kullanıcıya göze batmayan bir mesaj sunmanın harika bir yolunu sağlar; Odağı çalmanız gerekmediği (modal olmayan) ve süslü düğmelere veya metin alanlarına ihtiyaç duymadığınız durumlar için harikadır. Mosaic'i oluştururken bazılarını kullanacağımız uyarılar, istemler ve benzeri ortak UI öğelerini sunmanın başka yolları da vardır.

Eklentimizin Meta Verilerini Özelleştirme

Artık başlamak için temel bir eklentimiz var, ancak yine de daha fazla ince ayar yapmamız ve gerçekten bizim yapmamız gerekiyor. Bir sonraki adımımız eklentinin meta verilerini değiştirmek olacak.

Bu adım için eklenti paketi denen şeye göz atmamız gerekecek. 'Komut Dosyasını Çalıştır' penceresinde kaydet düğmesine bastığınızda, Sketch eklentinizi ~/Library/Application Support/com.bohemiancoding.sketch3/Plugins dizininde bulabileceğiniz Mosaic.sketchplugin adlı bir klasör olarak kaydetti. Bu biraz uzun ve hatırlaması can sıkıcı; kısayol olarak, Plugins -> Manage Plugins -> (right-click your plugin) -> Reveal Plugins Folder yoluyla da yukarı çekebilirsiniz. Finder'da tek bir dosya olarak görünse de, aslında Sketch'in çalıştırması için eklentimizin ihtiyaç duyduğu her şeyi içeren bir klasördür. Klasör olmasına rağmen tek bir dosya olarak görünmesinin nedeni, Sketch'i ilk yüklediğinizde .sketchplugin uzantısını bir "paket" (dosya olarak görünen özel bir klasör türü) olarak kaydetmesi ve otomatik olarak açılmasını istemesidir. açıldığında Sketch'te.

İçeri bir göz atalım. Mosaic.sketchplugin öğesine sağ tıklayın, ardından “Paket İçeriğini Göster” seçeneğine tıklayın. İçeride, aşağıdaki dizin yapısını görmelisiniz:

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

Orada neden .cocoascript uzantılı bir dosya olduğunu merak ediyor olabilirsiniz. Endişelenmeyin - bu yalnızca normal bir JavaScript dosyasıdır ve yalnızca daha önce girdiğimiz kodu içerir. Devam edin ve bu dosyayı index.js olarak yeniden adlandırın; bu, dizin yapısını aşağıdaki gibi görünecek şekilde değiştirecektir:

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

Bir eklenti paketi içindeki dosyaları düzenlemenin en yaygın yolu şudur: kodunuz (JavaScript) ve manifest.json , Sketch/ 'e aittir ve kaynaklar (düşünme görüntüleri, ses dosyaları, metin dosyaları, vb.) Resources/ 'a aittir.

manifest.json adlı dosyada ince ayar yaparak başlayalım. Visual Studio Code veya Atom gibi favori kod düzenleyicinizin içinde açın.

Şu anda burada nispeten az şey olduğunu göreceksiniz, ancak yakında daha fazlasını ekleyeceğiz. Eklenti bildirimi öncelikle iki amaca hizmet eder:

  1. İlk olarak, kullanıcıya eklentiyi tanımlayan meta veriler sağlar - adı, sürümü, yazarın adı vb. Sketch, eklentiniz için bir liste ve açıklama oluşturmak için Sketch -> Preferences -> Plugins iletişim kutusunda bu bilgileri kullanır.
  2. İkincisi, aynı zamanda Sketch'e işinize nasıl ineceğinizi de söyler; yani, Sketch'e eklentinizin menüsünün nasıl görünmesini istediğinizi, eklentinize hangi kısayol tuşlarını atamanız gerektiğini ve eklentinizin kodunun nerede yaşadığını söyler (böylece Sketch onu çalıştırabilir).

Eklentiyi kullanıcıya açıklayan 1. amaç göz önüne alındığında, muhtemelen şu anda kullanıcı için kafa karıştırıcı olabilecek ve eklentiyi tanımlamayı zorlaştıracak bir açıklama veya yazar verilmediğini fark edeceksiniz. İlgili anahtarların değerlerini şu şekilde ayarlayarak bunu düzeltelim:

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

Ardından, eklentinin tanımlayıcısını ayarlayalım. Bu tanımlayıcı, "sitenizin alanını alın, sırayı tersine çevirin, ardından ürününüzün adını sonuna yazın" demenin gerçekten kısa (veya sıkıcı, seçiminizi yapın) bir yolu olan "ters etki alanı gösterimi" olarak adlandırılan şeyi kullanır. Bu şuna benzer bir şekilde çıkacaktır: com.your-company-or-your-name-its-not-that-big-a-deal.yourproduct .

Bu adlandırma kuralına bağlı kalmak zorunda değilsiniz - diğer eklentilerle çakışmaları önleyecek kadar benzersiz olduğu sürece buraya istediğinizi koyabilirsiniz (ancak RDN formatına bağlı kalmak, özellikle de sağladığı gibi muhtemelen iyi bir fikirdir). eklenti tanımlayıcılarınız için basit, yeniden kullanılabilir bir sistem).

Bu amaçla, tanımlayıcınızı com.your-name.mosaic olarak değiştirin:

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

Kişisel olarak, meta verilerle ilgili tüm anahtarları (başlık, yazar, tanımlayıcı vb.) alıp her yere yayılmamaları ve bulmam gerektiğinde akıl sağlığımı korumama yardımcı olmak için bunları bildirimin üst kısmına yakın bir yerde gruplandırmayı seviyorum. .

Ardından menu ve commands tuşlarına bir göz atalım. Bu ikisi, Sketch'e hangi kodun çağrılacağını ve neye yanıt vereceğini söylemekten sorumludur.

menu tuşuna bakarsanız, değeri eklentimizin Plugins menüsünde görüneceği ad olan bir title anahtarı içerdiğini görürsünüz. Ayrıca, komut tanımlayıcılarının bir listesi olan bir items anahtarına sahiptir:

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

Şu anda bu listede yalnızca bir komut tanımlayıcısı var, "com.bohemiancoding.sketch.runscriptidentifier" . Komut tanımlayıcıları, commands listesinde her zaman bir komutu işaret eder. Şu anda eklentimizde bu tanımlayıcıya sahip olan yalnızca bir komut var:

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

Bir menu girişine bir komut tanımlayıcı eklediğinizde, Sketch bu tanımlayıcıya sahip komut girişini arayacak ve name anahtarının değerini (bu durumda “Mozaik”tir) gösterecek ve bunun yerine eklentinizin menüsünde gösterecektir. tanımlayıcının.

Komutların oynadığı role gelince, bir komut girişini, Sketch'e, bu komut çağrıldığında eklentimizin JavaScript kodunda hangi işlevi çalıştırmak istediğimizi söylemenin bir yolu olarak düşünebiliriz, “çağrı” genellikle kullanıcının ilgili menüye tıklamasıdır. kalem. Komut girişi kendi başına hiçbir şey yapmaz, yalnızca JSON'dur - yalnızca Sketch'e komut çağrıldığında çalıştırması gereken JavaScript'i nerede arayacağına dair bir açıklama sağlar.

Şimdiye kadar, bir komutun name ve identifier tuşlarının ne yaptığından bahsettik, ancak bir komutta ele alınması gereken iki anahtar daha var: script ve handlers .

script anahtarı, Sketch'e çalışması gereken JavaScript dosyasının nerede olduğunu söyler. Sketch'in söz konusu komut dosyasının Sketch/ klasöründe olduğunu nasıl varsaydığına dikkat edin, bu nedenle basitlik adına tüm JavaScript kodlarınızın Sketch/ klasörünün altında bir yerde olduğundan emin olmak isteyeceksiniz. Bu anahtardan geçmeden önce, tıpkı daha önce dosyayı yeniden adlandırdığımız gibi, bu anahtarın değerini index.js olarak değiştirdiğinizden emin olmanız önemlidir . Aksi takdirde Sketch, JavaScript dosyanızı bulamayacak ve çalıştıramayacaktır.

handlers anahtarının değeri, JavaScript'inizde hangi işlevin çağrılacağını belirlemek için Sketch'in baktığı şeydir. Burada yalnızca bir işleyici setimiz var: onRun değeriyle run . run , önceden tanımlanmış, yerleşik bir Sketch eyleminin adıdır. Bu run eylemi, bir kullanıcı bu komuta başvuran bir menü öğesini tıkladığında her zaman çağrılır. onRun , otomatik olarak oluşturulan script.cocoascript dosyasındaki (ki bunu index.js olarak yeniden adlandırdık) bir işlevin adıdır ve run olayı gerçekleştiğinde, yani kullanıcı menü öğesini tıkladığında çağrılmasını istediğimiz işlevdir.

Şimdiye kadar sahip olduğumuz örnekte, bu süreç şöyle bir şey oynuyor:

  1. Kullanıcı menü öğemize tıklar.
  2. Sketch, o menü öğesiyle ilişkili komutu bulur.
  3. Sketch, komutun başvurduğu komut dosyasını bulur ve onu çalıştırır (bu durumda, JavaScript'i index.js içinde yürütür).
  4. Bu komut bir menü öğesi tıklamasıyla çağrıldığından, bir run eylemi olarak kabul edilir. Bu, Sketch'in bir sonraki çağrılacak işlev için komutun handlers.run değerine bakacağı anlamına gelir, bu durumda bu onRun .
  5. Sketch, onRun işlevini çağırır.

Komutlar genellikle bir kullanıcının menü öğelerinizden birine tıklamasına yanıt olarak çağrılır, ancak aynı zamanda, kullanıcının seçimi veya bir katmandaki bir özelliği değiştirmesi gibi diğer kullanıcı eylemlerine yanıt olarak da çağrılabilirler. Ancak, bu eklenti için bu diğer eylemlerin hiçbirini kullanmayacağız. (Eylem API'si yardım sayfasında eylemler ve nasıl çalıştıkları hakkında daha fazla bilgi edinebilirsiniz.)

Bu manifestodan geçmeden önce, iki ince ayar daha yapmak isteyeceğiz. Şu anda menümüz şu yapıya sahip:

 Mosaic └ Mosaic 
Mozaik menü öğesinin, Mozaik adlı başka bir menünün içinde fazladan iç içe olduğunu gösteren resim
Oldukça gereksiz, değil mi? (Büyük önizleme)

…bu biraz gereksiz çünkü eklentimizde sadece bir menü öğesi var. Eklentimiz artık bir yerine iki tıklama aldığından, kullanıcımız için biraz gereksiz sürtüşme de ekler. Bunu, menümüze menu isRoot: true ekleyerek düzeltebiliriz:

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

Bu, Sketch'e ilk menü öğelerini menünün title altına yerleştirmek yerine doğrudan Plugins menüsünün altına yerleştirmesini söyler.

Kaydet'e basın ve Sketch'e dönün. Şimdi Mosaic -> Mosaic yerini sadece Mosaic aldığını görmelisiniz - mükemmel!

Mozaik eklentisinin kullanıcı arayüzünü gösteren resim
Mozaik'in kullanıcı arayüzü. (Büyük önizleme)

İkinci ince ayarımıza gelince, devam edelim ve bu komut tanımlayıcısını daha az hantal bir şeyle yeniden adlandıralım. Komut tanımlayıcılarının yalnızca bireysel bir eklenti bağlamında benzersiz olması gerektiğinden, onu "open" gibi daha kısa ve açık bir şekilde güvenle yeniden adlandırabiliriz:

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

Devam etmeden önce, menülerin başka menüler de içerebileceğini belirtmekte fayda var. Başka bir menünün items listesinin içine başka bir { title: ..., items: ... } girişi yerleştirerek kolayca bir alt menü oluşturabilirsiniz:

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

Eklentinin Kullanıcı Arayüzünü Oluşturma

Şimdiye kadar bazı demo kodları yazdık ve eklentimizin manifestosunu özelleştirdik. Şimdi, esasen bir pencereye gömülü bir web sayfası olan kullanıcı arayüzünü oluşturmaya devam edeceğiz (kullanmaya alışkın olduğunuz tarayıcılara benzer şekilde):

Eklentinin penceresi. (Büyük önizleme)
Eklentimizin arayüzünü oluşturan bileşenleri gösteren resim: pencere ve web görünümü
Eklentimizi oluşturan bileşenler. (Büyük önizleme)

Pencere

Mosaic'in kullanıcı arayüzü tasarımının en temel bileşeni olarak kabul edebileceğimiz kendi penceresi vardır; onunla başlayacağız. Bir pencere oluşturmak ve görüntülemek için, varsayılan olarak macOS'ta yerleşik olarak NSWindow adlı bir sınıfı kullanmamız gerekecek. Bu öğreticinin geri kalanında, aslında bunu biraz yapacağız ( NSWindow gibi yerleşik API'leri kullanarak), bu da aşina değilseniz biraz göz korkutucu görünebilir, ancak endişelenmeyin - açıklayacağım yol boyunca her şey!

Not: Yerleşik API'lerden bahsederken, bu sınıfı kullanabilmemizin nedeni, Sketch eklentileri tarafından kullanılan JavaScript çalışma zamanında bulunan bir köprü sayesindedir. Bu köprü, normalde yalnızca yerel uygulamalar tarafından kullanılabilen bu yerleşik sınıfları, yöntemleri ve işlevleri otomatik olarak içe aktarır.

Kod düzenleyicinizde Sketch/index.js açın, orada olanları silin ve aşağıdakileri yapıştırın:

 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); };

Şimdi bu ilk kod parçasının ne yaptığına bir göz atalım:

 function onRun(context){

Daha önce komutlar ve nasıl çalıştıkları hakkında konuştuğumuzu ve onRun olarak adlandırılan bir menü tıklamasına yanıt olarak aramasını söylediğimizi hatırlıyor musunuz? (Bir tazelemeye ihtiyacınız varsa, yukarıdaki kısmı tekrar ziyaret edin, sonra geri gelin.) Bu bitin tek yaptığı o işlevi yaratmaktır. Ayrıca onRun fonksiyonumuzun bir context argümanı aldığını fark edeceksiniz. Bu, Sketch'in komut işleyicilerinizi arayacağı ve bize belirli bilgileri sağlayabilecek bir argümandır. Daha sonra, eklenti paketimizin URL'sini kullanıcının bilgisayarında almak için kullanacağız.

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

Burada aslında birkaç şey yapıyoruz:

  1. İlk olarak, NSWindow üzerinde alloc() 'u çağırıyoruz; bu temelde "NSWindow'un bir örneği için bir miktar bellek ayırın" anlamına gelir. Oluşturmak istediğiniz yerel sınıfın her örneği için bunu yapmanız gerekeceğini bilmek yeterlidir. alloc yöntemi her yerel sınıfta mevcuttur.
  2. Daha sonra, initWithContentRect:styleMask:backing:defer: adlı NSWindow başlatıcı yöntemini (yani, aslında NSWindow örneğini oluşturan yöntem) çağırırız. Bunun yukarıdaki kodumuzda adlandırdığımızdan farklı olduğunu fark edeceksiniz - her argüman arasında bir sürü iki nokta üst üste ( : ) var. Bu sözdizimini JavaScript'te kullanamadığımız için Sketch, iki nokta üst üste işaretlerini alt çizgilerle değiştirerek gerçekten kullanabileceğimiz bir şeyle uygun bir şekilde yeniden adlandırır, bu şekilde JS adını alırız: initWithContentRect_styleMask_backing_defer .
  3. Ardından, yöntemin ihtiyaç duyduğu argümanların her birini iletiyoruz. İlk argüman olan contentRect için, kullanıcı arayüzümüz için yeterince büyük bir dikdörtgen sağlıyoruz.
  4. styleMask için, penceremizin bir kapat düğmesi, başlık çubuğu olmasını ve yeniden boyutlandırılabilir olmasını istediğimizi söyleyen bir bit maskesi kullanırız.
  5. Sonraki iki argüman, backing ve NSBackingStoreBuffered , her zaman defer ve false olarak ayarlanacak, bu yüzden onlar için gerçekten endişelenmemize gerek yok. (Bu yöntemin belgeleri, bunun neden olduğu konusunda daha fazla ayrıntıya girer.)
 window.releasedWhenClosed = false; window.makeKeyAndOrderFront(null);

Burada NSWindow releasedWhenClosed false olarak ayarladık, bu şu anlama gelir: “Hey! sırf kullanıcı kapatıyor diye bu pencereyi hafızadan silmeyin.” Ardından makeKeyAndOrderFront (null) adını veririz, bu şu anlama gelir: "Bu pencereyi öne taşı ve klavye odağını ver."

Web Görünümü: Arayüz

İşleri kolaylaştırmak için, kullanacağımız eklentinin web kullanıcı arayüzünün HTML ve CSS kodunu zaten yazdım; Eklememiz gereken tek kalan kod, onunla Sketch eklenti kodumuz arasında iletişim kurabileceğimizden emin olmakla ilgilenecek.

Ardından, HTML ve CSS kodunu indirin. İndirdikten sonra çıkarın, ardından “web-ui” adlı klasörü eklentimizin Kaynaklar klasörüne taşıyın.

Not : Asıl HTML/CSS kodunu yazmak ve optimize etmek, eklentinin temel özelliklerini destekleyen JavaScript'e odaklandığından bu eğitimin kapsamı dışındadır; ancak daha fazlasını öğrenmek isterseniz, web'de bu konuyla ilgili bir sürü öğretici var.

Eklentimizi şimdi çalıştırırsanız, bir pencere gösterdiğini göreceksiniz - evet, ilerleme! Ama boş, başlığı yok ve henüz pek kullanışlı değil. Web arayüzümüzü göstermesi için almamız gerekiyor. Bunu yapmak için, özellikle web içeriğini görüntülemek için yapılmış bir görünüm olan başka bir yerel sınıf olan WKWebView kullanmamız gerekecek.

WKWebView oluşturmak için gereken kodu penceremiz için yazdığımız kodun altına ekleyeceğiz:

 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); };

Eklentimizi şimdi çalıştırırsak, şimdi web kullanıcı arayüzümüzü görüntüleyen bir penceremiz olduğunu göreceğiz. Başarı!

Yine devam etmeden önce eklediğimiz kodun ne işe yaradığını inceleyelim:

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

Bu tanıdık gelmeli - temelde NSWindow yaptığımızda yaptığımızla aynı: bir web görünümü için bellek ayır, sonra başlat.

 window.contentView = webView;

Bu kod satırı, penceremize az önce yaptığımız web görünümünü görüntülemesini söyler.

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

Burada amacımız, daha önce oluşturduğumuz web-ui klasörüne işaret eden bir URL oluşturmaktır. Bu URL'yi almak için, eklentimizin paketinin kullanıcının dosya sisteminde nerede olduğunu bulmanın bir yoluna ihtiyacımız var. Burada, bize şu anda çalışan komut dosyasının URL'sini veren context.scriptURL özelliğini kullanıyoruz. Ancak, bu bize beklediğiniz gibi bir JavaScript String vermez, ancak üzerinde URL dizelerini değiştirmeyi kolaylaştıran birkaç yöntemi olan NSURL yerel sınıfının bir örneğini verir.

context.scriptURL bize verdiklerini çevirmemiz gerekiyor —

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

- içine:

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

Adım adım:

  1. URLByDeletingLastPathComponent() ilk kez çağırmak bize file://path-to-your-plugin/Contents/Sketch/ öğesini verir.
  2. URLByDeletingLastPathComponent() yeniden çağırmak bize file://path-to-your-plugin/Contents/ verir.
  3. Ve son olarak, URLByAppendingPathComponent ("Resources/web-ui/") kullanarak Resources/web-ui Resources/web-ui/ öğesinin sonuna eklenmesi bize file://path-to-your-plugin/Contents/Resources/web-ui/ öğesini verir.

Ayrıca doğrudan index.html dosyasına işaret eden ikinci bir URL oluşturmamız gerekiyor:

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

Son olarak, web görünümümüze index.html yüklemesini ve web-ui klasörünün içeriğine erişmesini sağlamasını söylüyoruz:

 webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL);

Peki. Şu ana kadar tam istediğimiz gibi web kullanıcı arayüzümüzü gösteren bir penceremiz var. Ancak, henüz tam olarak tamamlanmadı - orijinal tasarımımızda başlık çubuğu (veya "krom") yok, ancak mevcut penceremizde var. Ayrıca bir Sketch belgesinin içine tıkladığımızda, o belgenin penceremizin önünde hareket ettiği gerçeği de var ki bu bizim istediğimiz şey değil - kullanıcının eklenti penceresi ve Sketch belgesi ile zorunda kalmadan etkileşime girmesini istiyoruz. sürekli olarak bir pencereden diğerine odaklanın.

Bunu düzeltmek için öncelikle varsayılan pencere kromundan kurtulmamız ve sadece butonları tutmamız gerekiyor. Aşağıdaki iki kod satırını eklemek, başlık çubuğundan kurtulacaktır.

Not: Daha önce olduğu gibi, aşağıda kullandığımız tüm özellikler ve yöntemler NSWindow belgeler sayfasında belgelenmiştir.

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

Bu sonraki iki kod satırı, ihtiyacımız olmayan pencere düğmelerini (MacOS dilinde "trafik ışıkları" olarak da bilinir) kaldıracak - "yakınlaştır" ve "küçült" - yalnızca "kapat" düğmesini bırakacak:

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

Hazır buradayken, devam edelim ve pencerenin arka plan rengini web kullanıcı arayüzümüzünkiyle eşleşecek şekilde değiştirelim:

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

Ardından, kayan eklenti penceremizi diğer pencerelerin üstünde tutmak için bir şeyler yapmalıyız, böylece kullanıcı Mozaik penceresinin kaybolması konusunda endişelenmeden Sketch belgeleriyle etkileşim kurabilir. Bunun için, diğer pencerelerin “üstünde kalabilen” NSPanel adlı özel bir NSWindow türü kullanabiliriz. Bunun için tek gereken, NSPanel NSWindow değiştirmektir:

 const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(

Şimdi panel penceremize yüzmesini (diğerlerinin üzerinde kalmasını) ve yalnızca gerektiğinde klavye/fare odağını almasını söylüyoruz:

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

Ayrıca penceremizi, bulunduğu son konumda otomatik olarak yeniden açılacak şekilde ayarlayabiliriz:

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

Bu satır temel olarak “bu pencerenin konumunu, Sketch'in anahtar mosaic-panel-frame altındaki tercihleriyle kaydederek hatırla” diyor.

Hep birlikte, şimdi aşağıdaki kodumuz var:

 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); };

Kodu Düzenleme

Sonraki bölüme geçmeden önce, kodumuzu gezinmek ve ince ayar yapmak daha kolay olacak şekilde düzenlemek iyi bir fikirdir. Hâlâ ekleyecek çok kodumuz olduğundan ve index.js tüm kodlarımız için dağınık bir çöplük haline gelmesini önlemek istediğimizden, işleri biraz bölelim ve kullanıcı arayüzüne özel kodumuzu ui.js adlı bir dosyaya taşıyalım, Sketch klasörü altında. Web görünümü ve penceresi oluşturmak gibi yaptığımız bazı UI görevlerini de kendi işlevlerine çıkaracağız.

ui.js adında yeni bir dosya oluşturun ve içine aşağıdaki kodu ekleyin:

 // 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 };

Burada yaptığımız ve dikkate alınması gereken önemli birkaç değişiklik var. Penceremizin ve web görünümünün oluşturulması, gizlenmesi ve gösterilmesi için özel işlevler oluşturmamızın yanı sıra, kullanıcı arayüzü kodumuzu da modüler hale getirdik.

En alttaki module.exports = { loadAndShow, cleanup } satırına dikkat edin. Bu, bu UI kodunu içe aktaran nesnelerin ve işlev komut dosyalarının tam olarak hangi nesneleri ve işlev komut dosyalarını kullanabileceğini (ve endişelenmelerini istemediklerimizi gizleyerek) belirlememizin bir yoludur; bu, artık etkileşim için daha organize bir API'ye sahip olduğumuz anlamına gelir, UI'mizi gösterme ve yok etme.

Önerilen okuma : Sketch'teki Sembollerin Tüm Potansiyelini Ortaya Çıkarmak

Bunun pratikte nasıl göründüğünü görelim. index.js geri dönün, eski kodu kaldırın ve aşağıdakileri ekleyin:

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

ui.js kodumuzu içe aktarmak ve döndürülen modülü UI değişkenine atamak için require otomatik olarak bize sunduğu özel bir işlev kullanıyoruz. Bu, kullanıcı arabirimimizi tetiklemek için basitleştirilmiş bir API'ye erişmemizi sağlar. Artık işler çok daha düzenli ve bulması kolay!

Çözüm

Aferin - çok uzağa geldiniz! 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!