优化 SVG 图片

SVG 是一种基于 XML 的矢量图形格式。它具有许多优势,最值得注意的是它很轻量级。由于 SVG 是文本格式,因此可以使用简单的文本编辑器查看和修改它,并且应用 GZIP 压缩可以产生出色的效果。

对于网站而言,提供尽可能轻量级的资源至关重要,尤其是在移动设备上,带宽可能非常有限。您需要优化 SVG 文件,以便您的应用程序尽快加载和显示。

本文将展示如何使用专用工具来优化 SVG 图片。您还将了解标记的工作原理,以便您可以竭尽全力生成尽可能轻量级的图片。

介绍 svgo

优化 SVG 与压缩 CSS 或其他基于文本的格式(如 JavaScript 或 HTML)非常相似。它主要是关于删除无用的空格和冗余字符。

我推荐用来缩小 SVG 图片大小的工具是 svgo。它是用 node.js 编写的。要安装它,只需执行以下操作

$ npm install -g svgo

在基本形式中,您将使用类似这样的命令行

$ svgo --input img/graph.svg --output img/optimised-graph.svg

请确保指定 --output 参数,如果您想保留原始图片。否则,svgo 将用优化版本替换它。

svgo 将对原始文件应用多个更改 - 删除无用的注释、标签和属性,减少路径定义中数字的精度,或对属性进行排序以获得更好的 GZIP 压缩。

对于简单的图片,这将毫无意外地生效。但是,在更复杂的情况下,图片操作会导致文件混乱。

svgo 插件

svgo 由于基于插件的架构而非常模块化。

在优化复杂图片时,我发现主要问题是由两个 svgo 插件引起的

  • convertPathData
  • mergePaths

禁用它们将确保您在大多数情况下获得正确的结果

$ svgo --disable=convertPathData --disable=mergePaths -i img/a.svg

convertPathData 将使用相对和简写表示法转换路径数据。不幸的是,某些环境不会完全识别此语法,您将看到类似于

Screenshot of Gnome Image Viewer displaying an original SVG image (left) and a version optimised via svgo on (right)

GNOME 图片查看器显示原始 SVG 图片(左)和通过 svgo 优化后的版本(右)的屏幕截图



请注意,优化后的图片将在所有浏览器中正确显示。因此,您可能仍然希望使用此插件。

另一个可能给您带来麻烦的插件 - mergePaths - 将合并具有相同样式的形状,以减少源代码中的 <path> 标签数量。但是,如果两个路径重叠,这可能会产生问题。

Merge paths issue

在右侧的图片中,请注意角色颈部和手周围的渲染差异,还要注意 Twitter 徽标。轮廓视图显示了构成角色头部的三条重叠路径。

我的建议是先尝试使用所有插件激活的 svgo,然后如果出现任何问题,禁用上面提到的两个插件。

如果结果仍然与原始图片大相径庭,那么您需要逐个禁用插件,以检测导致问题的插件。以下是一份 svgo 插件 列表。

进一步优化

svgo 是一款很棒的工具,但在某些特定情况下,您可能希望进一步压缩 SVG 图片。为此,您需要深入了解文件格式并进行一些手动优化。

在这些情况下,我最喜欢的工具是 Inkscape:它是免费的、开源的,并且在大多数平台上都可用。

如果您想使用 svgo 的 mergePaths 插件,则必须自己合并重叠的路径。以下是操作方法

在 Inkscape 中打开您的图片,并找到具有相同样式(填充和描边)的路径。选择所有路径(按住 Shift 键进行多选)。单击“路径”菜单,然后选择“联合”。完成了 - 所有三个路径都合并成一个路径了。

Merge paths technique

创建角色头部的三条不同路径已合并,如右侧的轮廓视图所示。



对所有具有相同样式且重叠的路径重复此操作,然后您就可以再次使用 svgo,保留 mergePaths 插件。

您可以手动应用各种优化

  • 将描边转换为路径,以便它们可以与具有相似样式的路径合并。
  • 手动剪切路径,避免使用 clip-path
  • 将底部路径排除在重叠路径之外,并与相似路径合并,以避免图层问题。(在上面的图片中,请查看角色的头发 - 侧面的头发路径位于头部下方,但上面的头发位于头部上方 - 因此无法合并所有三条头发路径。)

最后考虑

这些手动优化可能需要大量时间才能获得微不足道的结果,因此在开始之前请三思!

优化 SVG 图片时的经验法则是确保最终文件每个样式(相同的填充和描边样式)只有一个路径,并且不使用 <g> 标签对路径进行分组。

在 Firefox OS 中,我们使用一个图标字体 gaia-icons,它是从 SVG 字形生成的。我发现优化它们会导致字体文件明显更轻,并且没有视觉差异。

无论您是使用 SVG 将图片嵌入应用程序,还是创建字体文件,请始终记住优化。这将让您的用户更满意!

关于 Guillaume Cedric Marty

Guillaume 在网络行业工作了十多年。他对网络技术充满热情,定期为开源项目做出贡献,并在他的 技术博客 上撰写文章。他还对电子游戏、动画以及日语(作为日语使用者)的外语着迷。

更多 Guillaume Cedric Marty 的文章……


5 条评论

  1. Lev Solntsev

    您好!我是 svgo 的维护者,将修复所有已知错误,使其尽可能可靠。v0.5.0 中修复了许多错误,并且希望所有已知错误(包括最烦人的 mergePaths(它目前不检查路径交叉点))将在即将发布的下一个版本中得到修复。

    但是,有一些已知问题将在一段时间内存在:svgo 根本不处理“style”标签(需要大量开发)并且尚未支持 SVG 2,因为它正在开发中,任何内容都可能发生变化。

    如果您遇到任何错误,请提交问题 https://github.com/svg/svgo/issues/new。我特别对本文中提供的图片感兴趣。它在 v0.5.0 中重现了吗?

    2015 年 3 月 13 日 下午 2:36

  2. Jesus Perales

    这很好,但没有 gulp 或 grunt 插件吗?

    2015 年 3 月 13 日 上午 7:42

    1. Lev Solntsev

      请查看 grunt-svgmin 和 gulp-svgmin。

      2015 年 3 月 16 日 上午 9:37

  3. MIDAS

    svgo 也有一个基于 Web 的前端:https://jakearchibald.github.io/svgomg/

    2015 年 3 月 17 日 上午 3:07

    1. wiz

      我使用我的实验网站 http://www.pictomago.com 生成的图片对其进行了测试,该网站使用过滤器和字体生成复杂的 SVG,并且效果很好。优化后某些图片无法正确显示。

      无论如何感谢您提供此工具!

      2015 年 3 月 21 日 下午 2:39

本文的评论已关闭。