美文网首页
sketch插件开发调研汇总

sketch插件开发调研汇总

作者: 硅谷干货 | 来源:发表于2022-12-14 17:03 被阅读0次

前言

好,先别着急敲击键盘。毕竟我们连使用哪种语言去开发都没决定,这曾经也是困恼我们许久的一个问题。目前Sketch Plugin开发大概有两种方式:

① 使用JavaScript + CocoaScript的混合开发模式,Sketch团队官方维护了一套JS API,并在开发者官网写了一句非常振奋人心的话:“ Take advantage of ES6, access macOS frameworks and use the Sketch APIs without learning Objective-C or Swift.”

理想很美满,但现实很骨感。这个API目前还不算完善,很多功能无法实现,因此我们需要搭配CocoaScript访问更丰富的内部API。

② 直接采用Objective-C 或Swift,并搭配macOS的UI框架AppKit进行开发,简单粗暴,并且可以利用OC运行时直接调用Sketch内部API。但这里要特别提醒一下,你要承担的风险是:随着Sketch的不断更新,内部API的命名和使用方式可能会发生较大变化,很多知名插件都因此放弃更新

本文采用了“混合开发模式”进行讲解,希望能够给你一些小启发。

image.png

1. Sketch Plugin开发流派

image.png

2. 环境配置

Skpm(Sketch Plugin Manager)是Sketch提供的用于Plugin创建、Build以及发布的官方工具。Skpm采用Webpack作为打包工具,当然如果你对前端知识足够熟悉,也可以采用Rollup或者roadhog。但是,为了防止遇到各种各样的报错,这里并不建议你这么做。

Skpm提供了一系列帮助快速入门的模板,最有用的莫过于skpm/with-webview,它可以帮助我们创建一个基于WebView展示的Demo示例,而且Skpm会在构建完成后,自动创建一个Symbolic Link将插件添加到Sketch的安装目录,使Plugin立即可用。

//基于webpack的Sketch官方打包工具skpm
npm install -g skpm
//创建示例工程
skpm create my-plugin --template=skpm/with-webview
//Install the dependencies
npm install
//构建插件
npm run build

3. 项目结构

Plugin Bundle

按照上面的步骤操作完成后,我们会得到如下插件目录,它以标准化的分层结构存储了源码文件以及构建生成的Sketch插件安装包。这里没有使用官方文档中最简单的Demo,而是使用目前开发中最为常用的With-Webview模板进行分析,以免出现学完“1+1”后遇到的全是“微积分”问题,并且大部分插件均是在此基础上进行拓展。

目录中的参数,相信你在看完注释后马上就能明白。可是如果此前没有前端开发经验,可能不了解在经过Webpack打包后,脚本文件的文件名会发生变更,比如resources中的webview.js经过打包后会储存在插件的Resources文件夹中,而文件名则变更为resources_webview.js,因此在进行代码编写时,如果需要在html中引用此文件,也要使用打包后的文件名,即:<script src="../resources_webview.js"></script>。这里有个小技巧,如果你不知道脚本文件打包后的文件名及路径,建议先使用Webpack进行编译,然后查看其在打包后的Plugin中的位置和名称,然后再进行引用。

├── assets //资源文件夹,如需更改需在package.json中的skpm.assets中设置 
├── my-plugin.sketchplugin   //skpm构建过程生成的插件包
│   └── Contents
│       ├── Resources
│       │   └── _webpack_resources
│       │   └── resources_webview.js
│       │   └── resources_webview.js.map
│       └── Sketch
│           ├── manifest.json
│           ├── __my-command.js
│           └── __my-command.js.map
├── package.json
├── webpack.skpm.config.js
├── resources //资源文件
│  ├── style.css
│  ├── webview.html
│  └── webview.js
└── src //需要被webpack打包的脚本文件以及manifest清单文件
    ├── manifest.json
    └── my-command.js

Manifest

你没有看错!plugin中也有manifest.json,它与其它平台比如Android开发中的清单文件意义相同。清单文件记录了作者信息、描述、图标以及获取更新的途径等等。想想看,每天熬夜加班写代码,总得有个地方把你的名字记录下来吧。但manifest最重要的作用其实是告诉Sketch如何运行插件,以及如何将插件集成进Sketch的菜单栏中。

commands使用一个数组,记录了插件所提供的所有命令。比如下面的例子,当用户从菜单栏点击 “显示工具栏”这个条目时,就会执行script.js中的function showPlugin() 。menu则提供了插件在Sketch菜单栏中的布局信息,Sketch会在插件被加载时初始化菜单。

{
  "commands": [
   {
      "name": "显示工具栏",
      "identifier": "roo-sketch-plugin.toolbar",
      "script": "./script.js",
      "handlers": {
        "run": "showPlugin"
      }
    }
  ],
  "menu": {
    "title": "🦘外卖积木SketchPlugin工具栏",
    "items": ["roo-sketch-plugin.toolbar"]
  }
}

package.json

简单来说,只要你的项目中用到了NPM,根目录下就会自动生成package.json文件。Node.js项目遵循模块化的架构,package.json定义了这个项目所需要的各种模块以及配置信息。使用npm install命令会根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。

非常值得称赞的是,Plugin开发中对于网络请求、 I/O 操作以及其它功能,可以使用与Node.js兼容的polyfill,其中许多常用modules已经预装到了Sketch中,比如consolefetchprocessquerystringstreamutil等。

这里你只需要知道以下几点:

  • 需要参与Webpack打包的脚本文件必须在resources目录下声明,否则不会参与编译(重点!考试要考!)。
  • assets目录需要配置在skpm.assets下。
  • 常用的命令可以定义在scripts中方便直接调用。
  • dependencies字段指定了项目运行所依赖的模块,devDependencies指定项目开发所需要的模块。
{
  "name": "roo-sketch-plugin",
  "author": "hanyang",
  "description": "外卖积木Sketch plugin,UI同学好喜欢~",
  "version": "0.1.0",
  "skpm": {
    "manifest": "src/manifest.json",
    "main": "roo-sketch-plugin.sketchplugin",
    "assets": ["assets/**/*"]
  },
  "resources": [
    "src/webview/template/webview.js"
  ],
  "scripts": {
    "build": "rm -rf roo-sketch-plugin.sketchplugin && NODE_ENV=development skpm-build",
  },
  "dependencies": {},
  "devDependencies": {}
}

4. API Reference

JavaScript API

由于使用了与Safari相同的JS引擎,Plugin脚本可以获得完整ES6支持。官方的JavaScript API由Sketch团队维护,并允许访问和修改Sketch文档,通过API可以向Sketch用户提供数据并提供一些基本的用户界面集成。

//访问、修改和创建文档从color到layer再到symbol等方方面面
var sketchDom = require('sketch/dom')
//对于异步操作,JavaScript API提供了fibers延长contex的lifeTime
var async = require('sketch/async')
//直接在Sketch中提供图像或文本数据,DataSupplier直接与Sketch用户界面集成。
var DataSupplier = require('sketch/data-supplier')
//无需重新build的情况下显示通知以及获取用户输入
var UI = require('sketch/ui')
//保存图层或文档的自定义数据,并存储插件的用户设置。
var Settings = require('sketch/settings')

CocoaScript Syntax

CocoaScript通过赋予了JavaScript调用Sketch内部API以及macOS Cocoa frameworks的能力,这意味着除了标准的JavaScript库外,还可以使用许多很棒的类与函数。CocoaScript建立在苹果的JavaScriptCore之上,而JavaScriptCore是为Safari提供支持的JavaScript引擎。

因此,当你使用CocoaScript编写代码的时候,你就是在写JavaScript。CocoaScript中的Mocha实现JS到Objective-C的Bridge,虽然Mocha包含在CocoaScript中,但文档仍保留在原始Github中。因此,你在CocoaScript的Readme中看不到任何语法教程。这里一个诀窍是,如果你想了解Mocha将原生的Sketch Objects通过bridge,从Objective-C传递到JavaScript层的属性、类或者实例方法的信息,可以将其通过console打印出来:

let mocha = context.document.class().mocha()
console.log(mocha.properties())
//OC
[executeOperation:withObject:error:]
//CocoaScript
executeOperation_withObject_error()

通过CocoaScript 提供的Bridge使用JavaScript调用Objective-C的基本语法如下:

  • Objective-C的方括号语法“[ ]”转换为JavaScript中的点“ . ”语法。
  • Objective-C的属性导出到JavaScript时Getter为object.name() 而Setter为object.name = 'Sketch'。
  • Objective-C的selectors被暴露为JavaScript 的代理方法。
  • “:” 冒号被转换为下划线“ _”, 最后一个下划线是可选的。
  • 调用带有一个下划线的方法需要加倍为两个下划线: sketch_method变为sketch__method。
  • selector的每个component被连接成不带有分隔符的单个字符串。

5. Actions

行为定义

Action指的是由于用户交互而在应用程序中发生的事件,比如“打开文档”、“关闭文档”、“保存”等。Sketch所提供的了Action API可以使插件对应用程序中的事件做出反应,有点类似Android开发中的的BroadCast或者Job Scheduler。官方文档列举了数百个可供监听的Action,但最常用到的只有下面几个:

image.png

监听回调

我们只需在插件的manifest.json文件中添加一个handler即可。比如下面的例子添加了对于“OpenDocument”的监听,也就是告诉插件在新文档被打开时要去执行onOpenDocument这个function。

 {
      "script": "action.js",
      "identifier": "my-action-listener-identifier",
      "handlers": {
        "actions": {
          "OpenDocument": "onOpenDocument"
        }
      }
}

当一个Action被触发时,会回调JS中的监听方法,与此同时Sketch可以向目标函数发送Action Context,其中包含动作本身的一些信息。在下面例子中,每次打开文档时都会弹出一个Toast。

function onOpenDocument(context) {
    context.actionContext.document.showMessage('Document Opened')
}

6. Bridge双向通信

在常规的插件开发中,UI层一般采用Webview实现,因此你可以使用各种前端开发框架,比如React或者Vue等;而插件的逻辑层(负责调用Skecth API)显然不在WebView中,因此需要通过Bridge进行通信。逻辑层将从服务器获取到的数据传递给UI层展示,而UI层则将用户的操作反馈传递给逻辑层,使其调用Sketch API更新Layers。

image.png

插件发送消息到WebView

//On the plugin:
browserWindow.webContents
  .executeJavaScript('someGlobalFunctionDefinedInTheWebview("hello")')
  .then(res => {
    // do something with the result
  })

//On the WebView:
window.someGlobalFunctionDefinedInTheWebview = function(arg) {
  console.log(arg)
}

WebView发送消息给插件

//On the webview:
window.postMessage('nativeLog', 'Called from the webview')
//On the plugin:
var sketch = require('sketch')
browserWindow.webContents.on('nativeLog', function(s) {
  sketch.UI.message(s)
})

经过了以上步骤,我们就得到了一个基础插件,它以WebView作为内容载体,并具有双向通信功能。打开插件时,Webview会将页面加载完成的事件传递给逻辑层,逻辑层调用Sketch API弹出Toast;点击Get a random number可以从逻辑层获取一个随机数。

image.png

Sketch插件开发汇总图

image.png

Sketch解析方案参考资料

  1. AirBnb 的react-sketchapp:提供了UI框架和项目脚手架(github),不提供解析源码相关功能
  2. 58同城的Picasso:提供了解析代码的思路(博客)
  3. sketch-node-parser:使用纯NodeJS从草图中解析文件,资料少,更新慢
  4. sketch-to-html:使用纯NodeJS从草图中解析文件,不能生成标注图
  5. sketch-meaxure:可以生成标注图和代码片段的信息,满足部分业务需求

官方参考链接:

sketch官方参考指南
sketchapp官方参考指南

翻阅过的sketch资料

1、Sketch 插件开发实践总结
2、浅谈sketch插件开发(三)
3、Airbnb - React Sketch App
4、58同城Picasso
5、掘金sketch插件开发指南
6、知乎Sketch插件开发指南
7、Sketch webView方式插件开发技术总结
8、从 sketch 中获取颜色、字体组件内容
9、积木Sketch Plugin:设计同学的贴心搭档
10、携程机票Sketch插件开发实践
11、sketch 导出html 的开源项目

相关文章

网友评论

      本文标题:sketch插件开发调研汇总

      本文链接:https://www.haomeiwen.com/subject/hlmftdtx.html