更多代碼詳情:github.crmeb.net/u/LXT
簡介
由於SVG自身的矢量性質,不管在什么情況下,圖標都很清晰,可以適應不同尺寸大小和不同分辨率。不用擔心模糊和鋸齒。同時還能更改圖標的填充顏色。
CSS雪碧圖和SVG雪碧圖
傳統的CSS圖標可以分為圖片圖標和字體圖標。
圖片圖標是將所有的icon整合到一張圖中,然后通過定位獲取其中的某個圖標。優點是管理簡單,網絡請求少。缺點是在高像素屏幕上圖標和周邊內容相比會顯得比較模糊;大小固定;大多數樣式無法修改,單個圖標使用場景有限。
相對來說字體圖標會好很多。字體圖標的基本原理是將Icon定義為字體圖像, 在CSS中用@font-face引入Icon Font自定義字體, 再利用font-family和字符碼顯示出指定的圖標。
@font-face {
font-family: 'iconfont';
src: url(/res/icon2.ttf) format('truetype');
}
.icon2 {
font-family: 'iconfont';
}
字體圖標的優點是可以修改圖標的顏色和大小(font-size),網絡請求少。缺點就是添加圖標比較麻煩,圖標放大后有可能帶有鋸齒。跟SVG圖標相比,字體圖標可以修改的樣式屬性也是很有限的。
相對於圖片圖標和字體圖標,SVG圖標可以保持清晰的無限伸縮、具有較多的樣式可以動態更改。
SVG圖標 SVG在HTML代碼中是以SVG代碼節點存在而不是一個圖標鏈接的引用,這是它得以修改樣式的前提。但它又不是在需要用到的地方直接將SVG代碼添加上去,而是有固定的地方來管理所有的圖標,只需定義每個圖標的Id,在需要用到的地方直接通過Id來引用即可。這種使用方式使得圖標在使用時不會被復雜的SVG代碼影響到業務代碼的可讀性,同時最主要的是可以復用SVG圖標和統一管理。
SVG可以做到這一點主要跟SVG中的兩個子標簽< symbol >、< use >相關。
symbol標簽
在SVG雪碧圖的使用中,< symbol >標簽用於定義圖標內容。
symbol元素是什么呢?
symbol元素用來定義一個圖形模板對象,只是單單的定義不會渲染出來,定義后可以在自身所在的SVG中或者其他的SVG中通過< use >標簽元素實例化圖標,也就是通過< use >引用從而被渲染出來。symbol里面可以添加任意的SVG繪圖元素,包括動畫,但不包括< defs >,除了不顯示外基本和SVG跟標簽< svg >標簽差不多,同樣可以設置viewbox這些屬性。
我們在定義圖標時,每一個symbol代表一個圖標。除了不顯示外,整個< symbol >就是一個完成的SVG圖標。
<svg>
<symbol id="svg-test" viewBox="0 0 26 26">
<desc>居中對齊</desc>
<path d="M7,9h12c0.5,0,1-0.5,1-1s-0.5-1-1-1H7C6.5,7,6,7.5,6,8S6.5,9,7,9z"/>
<path d="M19,17H7c-0.5,0-1,0.5-1,1s0.5,1,1,1h12c0.5,0,1-0.5,1-1S19.5,17,19,17z"/>
<path d="M10,12c-0.5,0-1,0.5-1,1s0.5,1,1,1h6c0.5,0,1-0.5,1-1s-0.5-1-1-1H10z"/>
</symbol>
<symbol id="svg-tool-stroke-5" viewBox="0 0 30 16" >
<desc>描邊5</desc>
<rect x="-10" y="6" width="7" height="2"/>
<rect x="-1" y="6" width="2" height="2"/>
<rect x="3" y="6" width="7" height="2"/>
<rect x="12" y="6" width="2" height="2"/>
<rect x="16" y="6" width="7" height="2"/>
<rect x="25" y="6" width="2" height="2"/>
<rect x="29" y="6" width="7" height="2"/>
<rect x="38" y="6" width="2" height="2"/>
</symbol>
</svg>
需要留意的是,里面無法定義< defs >的,所以如果設計紋理或者漸變之類的圖標樣式,需要在< symbol >所在的SVG之前,再用一個SVG來定義這些填充內容。然后再引用到< symbol >中。
<svg id="defs-svg">
<linearGradient id="linear-gradient" x1="0.122" y1="0.147" x2="0.902" y2="0.872" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f4d039"/>
<stop offset="1" stop-color="#f73"/>
</linearGradient>
</svg>
<svg id="sym-svg">
<symbol id="svg-tool-rect" viewBox="0 0 30 16" >
<desc>矩形</desc>
<rect x="0" y="0" width="24" height="14" fill="url(#linear-gradient)"/>
</symbol>
</svg>
SVG圖標的定義一定要在使用前面,也就是< symbol >
標簽一定要在< use >標簽前面,一般我們在文檔流的頭部引入圖標的定義,確保整個文檔流任意地方都可以用到我們定義的圖標。同時將圖標處理成不可見。#defs-svg 這個SVG在文檔流中是不能被隱藏的,隱藏后那些漸變濾鏡等效果就無法使用,所以一般設置寬高為0,層級最低。而#sym-svg可以被隱藏,隱藏后不會印象圖標的使用。
use標簽
< use >標簽是一個引用的標簽,可以通過節點id引用定義在< defs >中的元素,也可以引用< symbol >標簽。
use標簽有兩個作用:
1、可重復調用
2、跨SVG調用
<svg>
<defs>
<g id="shape">
<rect x="0" y="0" width="50" height="50" />
<circle cx="0" cy="0" r="50" />
</g>
</defs>
<use xlink:href="#shape" x="50" y="50" />
<use xlink:href="#shape" x="200" y="50" />
</svg>
<svg width="500" height="110"><use xlink:href="#shape" x="50" y="50" /></svg>
<!-- 直接調用上一節定義好的symbol -->
<svg width="500" height="110"><use xlink:href="#svg-tool-rect" x="50" y="100" /></svg>
< use >是SVG圖標使用原理中的一個關鍵點,我們可以把SVG圖標全部定義在一個SVG中,統一處理。在需要使用的地方再重新創建一個SVG,通過use標簽來調用圖標。
這樣做的好處是可以降低圖標代碼的重復使用、減少圖標代碼對業務代碼的影響。
更改SVG圖標的樣式
我們通過< use >標簽添加到svg中圖標,可以更改SVG的一些樣式,如fill,stroke等,然后通過樣式繼承,將屬性值繼承到子元素中,從而起到更改圖標樣式的作用。
要更改填充色,首先在symbol下定義的圖標自身標簽上不能帶有顏色,然后在使用時我們直接改SVG的fill,這個fill的顏色值會繼承到里面去。如果我們在symbol里面已經定義好了顏色的是無法在使用時更改的。
<svg>
<symbol id="svg-test" viewBox="0 0 26 26">
<desc>居中對齊</desc>
<path d="M7,9h12c0.5,0,1-0.5,1-1s-0.5-1-1-1H7C6.5,7,6,7.5,6,8S6.5,9,7,9z"/>
<path d="M19,17H7c-0.5,0-1,0.5-1,1s0.5,1,1,1h12c0.5,0,1-0.5,1-1S19.5,17,19,17z"/>
<path d="M10,12c-0.5,0-1,0.5-1,1s0.5,1,1,1h6c0.5,0,1-0.5,1-1s-0.5-1-1-1H10z"/>
</symbol>
</svg>
<svg fill="red">
<use xlink:href="#svg-test"/>
</svg>
<svg fill="blue">
<use xlink:href="#svg-test"/>
</svg>
如何更改圖標中的多個顏色
根據上面描述知道,如果按照上面的方式,那能夠更改的只有圖標中的一種顏色。當然是可以設置多個顏色。這里使用到css的自定義屬性 CSS Custom Properties
需要對< symbol >里面的圖標代碼進行更改,將圖形的顏色設置為fill: var(–*[, default])的形式。
<symbol id="icon-flag" width="150" height="100" viewBox="0 0 3 2">
<rect width="1" height="2" x="0" style="fill: var(--color0, #008d46)" />
<rect width="1" height="2" x="1" style="fill: var(--color1, #fff)"/>
<rect width="1" height="2" x="2" style="fill: var(--color2, #d2232c)"/>
</symbol>
定義css樣式
.flag-belgium {
--color0: #201b18;
--color1: #f1ee3d;
--color2: #dc352f;
}
<svg class="icon">
<use xlink:href="#icon-flag"/>
</svg>
<svg class="icon flag-belgium">
<use xlink:href="#icon-flag"/>
</svg>
< symbol >中的標簽在獲取填充色時,會先獲取–color的顏色,如果顏色值不存在則獲取默認色值。
這就是如何在SVG雪碧圖的制作原理,主要包含兩步,一步是使用定義圖標模板、一步是利用添加圖標。使用SVG圖標最麻煩的就是在定義圖標這一塊,設計師一般只提供SVG圖標,不會提供< symbol >代碼,需要你手動去求改SVG代碼,這一步比直接使用位圖圖標麻煩得多。當然如果有條件的話,也可以寫一個腳本去自動將設計師給你的SVG圖片轉換成< symbol >代碼。這樣就省心多了。
webpack合並svg小文件,轉為雪碧圖
var SVGSprites = require('svg-sprite-plugin')
new SVGSprites({
src: '../../static/vast/',
log: 'info',
sprites_conf: {
'icons': {
shape: {
id: {
separator: '-'
}
},
mode: {
css: {
dest: config.staticPath + 'vast/css/',
layout: "diagonal",
sprite: 'sprite.svg',
bust: false,
render: {
css: true
}
}
}
}
}
})