如何制作 Sketch 插件
Sketch 是近些年比较流行的 UI 设计软件,它比起之前常用的 Illustrator 或者 Photoshop 比较好的地方在于小巧功能简单但足够,同时对 Mac 的触摸板支持更加友好。另外它的插件系统也要比 Adobe 更加友好,大量的插件帮助我们解决协同和效率上的问题。
Sketch 插件最大的好处在于可以直接使用 JavaScript 进行开发,并提供了许多配套的开发工具。下面我就以帮助设计师同学快速插入占位图的插件 Placeholder 为例,带大家一步一步的了解如何进行 Sketch 插件开发。
在进行插件开发之前,我们需要了解一些基础的知识。Sketch 是一套原生 Objective-C 开发的软件,它之所以能支持使用 JS 开发,是因为它使用 CocoaScript1作为插件的开发语言。它就像是一座桥(Bridge),能让我们在插件中写 OC 和 JS,然后 Sketch 将基础方法进行了封装,实现了一套 JavaScript API2,这样我们就能使用 JS 开发 Sketch 插件了。
注: 关于如何开发插件,官方提供了一份入门教程《Create a plugin》3,在阅读下文之前,也可以花 2~3min 先看看这篇官方教程,内容比较简短。
需求整理
在进行插件开发之前,我们捋一捋我们需要实现的功能。http://placeimg.com/ 是一个专门用来生成占位图的网站,我们将利用该网站提供的服务制作一个生成指定大小的占位图并插入到 Sketch 画板中的功能。插件会提供一个面板,可以让使用者输入尺寸、分类等可选项,同时提供插入按钮,点击后会在画板插入一张图片图层。
使用 skpm 初始化项目
skpm 是 Sketch 官方提供的插件管理工具,类比于 Node.js 中的 npm。它集插件的创建、开发、构建、发布等多项功能于一体,我们在很多场景都需要使用它。安装的话比较简单,直接使用 npm 全局安装即可。
npm install -g skpm
按照官方教程,安装完毕之后我们就可以使用 skpm create 命令来初始化项目目录了。当然 skpm 是支持基于模板初始化的,官方仓库也列举了一些模板4,我们可以使用 --temlate 来指定模板进行初始化。不过处于教学的目的,我这里就还是使用官方默认的模板创建了。
➜ ~ skpm create sketch-placeimg ✔ Done! To get started, cd into the new directory:cd sketch-placeimg To start a development live-reload build:npm run start To build the plugin:npm run build To publish the plugin:skpm publish
skpm 内部会使用 webpack 进行打包编译,运行 npm run build 会生成 sketch-placeimg.sketchplugin 目录,该目录就是最终的插件目录。双击该目录,或者将该目录拖拽到 Sketch 界面上就成功安装插件了。和 webpack --watch 类似,运行 npm run watch 的话对监听文件变化实时编译,在开发中非常有帮助。
注: 不要使用 npm start 进行开发,它携带的 --run 命令会使得构建速度特别慢 5。虽然它带 Live Reload 功能会很方便,但在官方未修复该问题前还是不建议大家使用。
项目结构入门
创建好的模板目录结构如下,为了帮助大家理解,我们来简单的介绍下这些目录和文件。
. ├── README.md ├── assets │ └── icon.png ├── sketch-assets │ └── icon.sketch ├── sketch-placeimg.sketchplugin │ └── Contents │ ├── Resources │ │ └── icon.png │ └── Sketch │ ├── manifest.json │ ├── my-command.js │ └── my-command.js.map ├── node_modules ├── package.json └── src├── manifest.json└── my-command.js
package.json
和大多数 JS 项目一样,skpm 创建的项目中也会有 package.json 文件。该文件除了像之前一样记录了项目的依赖和快捷命令之外,还增加了 skpm 字段用来对 skpm 进行配置,默认的值如下。
{..."skpm": {"name": "sketch-placeimg","manifest": "src/manifest.json","main": "sketch-placeimg.sketchplugin","assets": ["assets/**/*"],"sketch-assets-file": "sketch-assets/icons.sketch"},... }
这里指定了该插件的名称为 sketch-placeimg,插件的 manifest 文件为 src/manifest.json。main 表示的是最终生成的插件目录名称。assets 则表示的插件依赖的图片等相关素材,在编译的时候会将命中该配置的文件拷贝到 <main>/Contents/Resources 目录下。
manifest.json
manifest.json 这个文件大家可以理解为是 Sketch 插件的 package.json 文件。我们来看看默认生成的 manifest.json。
{"$schema": "https://raw.githubusercontent.com/sketch-hq/SketchAPI/develop/docs/sketch-plugin-manifest-schema.json","icon": "icon.png","commands": [{"name": "my-command","identifier": "sketch-placeimg.my-command-identifier","script": "./my-command.js"}],"menu": {"title": "sketch-placeimg","items": ["sketch-placeimg.my-command-identifier"]} }
看到 $schema 就有 JSON Schema 那味了,它对应的 JSON 文件地址告诉我们可以在里面配置那些字段。其实最重要的其实就是上面列出来的 commands 和 menu 两个字段。
commands 标记了插件有哪些命令,这里只有一个命令,命令的名称(name)是 my-command,该命令的 ID(identifier)为 sketch-placeimg.my-command-identifier,对应的执行脚本为 ./my-command.js。
menu 则标记了该插件的导航菜单配置,比如示例这里它指定了该插件在插件菜单中的名称(title)为 sketch-placeimg,并拥有一个子菜单,对应的是 ID 为sketch-placeimg.my-command-identifier的命令。通过这个 ID,菜单的行为就和执行脚本关联起来了。
appcast.xml
manifest.json 默认的示例中有两个比较重要的字段没有配置,那就是 version 和 appcast。version 很明显就是用来表示当前插件的版本的。而 appcast 它的值是一个 XML 的 URL 地址,该 XML 里面包含了该插件所有的版本以及该版本对应的下载地址。Sketch 会将 version 对应的版本和 appcast 对应的 XML 进行对比,如果发现有新的版本了,会使用该版本对应的下载地址下载插件,执行在线更新插件。一个 appcast.xml 文件大概是这样的格式。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><item><enclosure url="https://github.com/lizheming/sketch-placeimg/releases/download/v0.1.1/sketch-placeimg.sketchplugin.zip" sparkle:version="0.1.1"/></item><item><enclosure url="https://github.com/lizheming/sketch-placeimg/releases/download/v0.1.0/sketch-placeimg.sketchplugin.zip" sparkle:version="0.1.0"/></item></channel> </rss>
如果是通过 skpm publish 命令去发布插件的话,会自动在根目录生成一个 .appcast.xml 文件。当然按照官方文档 《Update a plugin》6所说,你也可以手动生成。
resource
从上面的内容我们可以知道,skpm 会通过 package.json 中指定的 manifest 文件读取所有 commands 对应的 script 文件作为编译入口文件,将这些文档编译打包输出到 <main>/Contents/Sketch 目录。所有的 assets 配置对应的文件会拷贝到 <main>/Contents/Resources 目录中。最终完成插件的生成。
换句话来说只想要走 webpack 打包编译的话就必须是插件的命令才行。如果有一些依赖的非插件类资源,比如插件嵌入的 HTML 页面依赖的 JS 文件想要走编译的话,就需要使用 resource 这个配置了。resource 配置中配置的文件会走 webpack 的编译打包,并输出到 <main>/Contents/Resources 目录中。
插件开发
一些基本原理了解清楚之后我们就可以进行插件的开发了。首先我们需要用户点击插件菜单之后打开一个面板,该面板可以配置尺寸、分类等基础信息。
Sketch 插件中我们可以使用原生写法进行面板的开发,但是这样写起 UI 来说比较麻烦,而且对前端同学来说入门比较高。所以一般大家都会采用 WebView 加载网页的形式进行开发。原理基本上等同于移动端采用 WebView 加载网页一样,客户端调用 WebView 方法加载网页,通过实例的 webContents.executeJavaScript()方法进行插件到网页的通信,而网页中则使用被重定义的 window.postMessage 与插件进行通信。
sketch-module-web-view
想要在插件中加载网页,需要安装 Sketch 封装好的 sketch-module-web-view 插件。
npm install sketch-module-web-view --save-dev
// src/my-command.js import BrowserWindow from 'sketch-module-web-view'; export default function() {const browserWindow = new BrowserWindow({width: 510,height: 270,resizable: false,movable: false,alwaysOnTop: true,maximizable: false,minimizable: false});browserWindow.loadURL(require('../resources/webview.html')) }
当你做完这些你会发现点击插件菜单后什么都没有发生,这是因为还需要更改一下配置。大家可以看到我们最后是使用了 require() 引入了一个 HTML 文件,而官方默认的模板是没有提供 HTML 引入的支持的,所以我们需要为 HTML 文件增加对应的 webpack loader。
我们这里需要的是 html-loader 和 @skpm/extract-loader 两款 Loader。前者是用来解析处理 HTML 中存在的包括 <link /> 或者 <img /> 之类的 HTML 代码中可能存在的资源关联情况。而后者则是用来将 HTML 文件拷贝到 <main>/Contents/Resources 目录并返回对应的 file:/// 格式的文件路径 URL,用来在插件中进行关联。
npm install html-loader @skpm/extract-loader --save-dev
Sketch 插件官方为我们自定义 webpack 配置也预留好了入口,在项目根目录中创建 webpack.skpm.config.js 文件,它导出的方法接收的参数中第一个则是插件最终的 webpack 配置,我们直接在这基础上进行修改即可。
// webpack.skpm.config.js module.exports = function (config, entry) {config.module.rules.push({test: /\.html$/,use: [{ loader: "@skpm/extract-loader" },{loader: "html-loader",options: {attributes: {list: [{ tag: 'img', attribute: 'src', type: 'src' },{ tag: 'link', attribute: 'href', type: 'src' }]}}}]}); }
html-loader 插件在新版里对配置格式做了一些修改,所以之前很多老的教程中的配置都会报错。当然如果你有更多的插件需求也可以按照这个流程往配置对象中添加。之后我们再执行 npm run watch,点击菜单就可以看到我们预期的页面了。
注: 官方是提供了一套带有 sketch-module-web-view 模块的模板的,这里只是为了能更清楚的给大家解释清楚插件的原理和流程所以和他家一步一步的进行说明。真实的开发场景中建议大家直接使用以下命令进行快速初始化。
skpm create <plugin-name> --template=skpm/with-webview
React 的集成
面板这块我准备使用 React 进行开发,主要是有 React Desktoop 7 这个 React 组件,能够很好的在 Web 中模拟 Mac OSX 的 UI 风格(虽然也就几个表单没什么好模拟的就是了)。
令人开心的是 skpm 默认的 webpack 配置已经增加了 React 的支持,所以我们不需要额外的增加 webpack 的配置,只需要把 React 相关的依赖安装好就可以进行开发了。
npm install react react-dom react-desktop --save-dev
增加 webview.js 入口文件。由于该文件需要走 webpack 编译,但是又不是插件命令的执行文件,所以我们需要像上文说的,将入口文件加入到 package.json 的 skpm.resources 配置中。
// package.json {"skpm": {"resources": ["resources/webview.js"]} } // resources/webview.js import React from 'react'; import ReactDOM from 'react-dom'; function App() {return (<><p>Hello World!</p><hr />via: <em>@lizheming</em></>) } ReactDOM.render(<App />, document.getElementById('app'));
webview.html 也需要改造一下,引入 JS 入口文件。这里需要注意一下 ../resource_webview.js 这个引用文件地址,这是 JS 入口文件编译后最终的文件地址。主要是因为 HTML 文件最终会生成到 <name>.sketchplugin/Resources/_webpack_resources 目录下,而 JS 入口文件会将 / 分隔符替换成 _ 分隔符,生成在 <name>.sketchplugin/Resources 目录下。
<!DOCTYPE html> <html lang="zh-CN"><head><meta charset="utf-8" /><title>PlaceIMG</title></head><body><div id="app"></div><script src="../resources_webview.js"></script></body> </html>
注:
1.HTML 文件生成到
_webpack_resources
配置 82.JS 入口文件生成到
Resource
目录配置9
面板开发
流程打通了之后接下来我们可以专心进行面板的开发了。面板开发这块就不多描述了,无非就是前段页面的编写而已,最后插件面板大概是长这样子的。
-_-||嗯,其实我就是想和大家讲下流程硬上 React 的…
选择完毕点击插入后,调用 postMessage() 方法将最终的配置传递给插件。
//resources/webview.js import React, {useReducer} from 'react'; function App() {const [{width, height, category, filter}, dispatch] = useReducer((state, {type, ...payload}) => ({...state, ...payload}),{width: undefind, height: undefined, category: 'any', filter: 'none'});const onInsert = _ => postMessage('insert', width, height, category, filter);return (<button onClick={onInsert}>插入</button>); }
注: Web 原生的 postMessage() 方法的语法为 postMessage(message, targetOrigin, [transfer])。事件名称和事件参数都应该序列化之后通过 message 参数传入。
Sketch 插件中的 postMessage() 方法是注入方法,它对原生的方法进行了复写,所以参数格式上会与原生的不一样。注入方法的实现可参见 sketch-module-web-view 代码 10 。
在插件中,我们监听 insert 事件,获取到用户选择的配置之后给生成图片图层插入到画板中。
//src/my-command.js import sketch, { Image, Rectangle } from 'sketch/dom'; import BrowserWindow from 'sketch-module-web-view'; export default function() {const browserWindow = new BrowserWindow({...});browserWindow.webContents.on('insert', function(width, height, category, filter) {const url = 'https://placeimg.com/' + [width, height, category, filter].join('/');new Image({image: NSURL.URLWithString(url),parent: getSelectedArtboard(),frame: new Rectangle(0, 0, width, height),});return browserWindow.close();}); }
插件发布
最终我们的插件的主体功能就开发完毕了。下面我们就可以进行插件的发布了。我们可以直接使用 skpm publish 进行发布,它需要你通过 skpm publish --repo-url 或者是 package.json 中的 repository 字段为插件指定 Github 仓库地址。
在 Personal Access Token11 页面为 skpm 申请新的 Token,记得勾选上 repo 操作的权限。使用 skpm login <token> 进行登录之后,skpm 就获得了操作项目的权限。
最后通过 skpm publish <version> 就可以成功发布了。如前文所说,发布后会在项目目录创建 .appcast.xml 文件,同时会发布一条对应版本的 Release 记录,提供插件的 zip 包下载地址。执行完 publish 操作后,如果发现你的插件还没有在 插件中心仓库12 中列出来,还会询问你是否提交个 PR 把自己的插件增加上。
当然如果你的插件不方便发布到 Github 上,也可以使用前文所说的手工发布,执行 skpm build 后对生成的 <name>.sketchplugin 目录进行打包即可。
插件调试
上文的示例插件比较简单,所以没有使用特别多的调试手段。在官方教程《Debug a plugin》13 中描述了多种可以进行调试的方式。用的比较多的还是日志调试方式,可以使用系统的 Console.app 查看日志,也可以使用 skpm log -f 插件日志。
文档里说的大部分是插件的调试,WebView 内的前端代码调试会更简单一点。WebView 窗体右键审查元素即可使用 Safari 的开发者工具进行调试了。
注: 插件本身的代码本质是客户端代码,WebView 本质是前端代码,所以两者的调试和日志输出位置都是有区别的,这里要注意区分。
后记
以上就是开发 Sketch 的一些基础知识和简单流程,其它的就是多去看一下Sketch API14 文档了。不过在实际的使用中 Sketch 的这套 JavaScript API 并不是非常完美,部分功能可能还暂时需要使用原生 API 区别。这时候可以多 Google 一下,能找到很多前人的实现,节省自己的工作量。
本文主要是介绍了一套 JavaScript API + WebView 的偏前端的开发方式,代码我都已经放到 Github 上 https://github.com/lizheming/sketch-placeimg,大家可以自行查阅和下载。除了这种方式之外,我们也可以使用 OC + WebView 甚至是纯 OC 客户端的方式去开发插件。使用纯客户端开发的话性能会比 JavaScript API 的形式好一点,但是对于不了解 OC 开发的前端同学来说上手难度还是比较高的。
除了 Sketch 之外,Figma 也是一款非常棒的 UI 设计软件。它基于 Web 开发,天生跨平台,更提供了更加易用的协作模式,解决 UI 开发中的多人协作问题。感兴趣的同学也可以去了解一下。
文内链接:
https://github.com/ccgus/CocoaScript
https://developer.sketch.com/plugins/javascript-api
https://developer.sketch.com/plugins/create-a-plugin
https://github.com/skpm/skpm#create-a-new-plugin
https://github.com/skpm/skpm/issues/266
https://developer.sketch.com/plugins/update-a-plugin
http://reactdesktop.js.org
https://github.com/skpm/skpm/blob/master/packages/builder/src/utils/resourceLoader.js#L7-L21
https://github.com/skpm/skpm/blob/master/packages/builder/src/utils/webpackConfig.js#L163-L169
https://github.com/skpm/sketch-module-web-view/blob/master/lib/inject-client-messaging.js
https://github.com/settings/tokens
https://github.com/sketchplugins/plugin-directory
https://developer.sketch.com/plugins/debugging
https://developer.sketch.com/reference/api
参考资料:
《Sketch插件开发总结》:https://zhuanlan.zhihu.com/p/28325423
关于奇舞周刊
《奇舞周刊》是360公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。
如何制作 Sketch 插件相关推荐
- sketch制作Android动画,如何直接用Sketch制作动画|Sketch插件|
原标题:如何直接用Sketch制作动画|Sketch插件| 本期的sketch插件来为大家讲解如何制作动画,看来看看马克笔设计留学的MUzi老师的教程吧! 安装 1.下载并解压 Anima Tooki ...
- qt制作一个画板_如何直接用Sketch制作动画|Sketch插件|
本期的sketch插件来为大家讲解如何制作动画,看来看看马克笔设计留学的MUzi老师的教程吧! 安装 1.下载并解压 Anima Tookit.ziphttps://timeline.animaapp ...
- sketch插件 android,设计师必备的SKetch插件合集
SKetch Avataaars 可以灵活的更换头像的五官,操作非常方便. Dapollo 一款基于Sketch平台的设计插件集,其中包含了组件库.页面模板库.色彩库.图标库等设计素材帮你更高效的完成 ...
- sketch里的ios控件_「插件」五分钟了解微信团队打造的 Sketch 插件 :WeSketch
前言 WeSketch 是一个强大的 Sketch 插件合集,由微信设计团队量身打造,让设计师和开发者更佳高效的使用 Sketch. whose.design - 发现更多设计工具www.whose ...
- MacW小编分享设计师们常用Sketch插件合集,让你效率翻倍!
常用Sketch插件都有哪些?Sketch插件总是层出不穷,可以让大家在作出炫酷设计稿的同时,更让大家的工作效率翻倍.macw小编为大家总结了一大波Sketch插件合集,喜欢的赶快收藏起来吧!1.Sk ...
- 积木Sketch插件进阶开发指南
前段时间,美团外卖技术团队积木Sketch插件"意外走红".为了帮助更多的设计师小哥哥.小姐姐落地设计规范,提升产研效率,积木Sketch团队开始着手打造一个平台化的产品.本文介绍 ...
- 使用Envato Elements Sketch插件立即创建惊人的原型
近年来,原型工具的兴起是不可否认的. 设计人员正在利用这些功能强大但易于使用的程序来构建网站和移动应用程序的功能模型. 因此,它们已成为设计过程中至关重要的部分. Sketch是最广泛使用和最著名的原 ...
- 最佳助攻!25款轻巧实用的SKETCH插件大合集
最佳助攻!25款轻巧实用的SKETCH插件大合集 CocoaChina Sketch绝对是除了PS和AI之外在Mac 平台上最热门的设计工具,它更新迅速,功能完备,并且非常契合目前对于UI设计的需求, ...
- Sketch装机必备!10款Sketch 插件使用率超高!
本文给大家推荐和整理了 10款 使用率超高的 Sketch 插件.Sketch 是一款深受 UI 设计师欢迎的 UI 设计工具,由于其轻便的格式,简洁的 UI 界面操作,很快风靡 UI 设计行业.其 ...
最新文章
- 【翻译】SQL Server索引进阶:第三级,聚集索引
- 微信小程序万里目_4款万里挑一的微信小程序,每一个都是黑科技!
- 网页请求复制为curl,然后导入postman调用
- python pandas读取excel-Python用Pandas读写Excel
- PTA —— 基础编程题目集 —— 编程题 —— 7-3 逆序的三位数 (10 分)
- Linux + RIL.pdf
- 【详细解读】进程管理 -死锁问题 系统有三个进程:A B C 这3个进程都需要5个系统资源。如果系统至少有多少个资源,则不可能发生死锁
- LKM:Linux Kernel Map(图解Linux内核)
- 上线随想之2011-03-30
- Audio驱动开发之音频链路学习笔记
- Android下载网络图片并缓存
- 《深入解析Windows操作系统》- 读书笔记
- 巨蚁数字全息过山车利用科技创造收获
- 吐血整理的几十款小程序登陆界面【附完整代码】
- 2019年“深圳杯”数学建模挑战赛B题(1、2问)
- SPSS应用程序无法启动,因为应用程序的并行配置不正确。请参阅应用程序事件日志,或使用命令行sxstrace.exe工具。
- 升级到ckplayerX
- 计算今天是本学期第几周
- node基础---02DIRT程序
- 高项_第九章人力资源管理
热门文章
- Cannot resolve method ‘create‘ in ‘String‘
- 非线性控制1.0——S函数定义
- qcom vfe笔记(msm8996平台)
- 婚纱纪实类照片调色思路 教你PS洋气的油画效果
- 蓝桥杯练习题之 Fibonacci数列
- 【C语言】数据表现形式及基本数据类型
- 计算机网络技术中的单位换算,计算机存储/网络传输中单位换算1000还是1024
- 解密-大象跳转如何实现微信中点击链接直接跳到默认浏览器(不是在微信内置浏览器打开)
- Matlab实现Q-criterion涡结构可视化
- 人生的三把钥匙,太经典了!