SVG Symbol 和 Sprite 的好處和坑
用 Symbol 來把 SVG 合并到一個文件幾乎是現在最流行的用法。
Symbol 好處
方便
利用 ID 來取圖案,所以不用各種計算,可以隨便放。
反復利用
這應該是一個不太容易發現的好處,你可以在文件內部繼續用 <use> 來做圖案的各種版本。這樣 SVG 的優勢更加明顯,節省了好多空間。
比如這個博客里用到的社交圖案,原本的是只有圖案本身。例如這是 Codepen 的圖案:
<symbolid="icon-codepen"viewBox="0 0 32 32">
<title>codepen</title>
<pathclass="icon-path"d="M17.050 1.259c-0.882-0.546-2.016-0.546-2.855 0.042l-12.764 8.649c-0.672 0.462-1.092 1.218-1.092 2.016v9.321c0 0.84 0.42 1.596 1.134 2.057l12.974 8.355c0.84 0.546 1.931 0.546 2.813 0l13.226-8.482c0.714-0.462 1.134-1.218 1.134-2.057v-9.153c0-0.84-0.42-1.596-1.134-2.057l-13.436-8.691zM26.959 11.378l-4.87 3.191-4.576-3.233-0.042-6.382 9.489 6.424zM14.11 4.954v6.256l-4.702 3.191-4.702-3.065 9.405-6.382zM3.446 14.401l3.023 1.973-3.023 2.057v-4.031zM14.195 27.753l-9.447-6.172 4.744-3.233 4.744 3.107c-0.042 0-0.042 6.298-0.042 6.298zM12.389 16.332l3.065-2.099 3.569 2.267-3.149 2.099-3.485-2.267zM17.553 27.753v-6.298l4.535-2.939 4.87 3.107-9.405 6.13zM28.302 18.557l-3.233-2.057 3.233-2.099v4.157z"/>
</symbol>
現在直接在文章里 <use> :
<svgfill="#000">
<usexlink:href="/images/symbol-defs.svg#icon-codepen"/>
</svg>
就是這個效果:
在 symbol-defs.svg 里還有它的另外一個版本,帶圓圈的,只需要添加幾行就可以:
<symbolid="icon-codepen-circle"viewBox="0 0 32 32">
<title>codepen</title>
<circlecx="50%"cy="50%"r="50%"fill="#000"/>
<usexlink:href="#icon-codepen"width="20"x="6"fill="#fff"/>
</symbol>
同樣的使用方式,既環保又方便:
Symbol 壞處
不完全支持
這種方式并不完全支持 SVG 的各種特性。比如我開始就踩到了一個坑。我的 LOGO 里使用了 clippath ,使用這種方式就會失去效果。這個貌似是個 陳年老 bug 來的。
解決方式就是利用工具合并路徑,最好還壓縮成一條,方便管理。編輯工具推薦 Boxy SVG ,生成的代碼非常輕盈,而且盡可能保留原來的樣子,不會像 Illustrator 一樣源碼面目全非。壓縮工具推薦 SVGOMG! ,號稱 SVGO 's Missing GUI。
奇怪的寬高
在寬和高是百分比的情況下,會出現跟 <img> 或者普通 <svg> 不一樣的計算。有時高空出一段,有時寬空出一段。
這個我糾結了很久,沒有找到原因。我猜是受到原本整個 SVG 的影響。
解決方法是用相同寬高比的父 <div> 來限制;或者不用百分比。
慢
因為零部件是可以 <use> 的,所以引擎不能像圖片一樣直接解析完就一整塊到處扔。
雖然這個延時非常的小,一般幾乎感覺不到,但是如果像這個博客左邊的菜單欄一樣(電腦上),在每個頁面都是同樣的元素,那么切換頁面的時候就可以肉眼感受到圖案的閃動。這種情況就只能放棄使用 Symbol。可以考慮單獨一張 SVG 圖片或者: ?
SVG Sprite
SVG Sprite 與以前的 PNG Sprite 一樣,把圖案按一定方式平鋪到一張大圖片上。
Sprite 好處
對齊
SVG 不受大小限制,所以 Sprite 可以按統一的規格排列。
取的時候也不受大小限制,利用百分比來取。
比如這個博客左邊菜單的圖案就是 SVG Sprite, 利用 Sass 自動計算百分比 。
快
這種方式與普通圖片一樣肉眼看不到延時,而且還結合了 SVG 不受大小限制的優勢。
Sprite 壞處
添加麻煩
圖案受位置影響,當然沒有 Symbol 方法來得方便。
因為需要快速顯示的圖案不多,我是利用 Boxy SVG 一個一個添加的。
不太用心的查過一下,沒注意到有合適的自動化工具。
能用 Symbol 的當然優先使用 Symbol 方法,所以 Sprite 用的也不多,手動添加可以滿足。
有誤差
使用百分比因為受小數影響,圖案會有 1px 浮動,當然這個 1px 是根據圖案當前大小得出的,所以越小圖案浮動的位置越大。
解決方法有兩個,一是避免產生小數,按倍數來設置圖案大小;二是按圖案最小的情況計算出血,把圖案縮小空出足夠位置。
來自:https://blog.crimx.com/2016/11/28/svg-sprite/