大家好,我是前端西瓜哥。
上周图形编辑器交流群里有人问如何解析Figma导出的fig文件格式并获取可读数据。
经过一群朋友的一番讨论,这个问题终于解决了。
图文件
导出Figma设计文件,我们将得到一个fig文件。
Fig 是一种二进制格式。
它没有使用XML或JSON格式,而是选择使用Figma自己的专用编码工具进行序列化编码、封装,最终获得二进制文件。
与纯文本格式(JSON 和 XML)相比,二进制的优点是:
尺寸更小,因为数据更紧凑;
解析速度快,比如JSON,需要逐个字符解析,然后构造AST,同时考虑到转义、空格等特殊情况。 对于大文件,解析效率很差;
高保真,比如有些类型的纯文本格式其实很难表达,需要额外一层转换(比如类型要保存为字符串,就必须转换为普通数组);
安全。 由于编码规则是由应用程序自己实现的,因此也方便加密(如异或加密)。 我们无法知道编码和解码的规则。 除非主动宣布,否则我们只能尝试扭转。
首先使用 Figma 绘制一些基本形状。
然后导出fig文件并得到一个名为fig-file.fig的文件。
先打开看一下。
它不是一个文本文件,它应该是一个二进制文件。
无论如何,强制它以文本格式打开。
以PK开头的应该是ZIP格式文件头的标识符。
对了,再检查一下这个文件的二进制内容,看到开头是50 4B 03 04,说明它确实是一个ZIP文件。
基本上,很多应用程序的导出文件都会选择ZIP格式,然后将后缀名更改为您定义的后缀名,例如fig和xmind。
使用 ZIP 格式有以下好处:
文件经过压缩,体积更小,并且是单个文件;
目录结构被保留;
跨平台,基本上所有主流操作系统都支持ZIP。 虽然用户一般不会手动解压,但用户安装的应用程序可以直接使用操作系统底层API进行解压,有助于减小应用程序包的大小;
解压它。
unzip fig-file.fig
解压内容
解压后的内容是:
.
├── canvas.fig
├── fig-file.fig # 这个是压缩源文件
├── images
│ └── 0b15125516ae308a2d819f2970e851c0402949d2
├── meta.json
└── thumbnail.png
需要注意的是,提取的内容没有根文件夹来存储内容。
但如果使用可视化界面解压,通常会解压出一个与压缩包同名的文件夹。
这实际上是操作系统的一个附加操作。 目的是防止解压后出现大量文件与当前文件夹中的其他文件混合。 同名文件也可能存在问题。
.fig是真正的Figma数据内容,记录了图形树中图形之间的关系以及图形的属性。
该文件夹存放图片。 里面的文件添加.png后缀即可查看图片。
meta.json是图纸的一些基本信息,比如导出的客户端使用的背景颜色、文件名等。
.png 是预览图像。 如果您已经安装了figma桌面,该图像将从fig中提取并通过文件预览器进行预览。
等等,不,.fig? 为什么又是fig文件? 这是在玩俄罗斯套娃吗?
经鉴定,也是一个二进制文件,只不过它的文件格式是。 。 。 无花果猕猴桃?
猕猴桃
这种名为 Kiwi 的特殊格式是由 Figma 前 CTO Evan 开源的。
Kiwi 是一种用于有效编码树数据结构的二进制格式。
它受到格式的启发,但更简单、编码更紧凑,并且对自定义字段有更好的支持。
Kiwi 库提供了可以解析二进制文件并将其转换为编程语言对象的工具。 目前支持 ()、C++、Rust 和 Skew。
但您需要提供一个用于类型映射。
幸运的是,这保存在Fig 文件中。
.fig 文件
事实上,这个.fig文件不是Kiwi,它是一个复合产品。
首先,开头的fig-kiwi字符串是注释,表明它是一个fig文件(毕竟,正如我们前面看到的,fig文件也可能是一个ZIP),并且使用kiwi进行编码。
文件中有Kiwi二进制数据部分,也有需要提取的部分。
是时候在这里切片了。
有一个开源项目Figma-To-JSON可以成功解析fig。 让我们看看它是如何做到的。
看了一下,好像是50 89切的,切了几刀,就得到了一些片。 我们需要前两片。
第一个切片是,第二个切片是 Kiwi 数据。
每个切片都是 ZIP 压缩的,需要先解压缩,然后再进行 Kiwi 解码。
import { ByteBuffer, compileSchema, decodeBinarySchema } from "kiwi-schema"
export const figToJson = (fileBuffer: Buffer | ArrayBuffer): object => {
// 提取 fig 文件的 schema 和 kiwi 格式数据
const [schemaByte, dataByte] = figToBinaryParts(fileBuffer)
const schemaBB = new ByteBuffer(schemaByte)
const schema = decodeBinarySchema(schemaBB)
const dataBB = new ByteBuffer(dataByte)
const schemaHelper = compileSchema(schema)
// 这个 json 对象就是最终结果了
const json = schemaHelper[`decodeMessage`](dataBB)
return convertBlobsToBase64(json)
}
流程总结如下:
Figma 到 JSON
以上都是在讲fig文件解码的过程。
如果你只是想获取fig的结构,对过程不感兴趣,可以直接使用一个名为Figma-To-JSON的开源项目来解析。
下面是转换结果,是一个一维数组,风格类似quill的delta。
每个节点都保存了父节点的ID,可以将其关联起来构建图树。
获取Fig数据格式有什么好处?
首先,如果你开发自己的图形编辑器,或者直接与Figma竞争,需要设计数据结构,那么fig数据格式有很好的参考价值。
然后就是二次开发,写一些工具来做一些离线批处理操作,比如从fig中提取一些文本数据转成excel等奇怪的操作。
这样你就不需要连接到互联网来打开 Figma 网站并使用插件来执行这些操作。
Figma 官方视图
Figma的fig格式是半公开的,通过网上搜索可以找到很多线索。 由于 Figma 相对开放,所以使用的 Kiwi 编码格式也公开了。
不过Figma不会主动提供在客户端转换fig的方式(但可以使用开发者API请求服务器数据),因为这与它所希望的生态稳定性背道而驰。
如果Figma主动提供fig的内部格式,那么它将对这种格式负责,而当Figma开发新功能时,fig文件的结构很可能在未来的发展中发生破坏性的改变。
当然,如果你想尝试以同样的方式解析它转换成的结构,那也可以,但是你要自己对数据结构负责。
结尾