使用Figma API提取插图和图标
2023 年 11 月 2 日

使用Figma API提取插图和图标

本文是我写的关于令牌提取的前四篇文章的延续:

  • 第一部分:深入兔子洞 (opens new window)
  • 第二部分:使用Figma API (opens new window)
  • [第三部分:从Figma到我们的代码库](https://medium.com/iadvize-engineering/figma-tok 设计师们在Figma上创建他们的图标,而我们过去依赖于IcoMoon将它们放入我们的代码中。管理图标字体很复杂。我们从不知道图标是否是最新的,或者请求的图标是否可用。关于为什么SVG比字体更适合显示图标,有很多文章可以找到,但这不是重点。

在体验到自动导出令牌的好处后,我们想要复制这个过程来处理图片。 图标与插图

首先,我们需要明确一下图标和插图的概念,以及它们之间的区别。这将影响我们所有的流程,并且需要尽快解决。

插图

我们将插图视为图片,它们有尺寸、形状和颜色,但只有尺寸可以通过代码进行调整。我们需要能够根据使用场景来缩放我们的插图。

图标

图标无处不在。它们出现在按钮、菜单、标题等各个地方,它们是我们工具的一个更为重要的组成部分。

请注意,图标和插图不是令牌,而是组件,因此我们在每个平台上使用它们时都需要进行特定的处理。

在本文中,我们将重点讨论如何将它们导出为React组件,但您可以随意在自己的框架中使用。在React的基础上,我们的示例还使用了TypeScript,以提供更好的开发体验。 但是如果我们需要在图标上使用多种颜色怎么办?如果这些颜色只是同一颜色的不同阶梯,我们可以通过 Figma 中的不透明度属性来处理。如果这还不够,那么我们认为这是一幅插图。没有一个固定的约定,如何让多色图标改变颜色?你会允许改变其中一种颜色吗?但是这样怎么确保可读性?或者你会为每个图标提供多个主题吗?但这就是一个约定,你需要完全定义它!即使这是可能的,我认为这是一个特殊情况,应该在一个独立的库中处理,因为你的所有图标可能都不适用于这种特殊的模式。 对于图标而言,众所周知,根据其大小的不同,有时需要具有微妙的变化。较大的图标可以显示更多的细节,可以比较小的图标更加装饰。而较小的图标需要显示相对较少的细节,以保持易于扫描和理解。

我们可以通过与设计师共同遵循基本约定的方式来实现这一点。例如,我们可以在每个节点前加上其在图标中应该显示的大小,或者将每个子节点放在一个以大小为名称的组中... 类似于这样:

或者

我们选择了另一种选项:图标仅在需要的每个大小下创建,并通过命名约定进行链接。例如,我们有一个“M / User”和一个“S / User”。

通过这种策略,在特定大小的图标组中更改特定图标以更好地满足我们的需求变得简单。整个 Figma 文件 取我们的SVG

对于这篇文章,我将使用两个Figma文件,一个用于图标,另一个用于插图。您可以在这里找到它们:

我们的图标和插图都是组件,更好的是它们使用变体组合在一起。这使得在Figma上使用和切换它们变得很容易。此外,文档中的其他内容都是为了帮助设计师组织文件。顺便说一句,这些示例与我们的生产文件非常相似。

我们已经讨论过如何从Figma文件中提取元素,所以我不会再重复整个过程,但以下代码是作为提醒:

现在我们需要从文件中获取我们的组件。

获取我们的图像节点 #

由于文档是一个树形结构,我们需要在递归函数中处理这个问题。我们遍历整个树形结构,找到所有的图像节点。 处理图像名称

我们在Figma文件中使用了变体,这很好,但它使组件的命名变得有些复杂。我们必须依靠我们的“属性”来制作一个单一且更好的名称:

对于插图,我们不保留属性的名称,只保留其值。

对于图标,我们有两个属性:一个用于尺寸,另一个用于名称。我们将保留两者。

请注意,这纯粹是惯例。属性名称已在Figma中设置以适应我们的提取规则(...或者反过来,不要紧),可以以许多不同的方式处理它们,但我们将坚持这个例子。

让我们在上面的示例上运行它,看看我们的日志现在是什么样子:

结果是:

从我们的组件获取SVG

我们首先需要通过Figma API调用获取SVG的URL,然后针对每个组件进行单独的调用: 现在我们有一种方法可以将每个图像作为SVG进行检索,并将其输出为字符串。

编辑SVG图标

我们之前说过,我们希望图标具有与文本相同的颜色(就像我们以前使用的fontIcons一样),但是当我们检索我们的SVG时,颜色被设置且无法修改。我们需要一个解决方案!

在CSS中有一个鲜为人知但非常有用的关键字,可以帮助我们解决这个问题:currentColor。我们将用这个关键字替换所有的颜色,一切都会按我们的意愿进行:

你可以对SVG进行更多操作,例如优化它们。有一些库可以帮助你完成这项工作!

为每个SVG计算一个唯一的名称

我们接近尾声,但还没有完成:我们不能将所有的图标都放在我们的库中,这将导致一个巨大的包大小。相反,我们将把我们的图像上传到服务器并在运行时获取它们。

将我们的SVG发送到服务器的主要问题是版本问题。 图像版本化。如果我们使用图像名称作为文件名,将会给用户的缓存带来很大麻烦。

我们还需要先前版本的库能够安全地与旧版本的SVG一起运行。为了解决这个问题,我们将使每个版本的SVG具有不同的文件名。这样,每个库版本都保持了与服务器上相应文件之间的唯一映射关系。

一个获得唯一名称的方法是对组件的SVG内容进行哈希处理,并将其作为文件的版本名称。为了简单起见,我们将使用另一种方法。

Figma文件存储在Amazon AWS上,并且可以通过以下URL格式访问:

https://s3-us-west-2.amazonaws.com/figma-alpha-api/img/63a2/2510/7ccadbaf20da0f0576a4c9ba679dfe69 (opens new window)

如果你只取最后一部分,你将得到一个唯一的版本名称。我不认为依赖这个是一个好主意。毕竟,我们正在处理图像版本化。 将上述的Markdown翻译成中文,并删除一级标题,同时删除其中的图片链接,尽量消除Markdown格式错误和一些无用的段落,重新修饰整篇文章,使文章读起来更自然:这部分直接从Figma中获取,实现可能会随时间变化。为简单起见,这是我们在示例中采取的解决方案:

将所有内容整合在一起

让我们将上述实用函数应用于我们的Figma API调用结果:

现在由您来将每个图像作为单独的文件上传到您的服务器上。我们不会深入探讨这部分,因为它取决于您的平台系统,并且对本文没有太大影响。

生成我们的类型

从我们的SVG列表中,我们可以创建类型。这些类型将帮助我们确保以后对图标或插图组件的调用只允许存在的...嗯,图标或插图。

这只是另一种模板,就像我们为之前的令牌编写的那些模板一样。

对于插图

执行后,您将获得:

对于图标

这个有点长:我们想要ico Illustration组件

我们将从插图开始,因为它是最简单的组件。

首先,让我们来看看API:

为了强制执行正确的可访问性实践,我们强制开发人员设置一个标题(用作图像的alt属性)。

我们增加了设置图像尺寸的可能性。

最后,我们限制了“name”属性与已知的插图名称。这种类型在导出时生成,如上所述!

然后,我们可以构建URI来检索图像:

最后,我们可以创建我们的Illustration组件:

就是这样,我们不需要任何其他东西来使其工作。

图标组件

图标稍微复杂一些。

让我们来看看API:

大小是查找图标的入口点。设计师可以选择不以特定尺寸提供图标,或者简单地忘记了。这是合理的(为什么要提供我们不打算使用的东西?)但我们毕竟希望有特定尺寸的图标。

一旦执行,您将获得:

最后,我们可以创建我们的图标组件:

这样,我们就完成了,不需要任何其他东西来使其工作。 我们之前构建的类型在这里起到帮助作用。通过它们,可以知道给定大小的可用名称,并进行检查。

对于图标来说,标题并不是必需的,因为它们主要用于装饰并与文本结合使用。

颜色是最后一个属性。我们希望图标能够适应其所在上下文中的文本颜色。但在某些情况下,我们也希望直接设置图标的颜色,而无需在另一个容器中包裹我们的组件。因此,这个属性是可选的。

URI的构建方式与插图的方式略有不同:

对于最终组件,我们需要构建一些其他内容:如果我们希望图标与当前文本颜色匹配或者根据props设置颜色,就不能使用img标签。我们需要将实际的SVG内联到我们的代码中。

首先,我们需要手动获取它:

在这里,我们做了两件事情:

  • 使用自制的缓存来存储我们已经获取的图标( 从我们的服务器检索SVG,并使用dompurify进行清理,以防有什么地方出错。SVG将直接设置在DOM中,因此我们需要确保它们不包含任何黑客攻击。

让我们在我们的Icon组件中将所有这些组合起来:

在初始化时,我们使用缓存中的值填充我们的图标状态。

我们使用一个钩子来获取我们实际的图标,使用我们上面编写的函数。请注意,cancelFetch布尔值用于处理我们的函数是异步的事实,并防止在未挂载的组件上重新渲染。

最后,使用可怕的dangerouslySetInnerHTML来呈现组件(现在你知道为什么我们想要清理我们的SVG)。

这里有一些值得注意的事情:

  • 我们使用一个span容器来包裹我们的SVG,并在宽度和高度上设置相同的尺寸,具体取决于所请求的大小。 哎哟,你说的是dangerouslySetInnerHTML😱?

好吧,名字已经被更改了,每个人都惊慌失措…我们怎么能考虑使用这个属性呢?飞快逃跑吧!

但是等等…这真的危险吗?正如文档所说 (opens new window),React给它取了这个名字是为了防止我们随意打开跨站脚本攻击 (opens new window)的大门。如果我们想要使用这个属性,我们必须首先解决这个问题。 安全方面。我们使用两个屏蔽措施来处理这个问题:

  • 我们在运行时使用记录来构建我们的URI,这意味着我们只从已知的名称中获取已知的文件,
  • 我们在对SVG进行任何操作之前都会对其进行清理,即使在某个地方受到了破坏,我们也不会将任何危险的内容放入我们的DOM中。

现在看起来不那么可怕了,是吧?

益处 #

哇,这又是一篇充满代码和奇怪单词的大文章,但就令牌而言,这些库非常有用,我们不能再回到过去了:拥有自动化的一切非常方便!

如果你还没有迈出这个重要的一步,不要再等了!真心告诉你,这是值得的!

作为这些库的使用者,我不再需要担心是否有所有必要的资源来集成新的屏幕到我们的应用程序中。我只需输入我需要的名称,如果出现问题,那么我就知道我没有跟上最新版本的图标或插图库,仅此而已。这真是个大的时间节省器。

我们在[t 关于设计系统,我们的目标是高效、便捷地将设计元素转化为可实现的代码,以提高开发人员的体验并确保设计与产品的一致性。为此,我们决定采用Figma作为我们的设计工具,并将其与我们的开发流程紧密结合。

Figma是一款强大的设计工具,它提供了许多有用的功能,如实时协作、设计共享和设计文件的版本控制。但是,将设计元素转化为代码仍然需要手动操作,这可能非常耗时且容易出错。

为了解决这个问题,我们引入了Figma的令牌功能。令牌是一种将设计元素转化为代码的自动化工具,它可以将设计文件中的颜色、字体、间距等属性自动转化为代码,并将其集成到我们的开发流程中。

使用Figma的令牌功能,我们的设计师可以专注于设计工作,而不必担心设计元素在转化为代码的过程中会出现什么问题。这样一来,他们可以更加高效地工作,并保证设计与产品的一致性。

与此同时,我们的开发团队也受益于令牌功能。他们不再需要手动将设计元素从Figma中导出,并将其复制粘贴到代码中。相反,他们可以直接从设计文件中提取令牌,并将其应用到他们的代码中。这样一来,开发人员可以节省大量的时间和精力,同时还能保证代码的准确性和一致性。

总的来说,Figma的令牌功能为我们的设计系统带来了许多好处。它提高了开发人员的体验,减少了从Figma到代码的迁移时间,同时保证了设计与产品的一致性。我们的开发团队和设计师都非常喜欢这个功能,因为它使我们的工作更加高效和愉快。