UXPUB 🇺🇦 Дизайн-спільнота

Cover image for Руководство новичка по разработке Sketch-плагинов
Редакція
Редакція

Опубліковано • Оновлено

Руководство новичка по разработке Sketch-плагинов

Часть 1. С чего начать?

Вы хотите начать писать Sketch-плагины и не знаете, с чего начать? Продолжайте читать, так как этот пост как раз для вас!

Освоить базу не так просто. Есть масса примеров уже существующих плагинов, но очень сложно понять, с чего нужно начать. В помощь вам я собрал всю нужную информацию, которую только удалось отыскать, в одном месте.

Конечно, это не мануал по написанию плагинов для продвинутых, так как я сам не разработчик. Я UI/UX-дизайнер, которому иногда приходится кодить на довольно неплохом уровне (по крайней мере, я так думаю). Тру-программисты откровенно плачут, видя мой код, но я думаю, что как раз такой код хорошо понятен новичкам.

Если вы - инженер, который ищет более сложные примеры, вам будет полезен этот пост http://james.ooo/sketch-plugin-development, а также официальный сайт Sketch-разработчиков: http://developer.sketchapp.com/

Зачем писать плагин?

Плагины идеальны для автоматизации повторяющихся задач, они значительно упрощают работу и продакшн. Есть все шансы, что уже существует плагин под ваши нужды, так что сначала поищите готовое решение перед написанием своего. Очень вероятно, что кто-то уже справился с задачей лучше вас. Но если у вас уникальный рабочий процесс создания UI (как у меня с дизайном игровых интерфейсов в Unity), скорее всего вам потребуется кастомное решение.

Начало

Перед тем, как вы приступите к коду, установите все нужные программы и закладки.

  1. Установите текстовый редактор, если у вас его еще нет. (Я использую Atom, но есть много других отличных редакторов, таких как Sublime или Textmate).
  2. Откройте Консоль для дебага, и добавьте ее в свою панель Dock, вы часто будете ею пользоваться.

Image description

  1. Консоль используется вашей машиной для ВСЕГО дебага, так что создайте новый фильтр журнала запросов Sketch: File > New System Query Log

Скопируйте эти настройки и нажмите Ok.

Image description

Фильтр Sketch появится в колонке слева.

Image description

  1. Сделайте закладку папки Sketch Plugins для быстрого доступа, добавив ее в Избранное (Favorites) в окне Finder.

К этой папке вы тоже будете часто обращаться, так что желательно иметь ее под рукой.

/Library/Application support/com.bohemiancoding.sketch3/Plugins

Image description

Вот и все, вы готовы к написанию своего первого плагина!

Создание плагина за 10 простых шагов

Плагины Sketch - это папки с расширением .sketchplugin, которыми легко обмениваться с другими пользователями.

В этом примере мы создадим базовый скрипт для получения названия страницы. Вам не нужно знать программирование, чтобы реализовать эту задачу, но она поможет понять базовые принципы. В последующих постах я буду документировать разные скрипты для получения разных данных из Sketch и их изменения. Этот пример самый простой.

Плагины Sketch пишутся на CocoaScript, который представляет собой смесь Objective-C/Cocoa и JavaScript. Я неплохо знаком с Javascript, так что тут сложностей не возникло. Не скажу, что я в CocoaScript, как рыба в воде, но моих знаний по JavaScript было достаточно, чтобы разобраться.

Итак, начнем!

  1. Создайте новую папку в каталоге Sketch Plugins и назовите ее MyPlugin.sketchplugin

Image description

(как только вы добавите расширение .sketchplugin, двойной клик на ней запустит установку плагина вместо открытия папки. Чтобы открыть саму папку, кликните правой кнопкой мышки на плагине и выберите опцию Show Package Contents)._

  1. Внутри папки создайте еще одну папку и назовите ее Contents

  2. Внутри Contents создайте папку Sketch

Конечная структура папки плагина будет выглядеть так:

Image description

Внутри папки Sketch вы и будете создавать сам плагин, который состоит минимум из 2 файлов – манифеста и скрипта.

Image description

Манифест описывает плагин и может содержать разные горячие клавиши и дополнительные скрипты, он всегда называется manifest.json.

В скрипте содержится сам код плагина, и на него ссылается манифест. Имя можно изменять на свое усмотрение, но оно должно совпадать в обоих файлах.

  1. В текстовом редакторе создайте новый файл под названием manifest.json и сохраните его в MyPlugin.sketchplugin > Contents > Sketch

  2. Скопируйте и вставьте этот код в manifest.json, и сохраните.

Теперь MyPlugin появится в вашем меню плагинов Sketch. Вы можете изменить название плагина или горячую клавишу его вызова, и это отразится в меню Plugins в Sketch. Важно выбрать такую горячую клавишу запуска, которая не назначена для других установленных приложений или плагинов, иначе она не будет работать.

Теперь создадим MyScript.js, на который ссылается manifest. Убедитесь, что название файла совпадает с названием в файле manifest!

  1. Вернитесь в текстовый редактор и создайте новый файл под названием MyScript.js, и также сохраните его в папку MyPlugin.sketchplugin > Contents > Sketch folder

  2. Скопируйте и вставьте этот код в MyScript.js

Я детальнее поясню этот код в последующих частях. А пока что опирайтесь на комментарии в строках.

  1. Перейдите в Sketch и откройте новый файл

  2. В меню Plugins выберите MyPlugin > Get Page Names

Image description

  1. Перейдите в консоль и внизу лога вы должны увидеть название страницы

10:54:42 PM Get Page Names (Sketch Plugin): Page 1

Попробуйте изменить название страницы в Sketch-файле и перезапустите плагин. Лог должен показывать новое название. Добавьте еще одну страницу и переименуйте ее, а затем запустите плагин, консоль теперь покажет названия обеих страниц.

Вот и все!

Я работаю в Sketch всего несколько недель, и уже впечатлен его мощью и возможностями кастомизации. Вы можете скачать текущую версию плагина здесь.

Часть 2 - Пользовательские уведомления

Я открыл для себя отличный текстовый редактор Atom, на который и переключился. Не знаю, почему до сих пор не пользовался им, но теперь я попрощался со своим старым-добрым TextMate!_

В предыдущей главе мы работали над плагином, который показывал названия всех страниц вашего документа в Консоли. Теперь изучим другие способы отображения информации. Они нужны, если вы хотите уведомлять пользователей (и себя) о разных вещах, например, о том, что плагин отработал, или что пользователю необходимо ввести какие-то данные. Также вам не придется постоянно переключаться в консоль, чтобы протестировать свои скрипты.

Есть два дополнительных способа уведомления пользователей внутри Sketch:

  1. Сообщение (Message) - короткое ненавязчивое сообщение, которое отображается внизу приложения, прячется через короткий промежуток времени
  2. Окно оповещения (Alert Box) - стандартное всплывающее окно, которое либо запрашивает от пользователя ввод данных, либо требует какое-то действие для продолжения.

Для каждого способа есть свои случаи применения, и обычно вам не придется перегружать плагин (и пользователей) множеством сообщений. Поэкспериментируйте с обоими, чтобы понять, какой метод лучше для вашего собственного плагина.

Вернемся к скрипту плагина из первого примера и переделаем его.

Если рассматривать этот фрагмент кода, pageName ссылается на название каждой страницы в массиве страниц документа. Это контейнер с данными, содержащий всю информацию о странице. Обычно для доступа к этим массивам используются цикл for, которые итерируют через каждый объект, чтобы извлечь или назначить определенные значения.

В этой строке переменная pageName отправляется в Консоль.

log(pageName);

Теперь добавим сообщение вниз скрипта, который будет отображать сообщение внутри Sketch, когда скрипт отработает.

Для этого мы добавим строку кода после скобки цикла for:

doc.showMessage(“MyPlugin Finished!”);

Doc – это переменная вверху скрипта, которая ссылается на документ, а showMessage – это встроенная функция, в которой мы можем передавать переменную или строку (String) для отображения сообщения.

Вот как выглядит ее добавление после цикла for в контексте всего скрипта:

Запустите MyPlugin через меню Plugins, чтобы увидеть результат. Внизу окна Sketch вы должны увидеть:

Image description

Этот тип сообщений полезен, если вам не хочется постоянно переключаться в консоль, или если есть что-то, что вы бы хотели показать пользователю, но что не требует его участия.

Если вы хотите более выделяющегося сообщения, которое требует от пользователя какого-то действия, лучше использовать alert box. Чтобы добавить его, допишите строку кода в начало скрипта, и еще одну после отображения предыдущих сообщений.

Первая строка добавляется вверх, над объявлением переменной doc, чтобы обратиться к самому приложению:

var app = \[NSApplication sharedApplication\];

Вторая строка дает доступ к новой переменной для отправки сообщений в приложение.

[app displayDialog:"This is an alert box!" withTitle:"Alert Box Title"];

И вот как выглядит конечный код с новыми строками:

Запустите MyPlugin с меню Plugin, и вы должны увидеть что-то такое:

Image description

Меняйте сообщения (те, что в кавычках) на что угодно и перезапустите плагин. Полная кастомизация!

Это самое начало отладки и отображения данных внутри Sketch. Вы можете попробовать изменить скрипты сообщений/уведомлений, добавить дополнительные скрипты для показа разных данных - переменных или счетчиков массивов.

Чтобы показать количество страниц в документе, вы можете создать сообщение с отображением pages.count().

[app displayDialog:”This document has “ + pages.count() + “ pages.” withTitle:”Alert Box Title”\];

Вот таким будет результат:

Image description

Мы разобрались с пользовательскими уведомлениями! Сначала подготовили среду для разработки, затем разобрались, как дебажить и отображать сообщения внутри Sketch. Далее мы сфокусируемся больше на самом коде, поиске конкретных данных и способах их обработки.

Текущую версию плагина можно скачать здесь.

Часть 3 - Написание кода для многоразового использования

Настало время развернуть мониторы вертикально, потому что мы приступаем к программированию!

В этой части мы раскроем базовые концепты написания кода, создание функций для многократного вызова, а также линкование двух скриптов вместе. Если вы уже освоились в написании скриптов, можете просто проскроллить вниз до конца этой части, скачать исходники и переделать их на свой лад. Если же вы новичок в этом деле, или вам нужно освежить знания, продолжайте читать!

Базовые концепты написания кода

Есть код, который мы уже написали, и он включает в себя переменные, массивы, функции и циклы for. Эти элементы, а также операторы if/else, и есть фундаментальные кирпичики всего, что я делаю. Как только я освоил эти элементы (особенно, цикл loop), мне стало гораздо проще понимать скрипты. Я пишу свои скрипты на Javascript и Objective-C, но эти концепты довольно универсальны для любого языка программирования. Вам просто нужно выработать определенный способ написания кода.

Я бегло поясню эти понятия:

Переменная - это ссылка на какой-то тип информации. Это может быть как строка (кусок текста), так и число или булевское значение (true или false). Это горячая клавиша доступа к значению, и очень удобно использовать именно ее вместо того, чтобы печатать его руками снова и снова.

var myName = “Mike”;
var thisYear = 2016;
var givesHighFives = true;

Если я задам для myName значение “Mike”, тогда я просто могу писать везде в скрипте myName, и эта переменная будет ссылаться на “Mike”. Но если я захочу, чтобы значением myName стал “Shawn”, мне нужно будет изменить его только один раз в объявлении переменной, и каждая ее сущность в коде также изменится.

Массив - это тоже переменная, но обычно он содержит несколько однотипных значений. Как если бы у вас был массив дней недели, вы бы увидели стринговое значение всех дней внутри такого массива.

var daysOfTheWeek = {“Sunday”, “Monday”, “Tuesday”, Wednesday”, “Thursday”, “Friday”, “Saturday”};

Вы также можете написать его так, будет проще увидеть количество элементов массива, которые начинаются с 0:

var daysOfTheWeek\[\];
daysOfTheWeek\[0\] = “Sunday”;
daysOfTheWeek\[1\] = “Monday”;
daysOfTheWeek\[2\] = “Tuesday”;
daysOfTheWeek\[3\] = “Wednesday”;
daysOfTheWeek\[4\] = “Thursday”;
daysOfTheWeek\[5\] = “Friday”;
daysOfTheWeek\[6\] = “Saturday”;

Функция - это многократно используемый фрагмент кода, который выполняет определенную задачу. Обычно вы их задаете, если нужно делать что-то снова и снова. Вы можете передавать в нее переменные, заставлять их возвращать значение или держать их пустыми.

var eyesOpen = true;
function closeEyes(){
eyesOpen = false;
}
function openEyes(){
eyesOpen = true;
}

В примере выше каждый раз, когда вы хотите закрыть глаза, вы можете вызывать функцию closeEyes(), затем для их открытия вызывать openEyes().

Оператор if/else делает именно то, что говорит, т.е. проверяет какое-то условие, производит определенное действие, если условие выполняется, в противном случае выполняет что-то другое.

if(daysOfTheWeek == “Sunday”){
watchGameOfThrones();
}else if(daysOfTheWeek == “Wednesday”){
watchMrRobot();
}else{
watchTheNews();
}

Цикл for используется для повтора определенного блока кода известное количество раз. Например, в массиве daysOfTheWeek, если бы вы хотели вывести значения массива в список, вы бы воспользовались для этого циклом for.

Без цикла вы бы писали так:

log(daysOfTheWeek\[0\]);
 log(daysOfTheWeek\[1\]);
 log(daysOfTheWeek\[2\]);
 log(daysOfTheWeek\[3\]);
 log(daysOfTheWeek\[4\]);
 log(daysOfTheWeek\[5\]);
 log(daysOfTheWeek\[6\]);
Увійти у повноекранний режим Вихід із повноекранного режиму

А с циклом вам бы пришлось написать всего лишь:

for(var i = 0; i < daysOfTheWeek.count(); i++){
log(daysOfTheWeek\[i\];
}

Гораздо проще, правда? Для цикла мы задали начальное значение i, равное 0 и считали, пока i не достигнет количества значений в массиве daysOfTheWeek, т.е. 7. То есть начиная с i=0, цикл логирует значение daysOfTheWeek, потом добавляет к i 1, и все повторяется. Всего это проделывается 7 раз, пока не достигается полный набор значений в массиве.

Создание функции окна оповещения (Alert Box)

Вернемся к кодуMyPlugin. В предыдущей части мы создали окно оповещения, которое отображалось после отработки скрипта.

[app displayDialog:”This is an alert box!” withTitle:”Alert Box Title”];

Выглядит как что-то, что будет использоваться каждый раз, когда нам понадобится показать сообщения пользователю, и не особо хочется каждый раз прописывать всю строку кода для каждого такого сообщения. Это особенно актуально, если отображаемое сообщение - это комбинация переменных и строк, код может быть довольно длинный.

Отличный повод сделать повторно используемую функцию, и для этого нужно прописать:

Каждый раз, когда мы вызываем alert() и передаем заголовок и сообщение, будет отображаться окно оповещения.

Добавьте эту функцию в конец скрипта, после скобок функции onRun:

И теперь мы можем изменить код, написанный ранее, заменив им исходную ссылку на переменную, так как теперь она прописана в функции. Скрипт теперь выглядит так:

Запустите плагин, и вы будете видеть такой же результат, как раньше, но теперь ваш код ссылается на функцию. Ее можно вызвать в любом месте скрипта, и не нужно будет переписывать код снова и снова. Но что если бы у нас был другой скрипт, в котором нужно использовать эту функцию?

Ссылка на скрипты из других скриптов

И вот тут уместно создать библиотеку. Иногда у вас есть общая функция, которую не стоит привязывать к какому-то одному скрипту. Как в случае с функцией alert(), или с функцией округления числа до ближайшего целого. Это общие функции, которые, скорее всего, будут использоваться в разных скриптах. Поэтому вместо копипаста функции в каждый файл вы можете создать общий файл, и вставлять его по необходимости.

  1. Сохраните новый JavaScript-файл в ту же папку, в которой хранится MyScript.js, и назовите его common.js. Теперь в папке будет 3 файла:

Image description

  1. Вырежьте функцию alert из MyScript.js и вставьте ее в common.js и сохраните изменения.

В common.js должен быть только этот код:

  1. Чтобы запустить этот скрипт из MyScript.js, добавьте эту строку кода вверху скрипта и сохраните:

@import 'common.js'

Весь скрипт с новой строкой вверху и удаленной функцией alert() выглядит так:

Запустите плагин еще раз, он должен работать, как и раньше, но теперь вы запускаете функцию из общего скрипта! Оптимизация завершена!

Теперь у вас есть основы написания и понимания более сложных плагинов. Далее мы изучим доступ к данным документа Sketch через его переменные и массивы, способы прохождения по этим массивам для извлечения и назначения нужных нам значений.

Вы можете скачать текущую версию плагина здесь.

Часть 4 - Примеры из реального мира

Мы уже научились, как организовывать среду для написания и отладки кода, как отображать разные виды пользовательских уведомлений, а также освоили базовые понятия написания кода. Кажется, у нас есть все, чтобы начать писать собственные плагины.

К счастью, Bohemian Coding имеют документацию по своим классам:

http://developer.sketchapp.com/reference/class/

К сожалению, как пишется вначале этой страницы, она все еще “в стадии разработки”. Так что не все еще описано, и не так много примеров, что с этим всем делать.

Лично я лучше всего учусь на примерах. Понимание кода может вызывать большие трудности, но когда вы видите, как он используется применительно к вашим знаниям и целям, становится гораздо проще. Я приведу три примера, которые нашел, пока работал со Sketch, надеюсь, вам они окажутся полезными!

Пример 1: Переключение высоты и ширины артборда.

Странно, но в стандартном функционале Sketch нет смены ориентации артборда с портретной на альбомную и наоборот. Я поискал, и не нашел ни одного плагина, который решает эту проблему, так что самое время создать наш собственный!

Для ясности давайте определимся, что мы будем делать. Это помогает определить цель, способы ее достичь, а также выявить крайние случаи, с которыми придется столкнуться. Это почти как создание UX-сценария, правда?

Для этого плагина мы напишем скрипт, который выполняет следующее:

  • Сначала убеждается, что что-то выделено
  • Затем убеждается, что выделенный объект - это артборд
  • Затем берет исходную высоту и ширину выбранного артборда и сохраняет их в переменные
  • Затем задает новую высоту на основе его старой ширины, и новую ширину на основе старой высоты
  • В конечном итоге, уведомляет пользователя, что скрипт отработал

Добавление еще одного скрипта в MyPlugin

Вместо добавления новой порции кода в MyScript.js, давайте создадим новый скрипт под названием RotateArtboard.js, и сохраните его в папку MyPlugin.sketchplugin.

Добавьте этот код в RotateArtboard.js. Каждый основной скрипт должен быть в функции onRun, так что этот скрипт всегда является хорошей базой для старта:

Вы увидите, что мы импортируем файл common.js, чтобы использовать ту же функцию alert, которую мы уже создали.

На данный момент в папке плагина должны быть следующие файлы:

Image description

Теперь откройте manifest.json, чтобы добавить еще один скрипт в наш манифест.

Скопируйте фрагмент кода со всеми командами MyScript.js, добавьте запятую после блока MyScript, и вставьте перед закрывающейся скобкой commands, вот так:

Теперь вы видите новый скрипт в меню MyPlugin (можете менять горячие клавиши, кстати):

Image description

Вернемся к коду!

Чтобы узнать, что выделено, используем следующее:

var selection = context.selection;

Этот код создает переменную типа массив со всеми выделенными слоями. Теперь мы можем проверить этот массив, чтобы узнать, есть ли что-нибудь внутри него. Если там 0, тогда ничего не выделено, и мы скажем пользователю, что нужно что-то выделить.

if(selection.count() == 0){
doc.showMessage(“Please select something.”);
}

Но если счетчик не 0, тогда внутри массива что-то есть, как минимум, один слой должен быть выделен. Теперь мы можем пройтись циклом по выделенным слоям, чтобы определить, есть ли среди них артборды (MSArtboardGroup):

if(selection.count() == 0){
doc.showMessage(“Please select something.”);
} else {
for(var i = 0; i < selection.count(); i++){
if(selection\[i\].class() == "MSArtboardGroup"){
//do something
}
}
}

Вы можете использовать эту же технику для проверки, является ли выделение текстовым слоем (MSTextLayer), группой (MSGroupLayer), фигурой (MSShapeGroup / не задокументированная), импортированным изображением (MSBitmapLayer) или символом (MSSymbolInstance / не задокументированная)._

Чтобы получить высоту и ширину артборда, сначала нужно получить его фрейм. И уже из фрейма можно извлечь значения, и назначить новые.

Создайте переменную под названием artboard на основе элемента массива в цикле for, и так мы сможем получить текущие размеры. Использование цикла for позволяет работать с несколькими выделенными артбордами одновременно.

var artboard = selection\[i\];
var artboardFrame = artboard.frame();
var artboardWidth = artboardFrame.width();
var artboardHeight = artboardFrame.height();
Увійти у повноекранний режим Вихід із повноекранного режиму

Теперь создайте две новые переменные со значениями, которые нам нужны, т.е. поменяйте местами ширину и высоту:

var newArtboardWidth = artboardHeight;
var newArtboardHeight = artboardWidth;
Увійти у повноекранний режим Вихід із повноекранного режиму

Затем воспользуемся artboardFrame, чтобы задать высоту и ширину новыми переменными:

artboardFrame.setWidth(newArtboardWidth);
artboardFrame.setHeight(newArtboardHeight);
Увійти у повноекранний режим Вихід із повноекранного режиму

И, наконец, мы воспользуемся нашим окном уведомлений, чтобы сообщить пользователю об отработке скрипта и отобразить новые значения:

var alertMessage = “New Height: “+newArtboardHeight+ “ | New Width: “+newArtboardWidth;
 alert(“Artboard Rotated!”, alertMessage)
Увійти у повноекранний режим Вихід із повноекранного режиму

Вот весь скрипт с комментариями:

Подытожим пример 1:

  • Проверяем, выделено ли что-то
  • Определяем тип слоя выделенного, и делаем кое-что, если это тот тип, который нам нужен
  • Извлекаем исходный фрейм нашего выделенного артборда, высоту и ширину, и сохраняем это в переменных
  • Создаем новые переменные c нужными нам значениями
  • Задаем для фрейма выделенного артборда эти значения

Пример 2: Выделение слоев и их переименование на имя символа

Вот еще одна проблема из реального мира, которую я обнаружил, работая с символами. Если я добавляю новый символ из своей библиотеки, имя слоя изменяется на имя символа. Если я переключаюсь на другой символ, название слоя все равно остается без изменений. Иногда я хочу задать свое название слоя, а иногда просто хочу переключить его на название нового символа. Вот еще один идеальный повод написать плагин!

Для этого примера, скачайте файл Sketch для справок.

В файле Sketch на первом артборде вы увидите символ под названием Square, он находится по центру. Также в библиотеке есть еще один символ под названием Circle.

Выделите Square, и используя опции справа измените Square на Circle

Image description

Теперь посмотрите на слои слева - слой все еще называется Square! Я думаю, что мог бы изменить название вручную, но это не прикольно, особенно если изменить нужно множество сущностей.

Сценарий для этого плагина такой:

  • Сначала убедиться, что что-то выделено
  • Затем убедиться, что выделен именно символ
  • Получить название символа
  • Проверить, совпадает ли название символа с названием слоя
  • Если нет, изменить название слоя на название символа
  • И, наконец, уведомить пользователя, когда скрипт отработает

Вы заметите, что у нового и предыдущего скрипта много общего – та же проверка на выделение, и определение типа выделенных объектов. Так что мы можем воспользоваться готовыми наработками, но все же это довольно специфический случай, так что будем создавать отдельный скрипт.

Следуя первым шагам из предыдущего примера, давайте добавим еще один скрипт в MyPlugin.sketchplugin, создав новый файл под названием SetLayerNameToSymbolName.js и добавим его в manifest.json. Чтобы сэкономить время, просто используйте RotateArtboard.js и “Save As”. Мы будем использовать этот скрипт очень часто, так что начнем отсюда и сделаем несколько изменений.

аша папка сейчас содержит такие файлы:

Image description

В этом скрипте, вместо проверки, является ли выделение MSArtboardGroup (артбордом), мы проверим, является ли оно MSSymbolInstance (символом). Если является, мы выясним название symbolMaster и сравним его с названием слоя.

И вот вам новый скрипт с парой измененных строк:

Подытожим пример 2

В этом примере мы усвоили:

  • Проверки, является ли выделение артбордом или символом, выполняются идентично.
  • Как получить название symbolMaster и название слоя
  • Как сравнить два названия и настроить название слоя, если они отличаются.

Пример 3: Задание названий символов в качестве названий слоев

Предыдущий скрипт работает идеально, но иногда мне не хочется выделять каждый слой вручную. Иногда после разбрасывания кучи символов по документу я просто хочу привести все названия слоев в соответствие с названиями символов без выделения слоя. Для этого понадобится изменить следующее:

  • Сначала получить все страницы документа
  • Затем получить все артборды на каждой странице
  • Затем получить все слои на каждом артборде
  • Затем проверить, является ли какой-то из этих слоев слоем символа
  • Затем проверить, не совпадает ли название слоя с названием символа
  • Если не совпадает, заменить название слоя и уведомить пользователя

Так как мы теперь не учитываем, что сейчас выделено, нам придется изменить скрипт, чтобы он прошелся по данным страниц документа. Затем мы воспользуемся рядом вложенных петель for, которые будут итерировать по массиву артбордов, затем по массиву слоев, и наконец, дойдут до каждого слоя. Цикл for внутри цикла for, который внутри цикла for.

Наверное, для этой задачи мы создадим еще один новый скрипт. Начните с нового файла под названием SetAllLayerNamesToSymbolNames.js и также добавьте его в manifest.json, как мы делали раньше.

Теперь в папке MyPlugin.sketchplugin будет столько файлов:

Image description

И плагин в вашем списке меню, вместе с предыдущими примерами должен отображать новую опцию, как только вы добавите новый файл в манифест:

Image description

Чтобы извлечь данные страниц документа, используйте следующий код:

var pages = \[doc pages\];

Чтобы получить артборды страниц, используйте цикл for:

Чтобы получить слои артборда, используйте цикл for внутри цикла for:

Далее, чтобы извлечь каждый отдельный слой, вам нужно пройтись по слоям внутри цикла for, и затем проверить, что это за слой:

Как только мы установили, что это слой символа, мы можем проверить его название и сравнить с названием слоя. Если они отличаются, меняем название слоя на название символа, и все!

Вот как выглядит весь скрипт, для простоты понимания почти каждая строка прокомментирована:

Подытожим пример 3, тут мы научились:

  • Проходиться по всем страницам документа, чтобы получить список артбордов
  • Проходиться по всем артбордам страницы, чтобы получить слои
  • Проходиться по всем слоям артборда и проверять их тип
  • Сравнивать имя слоя с именем символов
  • И, наконец, если имена отличаются, изменить название слоя на название символа

Вывод

Это всего три примера, как можно начать использовать базовые понятия доступных классов Sketch, изученных ранее. Тут еще многое можно сделать, но мы пока только начинаем! Далее мы рассмотрим еще больше способов доступа к дополнительным классам внутри Sketch, еще больше примеров из реального мира.

Вы можете скачать текущую версию плагина здесь.

Часть 5. Класс MSLayer

Мы уже ознакомились с реальными, рабочими примерами того, что могут сделать классы в Sketch, так что можно углубиться в их изучение дальше. В этой части мы сфокусируемся на классе MSLayer, а затем изучим классы, наследующие этот.

Класс MSLayer - это базовый класс всех слоев в Sketch, и все другие типы слоев - это подклассы, наследующие его. Все, что вы добавляете в ваш документ, является изначально слоем - страница, артборд, группа, фигура, текст, изображение и т.д. Все это - подклассы класса MSLayer, и они могут все, что может класс MSLayer, и даже больше.

Чтобы лучше понять терминологию, есть два типа данных, доступных через класс:

  1. Атрибуты - именованное свойство объекта (например, высота, ширина или название)
  2. Методы - функции, связанные с классами, обычно используется для изменения атрибутов (таких как изменение высоты, ширины или названия)

Документация на сайте разработчиков уже содержит неплохую базу атрибутов и методов классов. Так что мы нет смысла воспроизводить все здесь. Вместо этого я покажу вам самые простые способы просмотра атрибутов слоя и использования его методов в реальном мире.

Получение атрибутов слоя

В предыдущей части мы рассмотрели два способа получения данных о слое: с помощью цикла по массиву выделения, а также путем гнездования петель for в массиве страниц документа.

Предположим, что вы использовали массив выделения, чтобы получить переменную под названием layer:

Зная, что все слои - это подклассы базового класса MSLayer, мы можем получить некоторые атрибуты из любого типа слоев, независимо от его специфики, а затем хранить их в виде переменных для доступа в будущем.

Некоторые атрибуты являются на самом деле сущностями других классов, и имеют свои собственные атрибуты и методы на базе этих классов. Для них я покажу пару примеров, как вы можете углубиться в данные. Но для более тщательного изучения вопроса используйте ссылку на документацию.

Вот несколько атрибутов, которые доступны в классе MSLayer:

Класс (тип слоя):

var layerClass = layer.class();

Фрейм (размер и положение, относительно его артборда, сущность MSRect):

var layerFrame = layer.frame();

var layerWidth = layerFrame.width();
var layerHeight = layerFrame.height();
var layerXpos = layerFrame.x();
var layerYpos = layerFrame.y();
Увійти у повноекранний режим Вихід із повноекранного режиму

Стиль (границы, заливки, тени, внутренние тени, сущность MSStyle):

var layerStyle = layer.style();

//получение массива цветов заливки
 var layerFills = layer.style().fills();

//получение каждого цвета заливки
 for(var z = 0; z < layerFills.count(); z++){
    var fillColor = layerFills\[z\].colorGeneric();
 }
Увійти у повноекранний режим Вихід із повноекранного режиму

Название слоя:

var layerName = layer.name();
Увійти у повноекранний режим Вихід із повноекранного режиму

Видимость:

var layerIsVisible = layer.isVisible();
Увійти у повноекранний режим Вихід із повноекранного режиму

Статус блокировки:

var layerIsLocked = layer.isLocked();
Увійти у повноекранний режим Вихід із повноекранного режиму

Отражение (горизонтальное или вертикальное):

//горизонтальное
 var layerIsFlippedHorizontal = layer.isFlippedHorizontal();

//вертикальное
 var layerIsFlippedVertical = layer.isFlippedVertical();
Увійти у повноекранний режим Вихід із повноекранного режиму

Поворот:

var layerRotation = layer.rotation();
Увійти у повноекранний режим Вихід із повноекранного режиму

Родительская группа (страница, артборд или группа):

var layerParent = layer.parentGroup();
Увійти у повноекранний режим Вихід із повноекранного режиму

Статус выделения:

var layerIsSelected = layer.isSelected();
Увійти у повноекранний режим Вихід із повноекранного режиму

Absolute Rect (глобальный размер и положение в целом документе, сущность MSAbsoluteRect):

var layerAbsoluteRect = layer.absoluteRect();

var layerAbsoluteWidth = layerAbsoluteRect.width();
var layerAbsoluteHeight = layerAbsoluteRect.height();
var layerAbsoluteXpos = layerAbsoluteRect.x();
var layerAbsoluteYpos = layerAbsoluteRect.y();
Увійти у повноекранний режим Вихід із повноекранного режиму

CSSAttributeString:

var layerCSSAttributeString = layer.CSSAttributeString();
Увійти у повноекранний режим Вихід із повноекранного режиму

CSSAttributes:

var layerCSSAttributes = layer.CSSAttributes();
Увійти у повноекранний режим Вихід із повноекранного режиму

В документации есть еще несколько, но это те, которые я обычно использую. Я выбрал на основе нужд скрипта. Но если вы действительно хотите сохранить все эти атрибуты сразу в переменные, вы бы могли сделать нечто такое:

Затем вы можете использовать консоль для логирования любых переменных, которых хотели бы видеть:

log(“Layer Rotation: “ + layerRotation);
Увійти у повноекранний режим Вихід із повноекранного режиму

Использование методов

Теперь, когда мы научились получать атрибуты слоя, мы можем использовать методы для их настройки. В классе MSLayer есть несколько доступных методов, которые позволяют менять конкретные атрибуты любого слоя. Их названия выдают их действия:

setName

var newLayerName = "New Layer Name";
layer.setName(newLayerName);
Увійти у повноекранний режим Вихід із повноекранного режиму

setIsVisible

//показать слой
 layer.setIsVisible(true);
 //спрятать слой
 layer.setIsVisible(false);
 //переключить
 layer.setIsVisible(!layer.isVisible())
Увійти у повноекранний режим Вихід із повноекранного режиму

setIsLocked

//заблокировать слой
 layer.setIsLocked(true);
 //разблокировать слой
 layer.setIsLocked(false);
 //переключить
 layer.setIsLocked(!layer.isLocked());
Увійти у повноекранний режим Вихід із повноекранного режиму

setRotation

var newLayerRotation = 180;
 layer.setRotation(newLayerRotation);
Увійти у повноекранний режим Вихід із повноекранного режиму

setIsFlippedHorizontal

//отразить по горизонтали
 layer.setIsFlippedHorizontal(true);
 //сбросить
 layer.setIsFlippedHorizontal(false);
 //переключить
 layer.setIsFlippedHorizontal(!layer.isFlippedHorizontal());
Увійти у повноекранний режим Вихід із повноекранного режиму

setIsFlippedVertical

//отразить по вертикали
 layer.setIsFlippedVertical(true);
 //сбросить
 layer.setIsFlippedVertical(false);
 //переключить
 layer.setIsFlippedVertical(!layer.isFlippedVertical());
Увійти у повноекранний режим Вихід із повноекранного режиму

setIsSelected

//выделить
 layer.setIsSelected(true);
 //снять выделение
 layer.setIsSelected(false);
 //переключить
 layer.setIsSelected(!layer.isSelected());
Увійти у повноекранний режим Вихід із повноекранного режиму

дублирование

layer.duplicate();
Увійти у повноекранний режим Вихід із повноекранного режиму

Теперь вы можете создавать разные типы плагинов, просто извлекая атрибут слоя и перенастраивая его.

Например, если вы хотите разблокировать все слои, вы сначала можете проверить, заблокированы ли они, затем можете их разблокировать:

Или если бы вы хотели добавить префикс к названию слоя:

И еще много всего, опции действительно бесконечны!

Методы атрибутов

Атрибуты, которые являются сущностями других классов, таких как фрейм или стиль, также имеют свои методы.

Например, чтобы изменить ширину слоя до 100, вам понадобится использовать setWidth на переменной фрейма:

Если вы хотите добавить на слой заливку, вы можете использовать addStylePartOfType(0) на переменной стиля:

Определение типа подкласса слоя Finding the Layer Subclass Type

Это все вы можете делать с любым MSLayer. Но что если, например, вы хотите считать строку текста из текстового поля? Вам нужно знать сначала, является ли этот объект текстовым полем, иначе код выбросит вам ошибку о несуществовании String.

Не все подклассы описаны в документации, но так как мы можем выяснить класс слоя из атрибута класса, мы можем легко с этим справиться. И чтобы еще больше упростить себе задачу, специально для этого я написал плагин!

Скачайте и установите плагин Show Layer Type Plugin здесь

Затем скачайте и откройте этот файл Sketch для тестирования.

В файле Sketch вы увидите артборд с несколькими разными типами слоев - 2 линии, символ, 2 текстовых поля и прямоугольник.

Image description

Выделите все слои и запустите плагин Show Layer Type. В консоли вы увидите такой вывод:

8/28/16 9:07:18.993 AM Show Layer Type (Sketch Plugin)\[46515\]: Background is a: MSShapeGroup
 8/28/16 9:07:18.997 AM Show Layer Type (Sketch Plugin)\[46515\]: Line is a: MSShapeGroup
 8/28/16 9:07:18.999 AM Show Layer Type (Sketch Plugin)\[46515\]: Author is a: MSTextLayer
 8/28/16 9:07:18.999 AM Show Layer Type (Sketch Plugin)\[46515\]: Icon is a: MSBitmapLayer
 8/28/16 9:07:19.000 AM Show Layer Type (Sketch Plugin)\[46515\]: Oval is a: MSSymbolInstance
 8/28/16 9:07:19.001 AM Show Layer Type (Sketch Plugin)\[46515\]: Title is a: MSTextLayer
 8/28/16 9:07:19.002 AM Show Layer Type (Sketch Plugin)\[46515\]: Line is a: MSShapeGroup
Увійти у повноекранний режим Вихід із повноекранного режиму

Если вы перейдете на страницу Symbols и выберите символ, снова запустите плагин, то увидите следующее:

8/28/16 9:10:08.600 AM Show Layer Type (Sketch Plugin)\[46515\]: Oval is a: MSSymbolMaster
Увійти у повноекранний режим Вихід із повноекранного режиму

Если вы выделите артборд и запустите плагин, вывод будет таким:

8/28/16 9:10:48.226 AM Show Layer Type (Sketch Plugin)\[46515\]: Artboard 1 is a: MSArtboardGroup
Увійти у повноекранний режим Вихід із повноекранного режиму

Если вы сгруппируете все слои на артборде, затем запустите плагин, увидите следующее:

8/28/16 9:11:24.234 AM Show Layer Type (Sketch Plugin)\[46515\]: Group is a: MSLayerGroup
Увійти у повноекранний режим Вихід із повноекранного режиму

Вот и все типы подклассов слоев! Возможно, есть и другие, но это все, которые мне удалось найти (документированные я сопроводил ссылками).

MSShapeGroup

MSBitmapLayer

MSTextLayer

MSSymbolInstance

MSSymbolMaster

MSArtboardGroup

MSLayerGroup

Теперь мы можем дифференцировать код в зависимости от того, какой этот класс, используя операторы if/else.

Каждый из этих подклассов располагает гораздо большим количеством атрибутов и методов доступа, которые мы рассмотрим в других постах. Изучите документацию по подклассам layer, чтобы быть готовым к старту!

Выводы

В этой части мы научились, как:

  • Просматривать атрибуты слоя
  • Изменять атрибуты слоя с помощью методов
  • Получать доступ к атрибутам атрибутов и методов
  • Проверять тип класса слоя и различать их в коде

Часть 6 — Экспорт данных

Sketch предоставляет удобный доступ к выходному коду svg и css через клик правой кнопкой мыши на слое. Это очень полезная опция для веб-дизайнеров, но для тех, кто занимается разработкой приложений или игр пользы в этом мало. Также приходится копировать и вставлять значения из одного приложения в другое, что представляет собой огромное поле для ошибок.

Есть много сторонних инструментов-мостиков между дизайном и разработкой (Zeplin, Avocode, Sketch Measure, Sympli и др.), но эти инструменты предоставляют лишь справочное руководство для разработчиков. Было бы куда полезнее, если приложения для дизайна и разработки работали вместе напрямую. Представьте: вы делаете дизайн чего-то в Sketch, нажимаете “экспортировать”, считываете свой проект по разработке и воссоздаете макет. Это избавит от необходимости в попиксельных спецификациях, и даже сэкономит время инженера на воссоздании дизайна в коде.

Набор инструментов, доступный для дизайнеров сейчас, создавался как решения для общих потребностей, они не заточены под каких-то специфические задачи. Но в этом и состоит прелесть разработки плагинов: вы можете создавать инструменты четко под свои нужды, нужно только знать, как это делать.

Мы уже прошлись по базе, получили фундамент для успешного программирования. Теперь же мы можем углубиться в самое сердце разработки плагинов, сделать реальное решение для реальной задачи.

Плагины Sketch - это инструменты, соединяющие дизайн с разработкой

Чтобы соединить дизайн и разработку, нужно найти общую основу двумя этими сферами. Так как нет родных способов их соединить, что мы можем использовать такое, что понятно обоим? Ответ - XML или JSON. С помощью плагинов Sketch может экспортировать данные в оба формата, и, скорее всего, среда разработки, в которой вы работаете, может их считывать. Так зачем слать разработчику пиксельные спецификации, из которых придется копировать значения вручную, если можно отослать их в файле XML и JSON и импортировать автоматически?

Это действительно одно из лучших решений, возможных для Sketch. В этой части я покажу базовый пример, как экспортировать атрибуты слоя в XML или JSON. По аналогии с предыдущими частями, давайте набросаем план. Наш плагин будет работать в таком порядке:

  1. Выделяем слой
  2. Создаем модальное окно для выбора папки пользователем и сохранения этого местоположения в переменной.
  3. Из выделенного поля создаются переменные для хранения базовой информации (Название, координата X, координата Y, высота и ширина).
  4. Сохраняем все эти переменные либо в XML, либо в JSON-объект.
  5. И, наконец, сохраняем этот объект в файл XML или JSON в предварительно выбранную папку.

Экспорт XML

Для начала мы начнем с создания нашего плагина. Создайте плагин под названием Export Layer to XML с основным скриптом под названием ExportLayerToXML.js. Также нужно добавить наш файл common.js для использования кастомного окна уведомлений, который создавали в предыдущих частях.

Мы уже знаем, как определить, выделен ли слой:

В операторе else мы создадим панель, где пользователь будет выбирать, в какую папку сохранить файл:

Потом создадим переменную, которая будет проверять, нажата ли кнопка, подключим ее к кнопке ОК, затем отформатируем выбранную категорию и сохраним ее в переменную для дальнейшего использования:

Когда все будет сделано, пройдемся циклом по выделенным слоям и вызовем функцию, которая записывает данные в XML-файл. Получившийся код будет выглядеть так:

Теперь для функции exportXML передадим 2 значения: выделенный слой и file_path.

Сначала мы настроим XML:

Затем из переданного слоя извлечем нужные переменные:

Сохраним эти переменные в объект XML:

И наконец, запишем XML-файл по переданному пути файла и уведомим пользователя, когда все будет сделано:

Скрипт целиком выглядит так:

Скачайте плагин или просмотрите его на GitHub, протестируйте. Если вы создадите прямоугольник на артборде и экспортируете в XML, получится примерно так:

Экспорт JSON

Сохранение JSON-файла реализуется почти также, кроме пары моментов. Мы можем использовать первую часть скрипта и создать функцию exportJSON, которая выглядит так:

Скрипт целиком выглядит так:

Вы можете скачать плагин здесь или посмотреть его на GitHub. Если протестируете скрипт, получите JSON-файл с таким содержимым:

{“layer”:\[{“name”:”Rectangle”,”xPos”:”550",”yPos”:”258",”height”:”234",”width”:”235"}\]}

Заключение

По итогу этой части мы научились:

  • Создавать модальное окно для сохранения файла
  • Создавать объекты XML и JSON для хранения переменных
  • Сохранять файлы XML и JSON в определенную папку.

Это всего лишь подсказка, как работать с экспортом данных из Sketch. Я только добавил пару атрибутов для старта, но есть огромное количество данных, из которых можно выбрать нужные для ваших целей.

Спасибо, что читаете наш урок, делитесь своими достижениями в комментариях. Успехов в создании собственных плагинов!

Удачи вам в создании собственных плагинов, делитесь достижениями под этим постом.


Перевод статьи Mike Mariano

Топ коментарі (0)