没有比在项目中添加图标更容易的了:您只需要写给设计者,他就会从Sketch中导出它并向您发送所需的选项,然后在代码中使用它。 如果您有十几个项目,多个平台和大量A / B设计测试,那么只需做同一件事,就可以多做40次,并且绝不会在任何地方犯错误……或者尝试使流程自动化。 削减-我的同事克里斯蒂亚诺·拉斯蒂利 ( Cristiano Rastelli)文章翻译的第一部分,介绍了这种自动化的一个例子。我们正在解决的问题
Badoo我们
正在开发一个约会应用程序。 实际上,这些是几个应用程序,每个应用程序都可以在多个平台(
iOS ,
Android ,
Mobile Web ,
Desktop Web )上运行,并且需要多个团队来工作。
在开发中,我们使用数百种不同的图标。 有些在每个应用程序中都相同,另一些对应于特定品牌。 有时设计会更改,图标也会随之更改:出现了一些新图标,其中一些已更新,一些已删除(但通常保留在代码库中)。
图标是由我们的设计团队创建和维护的,当图标准备就绪后,设计师通常会通过电子邮件,聊天或云发送图标。 这不仅花费时间,而且经常导致错误。 老实说,每次都会出错(我们都是所有人):有时图标在一个平台上更新,但未在另一个平台上更新,有时图标消失或与格式或大小不匹配。 因此,设计师和开发人员被迫保持经常接触。 开发人员直接从Sketch文件中导出图标,然后将它们添加到代码库中,但是没有检查可在数据库中重复使用的类似图标。 我确定您了解我在说什么。
我们在Badoo中拥有一个
名为Cosmos的
设计系统 ,最近我们引入了一个多平台(移动Web,Android和iOS)
令牌库 。 实际上,现在可以使用一组参数来描述设计更改(例如,按钮边框的外观,页面背景颜色,标题大小或动画持续时间在弹出窗口中),然后将其自动导出并在所有平台上的所有应用程序中使用。
我们的解决方案使我们能够在短时间内将设计思想(例如,改变颜色)转换为可正常运行的代码,这对我们的产品经理和设计师都同样印象深刻。 因此,他们的下一个问题(同时也是任务)是:“是否有可能对资源做类似的事情?” 我们回答:
“是的,您可以(可能) 。
”我必须承认,起初我们是盲目行动。 我们有几个想法,但是考虑到所有限制,我们不确定它们是否会起作用。 我们决定从MVP开始,但是一切进展顺利,该项目成为了具有所有必要功能的最终产品。
要求条件
MVP项目的要求很明确:该工具将在输入处接收一个Sketch文件,并以我们需要的所有格式输出所有图标,并支持A / B测试的图标变体。
困难在于,相同的图标根据品牌具有不同的参数(颜色,形状)。 以下是我们应用程序的一些图标。 如您所见,有些是绝对相同的,有些则在许多参数上有所不同,而有些则没有任何共同之处。

请注意,图标中使用的颜色不仅仅是颜色:它们与
商标中指示的
品牌颜色和特定功能完全对应。

因此,在开发工具时,我们的目标不仅是针对不同平台和品牌自动创建和交付图标,而且还要使根据品牌的动态着色成为可能。
草图和SketchTool
素描是我们设计师的主要工具。 而且,尽管我们考虑了其他选项(例如
Figma ),但我们知道在该项目的框架中,我们将使用Sketch格式的文件(因为我们的设计师最好拥有此工具,并且所有当前的图标和资源都以此格式保存) 。
实际上,在项目开始时,我们甚至不确定平台需要哪种文件格式。 我们设想这样的过程:以SVG格式从Sketch文件中导出图标,然后将SVG文件“馈送”到移动浏览器和Android的版本中,对于iOS,找到将SVG转换为PDF的库。 这是从一开始就制定的计划,尽管我们不知道我们的想法是否行得通以及可能会遇到什么问题。 实际上,为此,我们需要MVP-了解我们的项目是否正在实施,如果正在实施,那么它将非常耗时。
我不知道您是否必须使用PDF转换器,但是我的经验表明这是一场噩梦。 他们总是
几乎完成这项工作,但从未做到100%。 因此,在脊髓中,我感到我们正沿着一条湿滑的小路行走。
从Sketch导出资源非常完美-我从没有下载SVG,PDF和任何其他格式的问题。 因此,我决定找出是否可以与Sketch交互的另一种方式-直接通过Sketch(可能是通过编程)导出资源(我也对是否有可能创建自定义插件很感兴趣,尽管这对于没有这种经验的人来说意味着很多工作) 。
我知道草图文件的内部结构本质上是一个存档。 将.sketch重命名为.zip,您可以双击打开文件; 在结果文件夹中,您将看到JSON文件列表和PNG格式的预览文件。

因此,我开始研究JSON文件,以了解它们之间的关系。
我发现,尽管它们具有很大程度的嵌套(并且大小很大),但是对象内不同实体之间的关系并没有那么令人困惑。 您有页面,画板和图层。 每层包含可以具有通用样式的
路径 。 这些实体中的每一个都有一个唯一的ID,该ID可让您维护不同文件之间的连接。 并且所有页面都保存在JSON文件中,并包含在pages子文件夹中(页面ID作为文件名)。
在研究期间,我发现了一个重要发现:
图层,页面和样式的
名称只是可以在不中断Sketch文件内部结构的情况下随时更改的标签 。 仅附加到它们的唯一ID很重要,最终用户不会看到它(尽管您可以阅读它并在JSON文件中引用它)。 以下是唯一样式ID的示例:
{ "_class": "sharedStyle", "do_objectID": "49BA4E98-8D63-435C-81D9-E2F6CDB63136", "name": "name-of/the-style", "value": { "_class": "style", "endMarkerType": 0, "fills": [ { "_class": "fill", "isEnabled": true, "color": { "_class": "color", "alpha": 1, "blue": 0.7176470588235294, "green": 0.4627450980392159, "red": 0 }, "fillType": 0, "noiseIndex": 0, "noiseIntensity": 0, "patternFillType": 1, "patternTileScale": 1 } ], "miterLimit": 10, "startMarkerType": 0, "windingRule": 1 } }
因此,我考虑了在美术板和页面的命名中引入约定的可能性,以告知某种有关资源关系的元信息,并在组装过程中以编程方式使用它们。
素描工具
因此,当初步研究完成时,计划
“将图标导出到SVG,然后转换 ”变成了“
让我们为Sketch创建一个插件,该插件将直接以最终格式导出图标 。
” 但是,即使那样,工作计划还是很模糊的(不是正在实施的事实)。
通过研究现有插件的源代码,我试图了解它们是否可以与Sketch中的导出API进行交互,如果可以,如何进行交互。 那时,我遇到了一个以前从未听说过的工具-SketchTool。
SketchTool是官方的Sketch工具(由Bohemian Coding开发)。 根据文档,他
是Sketch附带的命令行实用程序,可让您对Sketch格式的文档执行某些操作,例如,检查或导出资源。 它还允许您从命令行控制某些Sketch功能-例如,运行插件。
等待,用于
导出资源的 命令行实用程序 ? 你需要什么! 另外,由于这是一个官方工具,因此版本兼容性,过时,支持等都应该没有问题。
我开始研究该实用程序并阅读了所有文档-Sketch网站上的
唯一页面 (Internet上很少有专用的资料,因此我现在听说它并不奇怪)。
SketchTool与Sketch捆绑在一起,可以在
Sketch.app/Contents/Resources/sketchtool/
找到
$/Applications/Sketch.app/Contents/Resources/sketchtool/bin/sketchtool
命令
$/Applications/Sketch.app/Contents/Resources/sketchtool/bin/sketchtool
,您将得到以下结果(我简化了数据):
Usage: sketchtool <command> [<args>] [--formats=<string>] [--use-id-for-name{=YES|NO}] [--export-page-as-fallback{=YES|NO}] [--serial{=YES|NO}] [--context=<string>] [--application=<path>] [--without-activating{=YES|NO}] [--item=<string>] [--items=<string>] [--safemode{=YES|NO} | --no-safemode | -S {<YES|NO>}] [--max-size=<float> | -m <float>] [--background=<string> | -g <string>] [--compression=<float> | -c <float>] [--new-instance{=YES|NO}] [--reveal{=YES|NO}] [--timeout=<float>] [--include-symbols{=YES|NO}] [--bounds=<rectangle>] [--outputJSON=<path>] [--filename=<string>] [--wait-for-exit{=YES|NO}] [--scales=<path>] [--overwriting{=YES|NO}] [--group-contents-only{=YES|NO}] [--trimmed{=YES|NO}] [--help] [--progressive{=YES|NO}] [--save-for-web{=YES|NO}] [--output=<path>] Commands: dump Dump out the structure of a document as JSON. export artboards Export one or more artboards export layers Export one or more layers export pages Export an area from one or more pages export preview Export a preview image for a document export slices Export one or more slices help Show this help message. list artboards List information on the document's artboards. list formats List the supported export formats. list layers List information on all of the document's layers. list pages List information on the document's pages. list slices List information on the document's slices. metadata List the metadata for a document. run Run a command from a plugin, inside Sketch. show Show the location of the various sketch folders. See 'sketchtool help <command>' for more information on a specific command.
如您所见,该工具具有四个主要功能:
read/dump
-读取/转储内部JSON文件的元数据转储,
list
创建文件实体列表,
export
-导出这些实体,
run
-运行插件提供的命令。
除此之外,每个命令还有几个可用选项。 在导出的情况下,SketchTool命令行上几乎也提供了在相应面板中可以找到的所有选项:

这意味着SketchTool允许您直接使用Sketch进行导出(例如,从SVG到PNG或PDF),而无需使用外部转换器。 太好了!
使用SketchTool和带有几个图标的常规Sketch文件进行的快速测试证实了我们的猜测:由于使用了这个简单的工具,我们无法使用外部程序进行导出,也无法编写自己的程序。 素描可以做任何事情!
草图文件
当我们决定使用Sketch存储和导出图标时,是时候将应用程序中使用的图标放入Sketch文件中了。
最初,我们计划只使用为MVP项目生成的有限图标集,但是很快意识到最好收集所有图标,以便立即消除重复,不一致和其他问题。
我们的设计师做得很好-几天后,他们在Sketch文件中使用的大部分资源都收集到一个文件中。 在这个阶段,他看起来像这样:

文件中的每个图标都有其自己的画板,并根据所需的图标名称进行命名(因此,相同名称的Sketch将给出源于资源导出的文件)。 将所有路径转换为路径,并将合并的路径缩小为一种形状。 因此,生成的资源保持了其完美的外观(如在源文件中一样),并且与各种平台兼容。

使用常见样式(和令牌设计)对图标进行动态着色
收集图标后的下一步是为图标应用必要的颜色。 我们在Sketch中创建了一组预定义的通用样式(
共享样式 ),它们的名称
与我们
设计系统的
标记的名称相对应,然后使用它们给图标着色。
这是如何将样式应用于特定图层的示例:

声明样式并将其应用于元素的方法如下:

命名约定起着
关键作用 。 设计人员可以在任何子文件夹中管理样式:样式名称由该颜色的相应标记的名称设置。 因此,随后,构建脚本可以以编程方式对其进行操作。
用于A / B测试的页面和画板的名称
现在是时候了解如何使设计人员能够进行图标的A / B测试了。 我们再次决定采用命名约定(我是KISS原则的忠实拥护者)。
在这种情况下,我们使用
页面名称来确定测试集(使用
XP_前缀),并使用
Arborboards的
名称来确定A / B测试所属的资源及其变体(在方括号中表示)。

用于测试的名称和变体不是我们发明的-它们必须与我们自己的拆分测试工具中分配给测试和变体的唯一ID相匹配。 因此,随后,资源可以正确地映射到特定的用户组。
多个品牌的多个文件
让我们感兴趣的最后一件事是如何为不同品牌维护相同图标的不同形式?

对于我们的产品经理而言,遵守此要求非常重要,并且我们有多种选择。 首先,我们要使用同一草图文件的不同页面,这些文件将根据品牌命名。 但是他们很快意识到这将使设计师的生活复杂化:让他们不断同步不同品牌的图标并不容易。 因此,我们决定使用多个文件:一个
通用文件 ,其中将存储所有不随品牌而变化的图标,以及
每个品牌的文件,这些文件将替换通用文件中的“基本”图标。

我们的草图文件已准备就绪! 是时候编写代码了。
阅读更多