本文结合工程化实践,系统介绍要实现一个生产级别的 Sketch 插件所需要的技术知识和解决方案,并以一个真实的业务场景为案例,从0到1来实现一个生产级别的插件开发。
从 Sketch 插件开发的机制,自动打包更新工程化、Sketch 中 Objective-C 的运行机制等方面,分享开发一个生产级插件所需的技术储备。
最终开发一个如下图所示的 MVP插件将文章中讲到的知识串联起来,学以致用,加深对 Sketch 插件开发的理解。
在开发前,为了使开发调试更顺畅,需要做一点配置工作。
一、开发环境配置
崩溃保护
在 Sketch 插件开发过程中,会经常遇到崩溃问题,需要设置下崩溃保护,提高插件开发效率。
代码语言:javascript复制defaults write com.bohemiancoding.sketch3 disableAutomaticSafeMode true
插件缓存
通过配置启用或禁用缓存机制:
代码语言:javascript复制defaults write com.bohemiancoding.sketch3 AlwaysReloadScript -bool YES
HTTPS
另外在插件开发的过程中,涉及到 HTTP 请求,都需要使用 HTTPS,这是系统强制要求,否则会引起 Sketch 崩溃。
二、Sketch 插件开发基本知识
目前 Sketch 插件开发大概有两种方式,原生和混合开发模式:
原生开发指直接采用 Objective - C 或 Swift,并搭配 macOS 的 UI 框架 AppKit 进行开发,但这里有一个风险,由于 sketch API 更新快,经常会出现功能失效或者是兼容问题,维护成本也非常大。
混合开发即指使用 JavaScript CocoaScript 的混合开发模式。虽然 Sketch 官方提供了 API,但是这个API目前还不算完善,很多功能无法实现,因此还需要搭配CocoaScript访问更丰富的内部API,来实现更复杂的功能。
对于前端工程师来说,这里更推荐使用混合模式的方式来开发插件,即 webview 配合 JavaScript CocoaScript 的方式,既能发挥我们自身的技术优势,插件升级管理也更灵活。
环境配置
Sketch 插件可以使用官方提供 Skpm 开发套件来搭建开发环境,它是基于 Webpack 作为打包工具的。
项目结构
按照上面步骤生成官方的示例插件后,会在我们指定的目录生成项目文件,并且自动安装插件到 Sketch,在插件菜单就会看到刚刚安装好的插件。
这里需要说明的是,官方的示例文件里,对于 webview 是直接编译集成在插件里面的,这样有一个好处是,可以提高 webview 的加载速度,但是对于 webview 更新却不是很方便,如果要更新 webview 的话,就得更新整个插件体验上不是很好。
Manifest
在 Sketch 插件中,Manifest 文件相当于插件的入口文件,这个文件记录了作者信息、描述、图标以及获取插件更新的途径等信息。
还可以定义插件提供的命令,比如显示插件的工具栏,执行某些图层的操作等。Sketch 会在插件被加载时初始化菜单。
下面这个例子就表示用户在菜单栏点击切换工具栏就会显示 TeaMaker 的工具栏。
在 Manifest 文件中,还指定了插件更新的地址文件即 appcast.xml,Sketch 在启动的时候,会读取这个文件,当 appcast.xml 文件中插件版本有更新的时候,Sketch 会提示用户插件有更新,直接在 Sketch 就可以更新插件,如下所示:
appcast.xml
appcast.xml 文件是用来推送插件更新的,采取 Sketch 的这个更新机制来迭代开发很方便,来具体看看这个文件的字段以及所代表的意义:
主要是 enclosure 和 sparkle:version 这两个字段,表示插件新版本的地址和版本号。当有插件版本更新时,我们只需要添加一个 item,并且输入新版本插件的地址和版本号就可以。这里有一个地方需要注意的是,插件的地址一定是要外网可以公开访问的,并且是 https 的,这样 Sketch 才能读取并更新,否则就更新不了。
Webview 开发
对于前端工程师来说,开发 Sketch 插件还有一个很方便的地方就是官方提供了 webview 的方式来和 Sketch 进行交互,即我们可以使用传统的 web 开发技术来和 Sketch 进行数据的交互(比如可以发送数据给 Sketch 或者是 Sketch 返回数据到 web 端),这样我们前端开发工程师可以很方便的使用熟悉的技术高效开发 Sketch 插件。
webview 开发需要用到官方的 sketch-module-web-view 这个包,使用它提供的方法来把 web 网页加载进来,就可以像正常的 web 开发一样来开发。
使用下面的方法,在 sketch 中创建一个 webview 面板:
代码语言:javascript复制import BrowserWindow from "sketch-module-web-view";
const options = {
identifier: WebviewIdentifier,
width: 1200,
height: 800,
center: true,
closable: true,
title: 'https://xxx',
url: 'https://xxx'
};
browserWindow = new BrowserWindow(options);
在 url 字段传入远程的网页地址就可以显示 web 页面,其它的参数去官方的文档详细查看。
开发好 webview 后,还要打通 webview 与 Sketch 插件的数据通讯功能。这个官方也提供了相关的方法,在文档有详细的说明。
这里就简单的来说下,比如在 webview 中,想执行定义好在 Sketch 中的方法,可以这样做:
代码语言:javascript复制window.postMessage('fill-picture') // 向 sketch 发送消息
插件开发部署自动化
当需要更新一个插件的时候,我们需要手动打包插件为 zip 文件,并且上传到外网服务器;还需要手动更新 appcast 文件,并发送外网,相当繁琐。
既然 skpm 是基于 node 环境来开发的,完全可以把这个过程自动化,当需要更新插件的时候只需要运行一个命令就可以。下面我们就来开始自动化构建的改造。
插件打包,上传自动化
插件打包和上传这块。我们需要把插件打包为 zip 文件,并且上传到外网服务器,这里以上传到腾讯云 cos 为例子来讲解。
先引入相关 zip 打包的库和腾讯云 COS 的 SDK:
代码语言:javascript复制// 自动打包插件文件
const zip = new JSZip();
const COS = require('cos-nodejs-sdk-v5');
首先是插件打包,这里可以借助于 JSZip 这个第三方的包来完成插件的打包,使用起来非常方便,并且压缩率还是不错的,代码也很简单。
先创建一个 JSZip 实例:
代码语言:javascript复制var zip =newJSZip();
使用 .file(fileName,fileContent) 添加一个txt文件或者是使用 .folder(folderName) 添加一个文件夹 :
代码语言:javascript复制zip.file("Hello.txt","Hello Worldn"); // 添加文件
var img = zip.folder("images"); // 添加文件夹
然后是生成一个 zip 文件:
代码语言:javascript复制zip.generateAsync({type:"blob"}).then(function(content){
saveAs(content,"example0.1.zip");
});
生成 zip 文件这里是一个异步操作,下面的文件上传也会基于这个操作来进行,具体到我们插件打包这里,文件名称需要注意下,最好带上插件的版本号。
生成 zip 文件后们接下来就是文件上传了,这里以腾讯云 COS 为例来演示自动化文件上传的构建。
关于腾讯 COS 的 SDK 使用可以去官方文档详细了解,这里就不再赘述。
使用腾讯云 COS 来定义一个上传方法:
代码语言:javascript复制function upload(file) {
const filePath = path.resolve(cwd, file);
const name = path.parse(filePath).name;
const ext = path.parse(filePath).ext;
const filename = `${name}${ext}`;
cos.putObject({
Bucket: ' XXXXXX',
Region: ' XXXXXX',
Key: filename,
StorageClass: 'STANDARD',
Body: fs.createReadStream(filePath),
onProgress: (progressData) => {},
}, (err, data) => {
if (err) {
console.log(err);
console.log(`[${filePath}] 上传失败`);
} else {
console.log(`https://${data.Location}`);
const zipUrl = `https://${data.Location}`;
}
});
};
上传完之后,它会返回文件在服务器上的下载地址。
定义好上传方法后,我们就可以在上面压缩 zip 文件后,调用这个定义好的上传方法来上传文件到腾讯云 COS :
代码语言:javascript复制zip.generateAsync({type:"blob"}).then(function(content){
saveAs(content,"example.zip");
}).then(function(){
upload(path.resolve(__dirname, `./XXX.zip`));
});
插件更新推送自动化
准备工作就绪后,接下来就是在 appcast 文件添加新的插件下载地址,以及修改版本号,完成插件更新推送。
对于修改 xml 文件来说,如果直接使用 JavaScript 来修改的话,还是比较繁琐,我们先来看下这个文件的结构:
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<item>
<enclosure url="https://...plugin.zip" sparkle:version="0.9.1"/>
</item>
</channel>
</rss>
如果使用 JavaScript 来修改,需要读取文件,并且使用正则表达式来匹配相关的标签来修改,非常繁琐。
进一步观察,这种结构化的文档和我们熟知的 json 数据格式是不是很像。可以使用 xml2js 这个库,专门用来把 xml 文档转换为 json 格式的文档,这样修改 xml 文件就变得非常简单。
思路如下,先把 xml 文档转换为 json 格式,对应到 Sketch 中的 appcast 文档中的其实就是修改 enclosure 和 sprkle:version 这两个字段,修改完之后,再把 json 转换为 xml 文档,就完成了 xml 文档的更新。
代码语言:javascript复制// 更新 appcast.xml
function updateXml (url) {
fs.readFile(appcast, function(err, data) {
xml2js.parseString(data, function (err, result) {
result.rss.channel[0].item.push({
enclosure: [
{
$: {
url:xxx
url,
'sparkle:version': xxx,
},
},
],
});
const builder = new xml2js.Builder();
const xml = builder.buildObject(result);
fs.writeFileSync(appcast, xml);
});
});
};
修改完之后,生成新的 xml 文档,然后再重上传腾讯云 COS 的步骤,把 xml 文档上传到腾讯云,就自动完成了插件打包,更新推送的工作。
把上面的几个步骤整合到 npm scripts 中,直接运行一个命令就可以更新推送插件。
插件调试
Sketch 插件开发过程,调试是一个必不可少的工作,JavaScriptCore 也有提供类似调试 JavaScript 代码打 log 的方式,我们可以在代码中放入:
代码语言:javascript复制console.log/console.error
进行输出日志查看。
也可以借助官方开发的 sketch-dev-tools 插件来查看输出的相关信息。
在 Sketch 插件开发过程中,调试工作是非常重要的一环,特别是涉及到对 Sketch 文件的相关操作以及要用 CocoaScript 来访问内部 Sketch API 和 macOS 框架底层 API 功能的时候,如果是在插件里打断点来调试,每次要查看相关的日志和结果,都需要运行插件,繁琐,开发效率低下。
这里推荐使用 sketch 提供运行脚本的功能配合 sketch-dev-tools 工具来进行相关的开发调试,可以实时查看代码运行的结果。
使用这个运行脚步的功能,只需要在里面直接写相关的功能,点击运行代码,就可以查看运行结果,非常方便高效。
Objective-C 使用方法
Sketch 官方封装了一套 JS API ,但提供的功能很有限,只能够对 Sketch 文档进行一些常规的操作:Sketch 中的 Document、Artboard、Group、Layer 等进行相关操作以及导入导出等,具体使用可以去文档地址查看,有详细的说明。
强烈建议使用上面提到的运行脚本的功能来进行调试,可以对 API 有一个大概的感知。
在实际开发的过程中,需要通过调用 Sketch 内部 API 以及 macOS Cocoa frameworks 的能力,来实现更丰富的功能。
CocoaScript 实现了 JavaScript 运行环境到 Objective-C 运行时的桥接功能,可通过桥接器编写 JavaScript 外部脚本访问内部 Sketch API 和 macOS 框架底层的 API 功能。
使用 JavaScript 调用 Objective-C 的基本语法如下:
- Objective-C的方括号语法“[ ]”转换为JavaScript中的点“ . ”语法。
- “:” 冒号被转换为下划线“ _”, 最后一个下划线是可选的。
- Objective - C 属性设置,Getter: object.name(),object.setName('Sketch'),可以使用 setXXX 方法调用。
下面来演示下 Objective-C 具体的使用方法。
比如,在开发 Tea Maker 的过程中,我需要在侧边栏中按钮下面添加一行文字,如下图所示:
我们先在文档中搜索 NSButton 这个类,有一个 title 的属性:
点开这个方法,里面有这样一个说明:
代码语言:javascript复制vartitle: String { get set }
根据我们上面说到的 JS 调用 Objective-C 的方法,我们在 Sketch 调用的时候,可以像下面这样来做:
代码语言:javascript复制const button = NSButton.alloc().init()
button.setTitle('文字信息')
这样就可以实现在按钮里添加文字。基本的知识准备好了,下面正式进入插件实战。
三、实战生产级插件开发
我们将会开发一个如下图所示的插件:
环境配置
先使用上面在环境配置章节讲到的,来配置下基本的开发环境:
代码语言:javascript复制skpm create sketch-fill --template=skpm/with-webview
基本环境配置好后,运行下面的命令来安装插件:
代码语言:javascript复制npm run postinstall
插件安装好后,在 Sketch 插件就可以找到刚安装好的插件:
下面来开发 webview,官方的静态文件是放在 recourse 目录下 html 文件中。
webview 创建
这里使用官方提供的 sketch-module-web-view 来创建 webview 容器,在插件 my-command.js 文件中使用下面的代码来实现 webview 容器:
代码语言:javascript复制import BrowserWindow from "sketch-module-web-view";
const options = {
identifier: WebviewIdentifier,
width: 1200,
height: 800,
center: true,
closable: true,
title: 'https://xxx',
url: 'https://xxx'
};
browserWindow = new BrowserWindow(options);
创建完容器之后,就可以创建具体的页面来开发插件功能。
使用传统的 html 来实现 webview 功能,直接在生成的 recourses 目录里修改 html 文件。
代码语言:javascript复制<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>sketch-fill</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
sketch-fill
<div>
<button id="button">填充图片</button>
</div>
<!-- 这里需要注意的是,编译后的脚本文件需要加上 recourses 前缀 -->
<script src="../resources_webview.js"></script>
</body>
</html>
然后可以写一些简单的 CSS 来美化下。
接着在 webview.js 写按钮的功能,就是点击的时候发送填充图片的方法给 sketch 来调用插件里定义好的 fill-picture 方法来填充图片:
代码语言:javascript复制// 取消页面右键点击事件
document.addEventListener('contextmenu', (e) => {
e.preventDefault()
})
// 发送消息给 sketch
document.getElementById('button').addEventListener('click', () => {
window.postMessage('fill-picture', 'Called from the webview')
})
首先来思考下,要在 Sketch 填充一张图片,一般的操作流程是:
- 新建一个形状图层
- 选择形状图层
- 把图片填充到形状图层中去
通过上门三个步骤我们才能把图片正确的插入到 Sketch 中去。
这里我们使用 HTTP 的方式通过图片的 URL 来下载图片实现图片填充功能。
功能开发
像这样关于数据操作的功能开发,很适合先使用 Sketch 自带的运行脚本的功能来开发核心的功能,核心功能跑通后,再来整合到插件中,来提高插件开发效率。
梳理下图片填充这个流程:
- 获取用户选择的图层
- 对图层进行判断,是否是形状图层
- 通过用户传的 URL 来下载图片,进行填充
先在 Sketch 中画一个矩形并且选中,然后在 Sketch 中打开运行脚本的功能窗口,从 Sketch JS API 找到获取当前选中的图层的方法,运行脚本,就可以获取当前所选图层:
输出当前图层的信息,可以看到图层的各个属性,比如我们要对图层的类型进行判断,可以使用图层中的 type 字段来实现:
图层获取和判断完成之后,接下来就是填充图片到图层中去,这里要用 HTTP 的方式来下载 URL 指定的图片来填充,在 Sketch 开发中,需要用到原生方法来对 URL 进行处理。
在 OC 的文档中找 URL 的处理方法:
在 OC 中使用 NSURLRequest 这个类方法来处理,先使用 NSURL.URLWithString 方法来获取URL,然后使用 NSURLRequest.requestWithURL 方法来创建请求。
请求创建之后,然后发送请求,并且获取请求相应的数据,需要用到 NSURLConnection 这个方法,它主要是做两件事:
- 负责发送请求,建立客户端和服务端的连接,发送请求给服务器
- 收集服务器返回的数据
步骤:
- 创建一个 NSURL 对象,设置请求路径
- 传入 NSURL 并创建一个 NSURLRequest 对象,设置请求头和请求体
- 使用 NSURLConnection 发送请求
需要用到 NSURLConnection 中的 sendSynchronousRequest:returningResponse:error: 方法来请求数据,和上面的 URL 获取方法,整合起来就可以获取图片的数据:
代码语言:javascript复制// 转换 URL
const request = NSURLRequest.requestWithURL(NSURL.URLWithString(url));
// 下载 URL 指向的图片
const data = NSURLConnection.sendSynchronousRequest_returningResponse_error(request, null, null);
获取图片资源之后,使用 NSImage 来加载图片数据资源以及使用 Sketch 内部的方法 MSImageData 来对图片数据进行初始化,这样才能最终得到图片的数据:
代码语言:javascript复制// response 是下载下来的图片
const image = NSImage.alloc().initWithData( data );
const imageData = MSImageData.alloc().initWithImage(image);
数据准备后,使用 Sketch 原生的方法来进行图片填充实现,较之 JS API 方便些。
代码语言:javascript复制// 先使用 sketchObject 方法,把 sketch JS API 提供的 fill 方法转换为原生方法
const fill = layer.sketchObject.style().fills().firstObject();
// 设置填充的类型是图片
fill.setFillType(4);
// 用图片来填充
fill.setImage( imageData );
// 图片使用填满的方式来填充矩形
fill.setPatternFillType(1);
对上面的方法进行一个简单的说明,这里使用原生 OC 的方法来填充图片,而获取图层的方法又是使用的 JS API 来获取的。所以需要把图层也就是 layer 进行一个转换,使用 Sketch 提供的转换方法 sketchObject 来进行转换,转换之后使用 OC 的原生方法来对图片数据进行相关操作。
Sketch 对形状的填充有颜色、渐变、图片。填充图片使用原生的方法是 fill.setFillType(4),然后使用 setImage 方法来填充图片。
这里还有一点需要注意点是,在填充图片的时候,图片的尺寸和用户选择的图片不可能刚好一样,所以还需要设置图片的填充方式,也就是图片自适应形状图层大小来进行缩放,使用 setPatternFillType(1) 。
具体这些方法有哪些参数,以及参数的作用,可以去 OC 官方的文档查看。
整合一下上面的代码,把它粘贴到运行脚本的窗口代码区域,运行一下就可以看到图片填充效果:
代码语言:javascript复制let sketch =require("sketch")
let UI = sketch.UI
let doc = sketch.getSelectedDocument()
let selectedLayersObject = doc.selectedLayers
let selectedLayersArray = selectedLayersObject.layers
const imageUrl = "https://i.picsum.photos/id/428/600/300.jpg?hmac=jWM5_19UIAUyKXm0fdUShV5JrVKKJeP5Pntx6QUbGas"
// 转换 URL
const request = NSURLRequest.requestWithURL(NSURL.URLWithString(imageUrl));
// 下载 URL 指向的图片
const data = NSURLConnection.sendSynchronousRequest_returningResponse_error(request, null, null);
// 图片数据初始化
const image = NSImage.alloc().initWithData( data );
const imageData = MSImageData.alloc().initWithImage(image);
selectedLayersArray.forEach(layer => {
if(layer.type ==="ShapePath") {
// 先使用 sketchObject 方法,把 sketch JS API 提供的 fill 方法转换为原生方法
const fill = layer.sketchObject.style().fills().firstObject();
// 设置填充的类型是图片
fill.setFillType(4);
// 用图片来填充
fill.setImage( imageData );
// 图片使用自适应的方式来进行缩放
fill.setPatternFillType(1);
}
})
上面我们使用 Sketch 本身提供的脚本运行功能就完成了插件核心功能开发,开发调试都非常方便高效。
从上面整个过程也可以看到,在开发的时候,可以先把功能点,拆分成一个一个小功能点,使用脚本运行功能来边调试边开发。最后,再把它们整合到一起完成整个插件功能的开发。
整合发布插件
核心功能开发完后,接下来就是整合到代码中,完成插件开发并发布。
首先在插件里要响应 webview 发来的事件:
代码语言:javascript复制import sketch,{ UI } from 'sketch';
browserWindow.webContents.on('fill-picture', function(s) {
// 响应 webview 的事件,开发具体的功能
// 接收 webview 传过来的参数
url = s.data
});
响应事件后,先要对用户的选择来做一个判断,判断用户有没有选择图层并且是形状图层,定义一个方法来判断,使用官方提供的 JS API 就可以实现:
代码语言:javascript复制function currentSelection() {
let doc = sketch.getSelectedDocument()
let selectedLayersObject = doc.selectedLayers
let selectedLayersArray = selectedLayersObject.layers
return selectedLayersArray;
}
使用上面的方法就可以判断用户是否选择图层了:
代码语言:javascript复制browserWindow.webContents.on('fill-picture', function(s) {
// 响应 webview 的事件,开发具体的功能
// 接收 webview 传过来的参数
url = s.data
let selectedLayersArray = currentSelection()
if ( selectedLayersArray.length== 0 )
{
UI.message('请选择一个形状图层来插入图片');
} else {
}
});
从 webview 获取 URL 之后,不能直接在 Sketch 中使用,需要把上面的获取 URL 的代码封装为一个函数:
代码语言:javascript复制function getUrl(url) {
// 转换 URL
var request = NSURLRequest.requestWithURL(NSURL.URLWithString(url));
// 下载 URL 指向的图片
var data = NSURLConnection.sendSynchronousRequest_returningResponse_error(request, null, null);
if (data){
return data;
} else {
UI.message('网络超时,再试试看');
return;
}
}
图片下载好了,接下来是填充图片到形状图层中去,也就是把上面用到的图片填充的代码封装为一个函数,定义一个填充图片的方法fillImage:
代码语言:javascript复制function fillUrlImage(layer,url) {
// 先判断图层是不是形状图层
if(layer.type == 'ShapePath') {
const fill = layer.sketchObject.style().fills().firstObject();
let imageURL;
// 下载图片
imageURL = url;
let response = getUrl(imageURL);
let image = NSImage.alloc().initWithData( response );
let imageData;
imageData = MSImageData.alloc().initWithImage(image);
fill.setFillType(4);
fill.setImage( imageData );
fill.setPatternFillType(1);
UI.message('图片填充成功')
} else {
UI.message('请选择一个形状图层来插入图片');
return;
}
}
图片下载和图片填充的方法定义好之后,就可以把上面实现的功能代码整合到 my-command.js 文件中去:
代码语言:javascript复制import BrowserWindow from 'sketch-module-web-view'
import { getWebview } from 'sketch-module-web-view/remote'
import UI from 'sketch/ui'
import sketch from 'sketch'
const webviewIdentifier = 'sketch-fill.webview'
const imageUrl = "https://i.picsum.photos/id/428/600/300.jpg?hmac=jWM5_19UIAUyKXm0fdUShV5JrVKKJeP5Pntx6QUbGas"
function currentSelection() {
let doc = sketch.getSelectedDocument()
let selectedLayersObject = doc.selectedLayers
let selectedLayersArray = selectedLayersObject.layers
return selectedLayersArray;
}
function getUrl(url) {
// 转换 URL
var request = NSURLRequest.requestWithURL(NSURL.URLWithString(url));
// 下载 URL 指向的图片
var data = NSURLConnection.sendSynchronousRequest_returningResponse_error(request, null, null);
if (data){
return data;
} else {
UI.message('网络超时,再试试看');
return;
}
}
function fillUrlImage(layer,url) {
// 先判断图层是不是形状图层
if(layer.type == 'ShapePath') {
const fill = layer.sketchObject.style().fills().firstObject();
let imageURL;
// 下载图片
imageURL = url;
let response = getUrl(imageURL);
let image = NSImage.alloc().initWithData( response );
let imageData;
imageData = MSImageData.alloc().initWithImage(image);
fill.setFillType(4);
fill.setImage( imageData );
fill.setPatternFillType(1);
UI.message('图片填充成功')
} else {
UI.message('请选择一个形状图层来插入图片');
return;
}
}
export default function () {
const options = {
identifier: webviewIdentifier,
width: 240,
height: 180,
show: false
}
const browserWindow = new BrowserWindow(options)
const webContents = browserWindow.webContents
// 页面加载完,打印消息
webContents.on('did-finish-load', () => {
UI.message('UI loaded!')
})
// add a handler for a call from web content's javascript
webContents.on('fill-picture', s => {
UI.message(s)
let selectedLayersArray = currentSelection()
if ( selectedLayersArray.length== 0 )
{
UI.message('请选择一个形状图层来插入图片');
} else {
selectedLayersArray.forEach(layer => {
fillUrlImage(layer,imageUrl)
})
}
})
browserWindow.loadURL(require('../resources/webview.html'))
}
// When the plugin is shutdown by Sketch (for example when the user disable the plugin)
// we need to close the webview if it's open
export function onShutdown() {
const existingWebview = getWebview(webviewIdentifier)
if (existingWebview) {
existingWebview.close()
}
}
整理完之后,运行 npm run build 命令来打包插件,然后安装,一个图片填充插件就开发好了。
如果还要添加其它的功能,就依照上面所说的方法,像搭积木一样,开发一个满足自己需求的插件。
总结
通过图片填充插件,来总结一下开发的流程:
- 首先使用官方提供的 Skpm 来初始化开发环境
- 使用官方提供 skpm-module-webview 来开发网页容器面板
- 使用你熟悉的技术来开发具体功能,比如, React 或者是 Vue。用 postMessage 的方式发送消息到插件端
- 在 sketch 端使用 JS API 或者是 OC 原生方法来实现相关的功能
在实际开发过程中,需要通过不断的查文档学习,不断的调试,这是一个必须要经历的过程,走完之后,你会发现,沉舟侧畔千帆过,病树前头万木春,更重要的是为业务赋能,提升团队工作效率。