如果您熟悉 Sketch,您可能已经在 Mac 应用程序和浏览器中都看过您的文档。虽然触点不同,但您看到的是相同的内容。但是您有没有想过我们是如何实现这一点的?
当您在浏览器中查看 Sketch 文档时,实际上您正在查看我们预先准备好的文档预览。它不仅仅是任何预览——它是整个页面的完全可缩放、可滚动的预览,上面可能有数百个画板。使用此预览,我们可以让团队中的任何人都访问文档,即使他们没有 Mac,仍然可以为他们提供出色的体验。
我想分享更多关于我们如何做到这一点以及如何保持跨平台渲染准确性的见解。我还将向您介绍我们最近解锁的一些性能改进。
关于衡量性能的说明
在我们开始之前,先简单介绍一下在 Sketch 和整个行业中衡量性能的方法。将性能归结为一个数字也很难。这在纸面上听起来可能不错,但在实践中通常意义不大。例如,由于 Sketch 文档差异很大,我们所做的一些更改对某些文档影响很大,但对另一些文档几乎没有影响。最终,我们选择通过关注我们的基本架构而不是特定的指标或追逐个别边缘情况来全面提高性能。
其次,此类大型技术项目的主要困难在于,您必须在保持汽车行驶状态的同时更换发动机。这给团队和产品都带来了一系列的挑战。
介绍:场景图
在过去的两年里,我们一直在 Mac 应用程序中制定一项长期计划,以摆脱我们直接到像素的渲染管道。相反,我们选择在 Sketch 图层和您在屏幕上看到的像素之间创建一个中间表示,我们认为这可以为我们解锁一些良好的性能优化。
该图不是根据带有样式、组和画板的图层进行思考,而是根据更基本的术语(例如您需要填充或描边的路径)进行思考——这是一个分析冗余绘图操作并加速的好级别。毕竟,更快渲染的关键是在各个通道之间尽可能少地绘制。
2022 年,我们开始构建我们的场景图——一种由节点组成的数据结构,有助于组织和表示图形场景。在我们的例子中,我们谈论的是以更基本的方式表示 Sketch 中的典型对象,例如图层、样式和画板。
这是一个它看起来的样子

在这里,您可以看到右侧的形状如何在场景图中转换。
一次一步
我们首先仅在渲染单个图层时使用我们的场景图,实际上在每次渲染过程中创建了数百个微小的场景图。然后,我们继续处理图层组和整个页面,最后跨所有线程共享单个场景图。随着每个版本的发布,我们稳步增加了场景图的范围。
随着 Sketch 95 的发布,我们已经跨越了另一个重要的里程碑。现在,我们不是每次都从头开始重建场景图,而是就地更新它。例如,当用户移动图层时,现在我们只需要更新树中的一个或两个属性,而不是完全重新创建它。
这似乎是一件显而易见的事情,我们也同意。但正如我们之前所说,必须在进行更改的同时保持引擎运行意味着我们需要小心谨慎地逐步改进——我们很高兴在 Sketch 95 中迈出了最后一步。
Sketch 94 和 95 之间的比较。
Mac 应用程序的改进
构建场景图对我们来说是一项成功,我们在我们自己的许多文档中都看到了更快的性能。由于这项技术上的飞跃,我们还能够进行以下功能改进,其中包括
- 放大时更好的阴影渲染
- 改进了符号内部和蒙版中的背景模糊
- 能够将任何图层变成 Alpha 蒙版并对其应用模糊
- 支持负阴影扩展(投射形状可以小于或大于阴影)

在这里,您可以看到负阴影扩展的作用。
但这不是衡量成功的唯一标准。由于在 Mac 上推出了场景图技术,我们还大大提高了 Sketch 在浏览器中的保真度和功能。
将其带到 Web 上
如果您使用 Sketch 一段时间了,您可能已经注意到我们从刚性的画板网格切换到我们 Web 应用程序中的无限画布视图。这反映了我们在 Mac 上都熟悉的体验,并且确实有助于简化设计师和利益相关者之间的对话,因为我们都在看同一件事。
我们如何在 Web 上构建这个新的完整 Canvas 体验?您可能已经猜到了答案:新的 Canvas 体验当然是由我们为 Mac 应用程序构建的相同场景图提供支持。我们新的场景图的伟大之处在于它与缩放无关,我们可以直接在前端中实时渲染它,而无需使用任何预渲染的资源。这意味着我们理论上可以在浏览器中提供流畅的平移和缩放体验。
但这并不意味着它是一个容易构建的功能。场景图已经处理了复杂的逻辑,例如解析符号、覆盖、布尔运算、轮廓文本等等。但仍然存在解释这些命令并快速、准确地将像素显示在屏幕上,并以各种浏览器支持的方式进行呈现的并非微不足道的部分。
克服挑战
让我们从头开始:场景图由我们的渲染农场生成,并存储在服务器上以供后续使用。当用户尝试在浏览器中查看文档时,我们会将生成的场景图传递给前端,前端会解析它并将其渲染成像素。 感谢 WebAssembly 和 Emscripten,我们不需要在 Javascript 中执行此操作,而是可以使用 C++ 和 Skia 渲染库(以及一些 WebGL)以全保真度和高速渲染路径、填充和滤镜。而且,因为我们不只是显示图像,所以我们可以在任何缩放级别上部分或完全渲染,让您可以随心所欲地平移和缩放。
不过,让 Web 上的 Canvas 平稳地平移和缩放是一项相当大的挑战,尤其是在复杂的 Sketch 文档上。 Web 浏览器的局限性以及它需要在其上工作的各种设备确实使这成为一个具有挑战性的问题。 例如,至关重要的是,所有浏览器最近才启用了有效的多线程处理,因此即使只有主线程可用,渲染器也必须正确工作。
如果您只有一个线程可用,如何在不阻止用户交互的情况下快速流畅地渲染? 我们不会在此处详细介绍,但我们提出了一些自己的策略,例如仅在用户未交互时才仔细调度和执行耗时的任务,并且我们构建了自己的系统来正确缓存 Canvas 内容并加速平移和缩放等操作。
最初旨在提高 Mac 上的渲染速度的项目在另一个领域解锁了强大的功能,即使这些改进最初对最终用户来说似乎是不可见的。 看到这些长期投入发挥作用真是令人非常满意,尤其是在我们设法提高 Web 和 Mac 体验之间的一致性时。
反过来,这为 Sketch 解锁了其他几个期待已久的功能,但我们将把这些内容留到另一篇文章中介绍。 在此之前,请继续关注 😉