SVG 压缩优化

565 阅读2分钟

前端经常会遇见 SVG 图标、图片,如下图所示

<svg class="lds-gears" width="54px" height="54px" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"
    style="background: none;">
    <g transform="translate(50 50)">
        <g transform="translate(-19 -19) scale(0.6)">
            <g transform="rotate(107.866)">
                <animateTransform attributeName="transform" type="rotate" values="0;360" keyTimes="0;1" dur="1s"
                    begin="0s" repeatCount="indefinite"></animateTransform>
                <path
                    d="M37.3496987939662 -7 L47.3496987939662 -7 L47.3496987939662 7 L37.3496987939662 7 A38 38 0 0 1 31.359972760794346 21.46047782418268 L31.359972760794346 21.46047782418268 L38.431040572659825 28.531545636048154 L28.531545636048154 38.431040572659825 L21.46047782418268 31.359972760794346 A38 38 0 0 1 7.0000000000000036 37.3496987939662 L7.0000000000000036 37.3496987939662 L7.000000000000004 47.3496987939662 L-6.999999999999999 47.3496987939662 L-7 37.3496987939662 A38 38 0 0 1 -21.46047782418268 31.35997276079435 L-21.46047782418268 31.35997276079435 L-28.531545636048154 38.431040572659825 L-38.43104057265982 28.531545636048158 L-31.359972760794346 21.460477824182682 A38 38 0 0 1 -37.3496987939662 7.000000000000007 L-37.3496987939662 7.000000000000007 L-47.3496987939662 7.000000000000008 L-47.3496987939662 -6.9999999999999964 L-37.3496987939662 -6.999999999999997 A38 38 0 0 1 -31.35997276079435 -21.460477824182675 L-31.35997276079435 -21.460477824182675 L-38.431040572659825 -28.531545636048147 L-28.53154563604818 -38.4310405726598 L-21.4604778241827 -31.35997276079433 A38 38 0 0 1 -6.999999999999992 -37.3496987939662 L-6.999999999999992 -37.3496987939662 L-6.999999999999994 -47.3496987939662 L6.999999999999977 -47.3496987939662 L6.999999999999979 -37.3496987939662 A38 38 0 0 1 21.460477824182686 -31.359972760794342 L21.460477824182686 -31.359972760794342 L28.531545636048158 -38.43104057265982 L38.4310405726598 -28.53154563604818 L31.35997276079433 -21.4604778241827 A38 38 0 0 1 37.3496987939662 -6.999999999999995 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23"
                    fill="#0097e0"></path>
            </g>
        </g>
        <g transform="translate(19 19) scale(0.6)">
            <g transform="rotate(229.634)">
                <animateTransform attributeName="transform" type="rotate" values="360;0" keyTimes="0;1" dur="1s"
                    begin="-0.0625s" repeatCount="indefinite"></animateTransform>
                <path
                    d="M37.3496987939662 -7 L47.3496987939662 -7 L47.3496987939662 7 L37.3496987939662 7 A38 38 0 0 1 31.359972760794346 21.46047782418268 L31.359972760794346 21.46047782418268 L38.431040572659825 28.531545636048154 L28.531545636048154 38.431040572659825 L21.46047782418268 31.359972760794346 A38 38 0 0 1 7.0000000000000036 37.3496987939662 L7.0000000000000036 37.3496987939662 L7.000000000000004 47.3496987939662 L-6.999999999999999 47.3496987939662 L-7 37.3496987939662 A38 38 0 0 1 -21.46047782418268 31.35997276079435 L-21.46047782418268 31.35997276079435 L-28.531545636048154 38.431040572659825 L-38.43104057265982 28.531545636048158 L-31.359972760794346 21.460477824182682 A38 38 0 0 1 -37.3496987939662 7.000000000000007 L-37.3496987939662 7.000000000000007 L-47.3496987939662 7.000000000000008 L-47.3496987939662 -6.9999999999999964 L-37.3496987939662 -6.999999999999997 A38 38 0 0 1 -31.35997276079435 -21.460477824182675 L-31.35997276079435 -21.460477824182675 L-38.431040572659825 -28.531545636048147 L-28.53154563604818 -38.4310405726598 L-21.4604778241827 -31.35997276079433 A38 38 0 0 1 -6.999999999999992 -37.3496987939662 L-6.999999999999992 -37.3496987939662 L-6.999999999999994 -47.3496987939662 L6.999999999999977 -47.3496987939662 L6.999999999999979 -37.3496987939662 A38 38 0 0 1 21.460477824182686 -31.359972760794342 L21.460477824182686 -31.359972760794342 L28.531545636048158 -38.43104057265982 L38.4310405726598 -28.53154563604818 L31.35997276079433 -21.4604778241827 A38 38 0 0 1 37.3496987939662 -6.999999999999995 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23"
                    fill="#7f8b95"></path>
            </g>
        </g>
    </g>
</svg>

可以看到里面大量啰嗦的代码,7.0000000000000036、6.999999999999999 等,是用第三方工具生成的线条或点,比如 Sketchup,如果用在网页上,就浪费了大量的字符,为了让网页更小更快,需要优化一下

使用 SVGO 进行优化

官网地址:github.com/svg/svgo

安装:npm -g install svgo

使用:

svgo one.svg two.svg -o one.min.svg two.min.svg
svgo *.svg
svgo src/*

Web SVGO

有开发者基于 SVGO,开发了网页版,不需要安装本地工具,直接上传就可以优化了,可以选择多种优化参数, jakearchibald.github.io/svgomg

可视化界面比命令行容易理解一点(虽然作者没有开发批量操作),可以看出 SVG 压缩/优化的几个方向:

  • Remove doctype,删除文档类型定义
  • Remove XML instructions,删除 XML 说明
  • Remove comments,删除注释
  • Remove ,删除元数据
  • Remove xmlns
  • Remove editor data
  • Cleanup attribute whitespace
  • Merge styles
  • Inline styles
  • Minify styles
  • Style to attributes
  • Clean IDs
  • Remove raster images
  • Remove unused defs
  • Round/rewrite numbers,对数字进行四舍五入取整
  • Round/rewrite number lists
  • Minify colours
  • Remove unknowns & defaults
  • Remove unneeded group attrs
  • Remove useless stroke & fill
  • Remove viewBox
  • Remove/tidy enable-background
  • Remove hidden elements
  • Remove empty text
  • Shapes to (smaller) paths
  • Move attrs to parent group
  • Move group attrs to elements
  • Collapse useless groups
  • Round/rewrite paths
  • Convert non-eccentric to
  • Round/rewrite transforms
  • Remove empty attrs
  • Remove empty containers
  • Merge paths,合并路径
  • Remove unused namespaces
  • Replace duplicate elements with links
  • Sort attrs
  • Sort children of
  • Remove ,删除无用的 title,这个是 xml 作为 xhtml 的扩展留下来的,用于网页直接打开时显示在浏览器标签页名称
  • Remove
  • Prefer viewBox to width/height
  • Remove style elements
  • Remove script elements

正则表达式替换

如果不想用第三方工具,可以使用正则表达式,简单的替换一下,相当于只优化了前面的Round/rewrite numbers

"--THE-SVG-STRING--".replace(/(\d+\.\d{3,})/g, function(s0, s1) {
    return Math.round(s1 * 1000) / 1000
});

原来的图片,就会被替换为:

<svg class="lds-gears" width="54px" height="54px" xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"
  style="background: none;">
  <g transform="translate(50 50)">
    <g transform="translate(-19 -19) scale(0.6)">
      <g transform="rotate(107.866)">
        <animateTransform attributeName="transform" type="rotate" values="0;360" keyTimes="0;1" dur="1s" begin="0s"
          repeatCount="indefinite"></animateTransform>
        <path
          d="M37.35 -7 L47.35 -7 L47.35 7 L37.35 7 A38 38 0 0 1 31.36 21.46 L31.36 21.46 L38.431 28.532 L28.532 38.431 L21.46 31.36 A38 38 0 0 1 7 37.35 L7 37.35 L7 47.35 L-7 47.35 L-7 37.35 A38 38 0 0 1 -21.46 31.36 L-21.46 31.36 L-28.532 38.431 L-38.431 28.532 L-31.36 21.46 A38 38 0 0 1 -37.35 7 L-37.35 7 L-47.35 7 L-47.35 -7 L-37.35 -7 A38 38 0 0 1 -31.36 -21.46 L-31.36 -21.46 L-38.431 -28.532 L-28.532 -38.431 L-21.46 -31.36 A38 38 0 0 1 -7 -37.35 L-7 -37.35 L-7 -47.35 L7 -47.35 L7 -37.35 A38 38 0 0 1 21.46 -31.36 L21.46 -31.36 L28.532 -38.431 L38.431 -28.532 L31.36 -21.46 A38 38 0 0 1 37.35 -7 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23"
          fill="#0097e0"></path>
      </g>
    </g>
    <g transform="translate(19 19) scale(0.6)">
      <g transform="rotate(229.634)">
        <animateTransform attributeName="transform" type="rotate" values="360;0" keyTimes="0;1" dur="1s"
          begin="-0.0625s" repeatCount="indefinite"></animateTransform>
        <path
          d="M37.35 -7 L47.35 -7 L47.35 7 L37.35 7 A38 38 0 0 1 31.36 21.46 L31.36 21.46 L38.431 28.532 L28.532 38.431 L21.46 31.36 A38 38 0 0 1 7 37.35 L7 37.35 L7 47.35 L-7 47.35 L-7 37.35 A38 38 0 0 1 -21.46 31.36 L-21.46 31.36 L-28.532 38.431 L-38.431 28.532 L-31.36 21.46 A38 38 0 0 1 -37.35 7 L-37.35 7 L-47.35 7 L-47.35 -7 L-37.35 -7 A38 38 0 0 1 -31.36 -21.46 L-31.36 -21.46 L-38.431 -28.532 L-28.532 -38.431 L-21.46 -31.36 A38 38 0 0 1 -7 -37.35 L-7 -37.35 L-7 -47.35 L7 -47.35 L7 -37.35 A38 38 0 0 1 21.46 -31.36 L21.46 -31.36 L28.532 -38.431 L38.431 -28.532 L31.36 -21.46 A38 38 0 0 1 37.35 -7 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23"
          fill="#7f8b95"></path>
      </g>
    </g>
  </g>
</svg>

是不是很简单呢? (\d+\.\d{3,}) 正则的意思是,只处理超过 3 位小数的,给他四舍五入

效果几乎不变,甚至有些地方更加平滑了

loading.svg