SVG 便可縮放矢量圖形。跟普通的圖片相比,它放大也不會失真,而且文件體積更小。如今瀏覽器對 SVG 支持性是很是好的,咱們常常在項目中使用它,好比使用 SVG 圖標或者使用 SVG 圖片解決高清屏幕下的 1px 顯示問題。css
本文將主要談論 SVG 圖標的使用,而且會結合實例給出相應的解決方案。文章將分爲上下兩篇: 上篇,主要介紹 SVG 的相關知識,介紹如何使用 gulp 合併圖標,並編寫一個 Icon 組件。下篇中,將介紹如何編寫 webpack 插件來處理 SVG 文件。html
使用 SVG 作圖標的話,就不得不拿來與 iconfont 作比較。iconfont 的兼容性比較好,但在顯示效果上並不如 SVG,而且不支持多色圖標。因此如今是推薦使用 SVG 圖標。vue
在項目中使用 SVG 圖標有多種方式,其中一種是 SVG Sprite,即把各個圖標合併成一張背景圖片。但這種方式很是不靈活,好比咱們沒法調整某個圖標的大小或者顏色。webpack
相比之下,一種更好的方式使用 SVG Symbol。把個個圖標合併成一個包含多個 symbol 的 SVG 文件。在須要使用圖標的地方,引用對應的 symbol 便可。git
假設有下面這一段 symbol 文件,裏面包含了一個 id 爲 QQ 的圖標。github
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="QQ" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
<path d="M2.87 23c-1.42 3.49-1.67 6.78-.54 7.37.79.44 2.06-.54 3.24-2.31a9.73 9.73 0 0 0 3.24 5.11C7.09 33.82 6 34.9 6 36.08c0 2 3 3.58 6.78 3.58 3.39 0 6.19-1.28 6.73-3h.79c.54 1.72 3.34 3 6.73 3 3.78 0 6.78-1.57 6.78-3.58 0-1.18-1.13-2.26-2.85-2.9a9.73 9.73 0 0 0 3.24-5.11c1.18 1.77 2.41 2.75 3.24 2.31 1.18-.59.93-3.93-.54-7.37-1.13-2.7-2.65-4.71-3.83-5.16v-.54a5.32 5.32 0 0 0-.79-2.8v-.2A2.92 2.92 0 0 0 32 13C31.69 5.93 27.18.33 19.86.33S8 5.93 7.73 13a2.92 2.92 0 0 0-.29 1.33v.2a5.32 5.32 0 0 0-.79 2.8v.54C5.57 18.31 4 20.27 2.87 23z"/>
</symbol>
</svg>
複製代碼
如今要使用這個圖標,經過設置 id 就能夠引入對應的 symbol。web
<svg class="icon icon-QQ">
<use xlink:href="#QQ"></use>
</svg>
複製代碼
咱們給圖標添加了一個類名,若有必要,還能夠經過 CSS 就能夠來調整圖標的樣式。這種方式可控性強,而且顯示效果也好。gulp
設計師給咱們的圖標都是一張張圖片,差很少像下圖這樣。瀏覽器
接下來須要對 SVG 進行合併壓縮處理。最省事的方式是使用 阿里巴巴矢量圖標庫 去管理圖標,須要使用 symbol 文件的話,在頁面上引入腳本便可。若是你喜歡這種方式,那下文就能夠沒必要再看了😂。app
在這裏,咱們使用 gulp 以及 gulp-svg-sprite 來處理 SVG 圖標。gulp-svg-sprite 是一個專門用來處理 SVG 圖片的 gulp 插件,提供了生成 sprite 背景圖片與 symbol 文件的功能。下面是 gulp 的配置文件
const gulp = require('gulp')
const svgSprite = require('gulp-svg-sprite')
const config = {
// 去除 svg icon 顏色
svg: {
transform: [
function (svg) {
return svg.replace(/(<style.*?<\/style>)/g, '').replace(/(fill=\"#([0-9a-f]{6})\")/g, '')
}
]
},
mode: {
view: {
bust: false,
sprite: 'sprite.svg',
render: {
css: true
}
},
symbol: true
}
}
gulp.task('svgSprite', function () {
return gulp.src('./icon/*.svg').pipe(svgSprite(config)).pipe(gulp.dest('svg'))
})
gulp.task('default', ['svgSprite'])
複製代碼
經過設置 mode
來配置生成不一樣類型的文件。上述配置中,咱們選擇生成 spirite 背景圖片與 symbol 文件。有些 SVG icon 中預設的有些顏色,在合併成 symbol 文件前,要作去色處理。配置插件的 transform
函數,便可完成對去色。
在項目文件夾目錄下執行 gulp
命令,生成的文件以下。
接下來拷貝 sprite.symbol.svg 的內容拷貝到 index.html 中,而且設置 SVG 元素隱藏。以後 Icon 組件就可使用了。這一步操做是手動進行的,很是不方便,因此在下篇中,咱們經過開發 webpack 插件來自動插入 symbol 文件內容到 index.html 中。
<!-- index.html -->
<body>
<!-- 拷貝 symbol 文件到這裏 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
<symbol id="QQ">
<!-- .... -->
</symbol>
</svg>
<div id="app"></div>
</body>
複製代碼
如今開發的 Icon 組件提供哪些功能或者有哪些參數呢?暫時提出如下幾點需求:
一個示例以下:
<template>
<svg :class="iconClassName" :style="{color: this.color}">
<use :xlink:href="'#' + type"></use>
</svg>
</template>
<script>
export default {
name: 'icon',
computed: {
iconClassName () {
return ['icon', `icon-${this.size}`, `icon-${this.type}`]
}
},
props: {
type: {
required: true,
type: String,
validator (value) {
return ['wechat', 'QQ', 'weibo'].indexOf(value) !== -1
}
},
size: {
type: String,
default: 'medium',
validator (value) {
return ['small', 'medium', 'large'].indexOf(value) !== -1
}
},
color: {
type: String,
default: '#cccccc'
}
}
}
</script>
<style lang="scss">
.icon {
display: inline-block;
vertical-align: middle;
fill: currentColor;
&.icon-medium {
width: 24px;
height: 24px;
}
// ...
}
</style>
複製代碼
Icon 組件有三種大小的尺寸,默認狀況下是 medium。圖標顏色能夠根據自定義,默認是 #cccccc
。在合併 SVG 圖標時,去除了圖標自己的顏色。設置 Icon 的樣式規則中有這一條 fill: currentColor;
,這段屬性代表 SVG 路徑填充色繼承當前元素的顏色,這樣咱們就能夠定製圖標的顏色了。
針對 Icon 組件的兩個props: type 與 size,編寫了 validator 函數來校驗傳入 prop 值,當傳入的 prop 值非法時,開發環境下會有錯誤的提示,從而避免了 Icon 組件使用不正確的問題。
組件註冊後,就能夠直接使用了。
<icon type="QQ" />
複製代碼
完整的代碼點擊這裏。
在本篇文章,咱們完成了 SVG 圖標的合併與 Icon 組件的編寫。SVG 圖標由於其自身的優點與瀏覽器的良好支持,很是適合在項目中使用。但願你們能夠探索出更多的用法。
在下篇文章中,咱們將經過開發 webpack 插件,避免手動的複製粘貼 SVG symbols 文件。