前端经常会遇见 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 位小数的,给他四舍五入
效果几乎不变,甚至有些地方更加平滑了