Sketch作为一款近些年流行起来的设计工具,在设计师里已经广为流传,Sketch的开发者甚至还为Sketch提供了开发插件的功能,让sketch有了更强的扩展性,正是基于如此强大的扩展性,让我们可以基于sketch做很多的扩展,今天在这里介绍下Sketch插件的开发方式。
技术方案
根据我自己的sketch插件开发经验,sketch插件开发有两种比较常用的技术选型
方式 | CocoaScript + Objective-C | skpm + JavaScript |
上手难度 | 低 | 中 |
文档丰富度 | 少 | 较丰富 |
编译方式 | 不用编译直接运行,“所写即所得” | 通过编译 bundle 运行 |
代码管理 | 明文保存,缺少混淆 | skpm工作集开发,发布,能够混淆 |
开发生态 | 缺少开发生态,需要手动编写工具类 | 可纳入前端生态,使用成熟的npm包等 |
开发工具 | 无限制,任何文本编辑器均可 | 使用js类如WebStorm等编辑器可提高开发效率 |
插件结构
从上面两个技术选型来看,各有千秋,目前我们的UI自动化插件两方面的技术选型都有使用到,这里先介绍第一种基于CocoaScript的方式,插件工程其实就是一个以.sketchplugin结尾的文件夹,里面的目录结构如下

可以直接双击example.sketchplugin进行安装,或者把该插件放在
/Users/xxxx/Library/Application Support/com.bohemiancoding.sketch3/plugins/
前一种方式的本质其实也是第二种方式
manifest.json
必不可少的文件,里面声明了插件的每个命令和对应入口函数
{
"author": "zujie.czj",
"identifier":"com.jc.testplugin",
"description":"Test",
"commands":[
{
"name":"HelloWorld",
"identifier":"com.jc.hello",
"handler":"onRunHello",
"script":"HelloWorld.cocoascript"
}
]
}
上面json里的identifier 用来表示该插件的ID唯一值,commands用来表示开发插件里的命令,比如上面我定义了一个名称为HelloWorld的command,它的入口方法在HelloWorld.cocoascript的onRunHello方法里

我们定义改命令的操作很简单,简单地打印一个HelloWorld
操作方式如下

可以在控制台看到Hello World输出

开发调试
代码知道怎么写了,那debug该如何操作呢?这方面插件支持还比较简陋,无法断点支持,只能通过打log,然后在mac的控制台程序里看输出来调试,就像前面打印的Hello World一样
context
从上面的介绍我们看到,插件的入口函数传入了一个context,这个context的包含这么些内容
- command: MSPluginCommand对象,代表当前执行的命令
- document: MSDocument 对象 ,当前的文档
- plugin: MSPluginBundle 对象,当前的插件bundle,里面包含当前运行的脚本
- scriptPath: NSString 当前执行脚本的绝对路径
- scriptURL: 当前执行脚本的绝对路径,跟 scriptPath不同的是它是个 NSURL 对象
- selection: 一个 NSArray 对象,包含了当前选择的所有图层。数组中的每一个元素都是 MSLayer 对象
通过这个context我们可以扩展出很多能力,比如我们这边实现一个选中图层弹出图层名称的简单功能
var onRunHello = function (context) {
//log("Hello World");
//log(JSON.stringify(context));
var selections = context.selection;
if(selections){
if(selections.length > 1){
context.document.showMessage("请选择一个图层");
}
else if(selections.length === 0){
context.document.showMessage("没有选中图层");
}
else{
var layer = selections[0];
context.document.showMessage(layer.name());
}
}
};
代码很简单,基本一看就懂,完成的效果就像
开发助手
使用CocoaScript我们需要知道sketch提供的api有哪些,官网文档并不丰富,但是有大神直接dump出sketch 的头文件, 通过这个头文件,我们基本所有的api都能查询到,开发资料一下子丰富起来

同时插件论坛 里面的问答资料也很丰富,回答也算及时,这些都能帮助快速开发出sketch插件。
skpm
我们一开始介绍过sketch插件开发还有另外一种skpm + JavaScript的方式,该种方式和前面所说的开发方式其实也是大同小异,但开发效率和工具却丰富得多。它基于丰富的工具库来做插件开发,前面介绍的方式如果是小米加步枪,这个方式至少算是扛着大炮做插件了。

安装skpm
npm install -g skpm
创建工程模板
直接在sketch的插件目录下
skpm create my-plugin
创建成功后

工程目录

目录 | 作用 |
src | 代码目录 |
*.sketchplugin | 编译产生资源,不可编辑,每次代码修改都需要编译生成 |
assets | 任何资源文件比如png都可以放在这个目录 |
开发
我们用这种新的技术手段把上面写的demo展示图层名字的demo改改
mainfiest.json:
{
"$schema": "https://raw.githubusercontent.com/BohemianCoding/SketchAPI/develop/docs/sketch-plugin-manifest-schema.json",
"icon": "icon.png",
"commands": [
{
"name": "my-command",
"identifier": "my-plugin.my-command-identifier",
"script": "./my-command.js",
"handlers" : {
"run" : "onRunName"
}
}
],
"menu": {
"title": "my-plugin",
"items": [
"my-plugin.my-command-identifier"
]
}
}
my-command.js:
let sketch = require('sketch');
let UI = require('sketch/ui');
// documentation: https://developer.sketchapp.com/reference/api/
export function onRunName() {
let doc = sketch.getSelectedDocument();
let selectedLayers = doc.selectedLayers;
let selectedCount = selectedLayers.length;
if (selectedCount > 1) {
UI.message('请选择一个图层')
}
else if (selectedCount === 0) {
UI.message('没有选中图层')
} else if (selectedCount === 1){
UI.message(selectedLayers.layers[0].name);
}
}
写完代码需要
npm run build
让代码生效。
上面的插件代码可以看出跟前一种方式比代码差异不大,但我们对应sketch提供的api是以import方式导入,同样的我们也可以import一些优秀的库比如treemap-js, xml-js等,这种方式相对开发资料更丰富,我们内部的插件开发新功能也基本采用这种技术方向开发
nice blog bro thanks, https://about.me/yerel1-bursa-eskort-bayan-sitesi
Bralette, sutyen gibi destek sağlamayan, daha çok rahatlık odaklı bir iç giyim parçasıdır. Genellikle ince askılara veya dantel detaylara sahiptir.