SVG Sprite 使用簡介

SVG簡介

SVG便可縮放矢量圖形 (Scalable Vector Graphics)的簡稱, 是一種用來描述二維矢量圖形的XML標記語言. SVG圖形不依賴於分辨率, 所以圖形不會由於放大而顯示出明顯的鋸齒邊緣.javascript

icon sprite

當咱們須要使用多個icon的時候, 爲了節省請求和方便管理, 一般會把icon合併到一個文件中, 在使用時再經過必定的方法從icon集合文件中取出所需的圖形並顯示. 目前使用得最多的應該就是咱們所熟悉的CSS Sprite和Icon Font.css

CSS Sprite

CSS Sprite的原理是將多個icon按必定規律整理到一個圖片文件中, 使用時利用background-imagebackground-position將圖片中特定部分顯示出來. CSS Sprite技術已經被普遍應用了很長的一段時間, 目前有許多自動化生成Sprite圖片和CSS文件的工具, 例如(gulp.spritesmith)[github.com/twolfson/gu…].html

.icon1 {
    background-image: url(/res/icon1.png)
}
.icon1-increase {
    background-position: -10px -10px;
}複製代碼
<i class="icon1 icon1-increase"/>複製代碼

CSS Sprite技術成熟, 兼容性好, 可是缺點也比較明顯. 如在實際需求中, 對應形狀相同但顏色不一樣的icon, 就須要爲不一樣顏色的icon各保存一份; 有時候須要對已有icon放大顯示時, 發現鋸齒嚴重, 那麼又要再保存一份放大版的icon. 所以, Sprite文件會隨着時間越變越大, 同時內容愈來愈亂, 逐漸變得難以管理.java

Icon Font

Icon Font的基本原理是將Icon定義爲圖片字體, 在CSS中用@font-face引入Icon Font自定義字體, 再利用font-family和字符碼顯示出指定的圖標.git

@font-face {
    font-family: 'iconfont';
    src: url(/res/icon2.ttf) format('truetype');
}
.icon2 {
    font-family: 'iconfont';
}複製代碼
<i class="icon2">&#33</i>複製代碼

因爲使用的是字體, 所以能夠經過color, font-size設置icon的樣式. Icon Font擁有比CSS Sprite圖片更小的文件體積, 維護也比圖片更方便, 可是icon font一般只能使用單一的顏色, 字體文件生成也比CSS Sprite更復雜.github

SVG Sprite

一般在使用SVG的時候, 咱們是直接寫到svg標籤當中:express

<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 3 2">
        <rect width="1" height="2" x="0" fill="#008d46" />
        <rect width="1" height="2" x="1" fill="#ffffff" />
        <rect width="1" height="2" x="2" fill="#d2232c" />
    </svg>複製代碼

此時SVG圖形會直接在頁面當中顯示. SVG屬性中, 能夠利用(symbol)[developer.mozilla.org/zh-CN/docs/…, 並利用(use)[developer.mozilla.org/zh-CN/docs/…, 從而實現SVG Sprite的功能.gulp

SVG Sprite實例:瀏覽器

<svg style="height:0;width:0;display:none;" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <symbol id="icon-italy" width="150" height="100" viewBox="0 0 3 2">
        <rect width="1" height="2" x="0" fill="#008d46" />
        <rect width="1" height="2" x="1" fill="#ffffff" />
        <rect width="1" height="2" x="2" fill="#d2232c" />
    </symbol>

    <symbol id="icon-france" width="150" height="100" viewBox="0 0 3 2">
        <rect width="1" height="2" x="0" fill="#002496" />
        <rect width="1" height="2" x="1" fill="#ffffff" />
        <rect width="1" height="2" x="2" fill="#ee2839" />
    </symbol>
</svg>

<svg><use xlink:href="#icon-italy"/></svg>
<svg><use xlink:href="#icon-france"/></svg>複製代碼

這樣就實現了SVG Sprite.app

原理

經過devtool能夠觀察到, use標籤是利用shadow dom實現的.

use.shadowdom
use.shadowdom

它經過xlink:href這個XML的attribute引用指定的SVG symbol, 在渲染時指定symbol標籤中的內容就會被渲染顯示在頁面當中. 這意味着, 若是沒法直接對use標籤中的shadow dom進行訪問和修改. 例如像use#rect這樣的選擇器是沒法生效的, 所以不能經過通常的css選擇器對use中圖形不一樣的部分進行控制.

CSS樣式

更多的時候, 咱們一般都只須要改變圖標的大小和顏色, 在SVG Sprite當中, 實現起來並不複雜.

  1. 大小

經過改變svg容器的大小, 能夠輕鬆地對圖標大小進行控制.

.icon{
    width: 120px;
    height: 80px;
}
.icon.icon-small{
    width: 60px;
    height: 40px;
}複製代碼
<svg class="icon"><use xlink:href="#icon-italy"/></svg>
<svg class="icon icon-small"><use xlink:href="#icon-italy"/></svg>複製代碼

svg.icon.size
svg.icon.size

  1. 顏色
  • 單色

顏色因爲不能直接對use的shadow root中的圖形標籤進行選擇, 所以在爲圖標定義顏色時須要利用fill: inherit這個一屬性.

svg path{
    fill: inherit;
}
.icon2-green{
    fill: #008d46;
}
.icon2-red{
    fill: #dc352f;
}複製代碼
<svg class="icon2 icon2-green">
    <use xlink:href="#icon-increase"/>
</svg>
<svg class="icon2 icon2-red">
    <use xlink:href="#icon-increase"/>
</svg>複製代碼

svg.icon.color
svg.icon.color

利用inherit, 還能夠定義stroke-width, stroke等屬性.

  • 多色

除了對圖標總體顏色進行定義之外, 還能夠根據須要對圖形不一樣部分進行顏色定義. 這裏使用到了css 的自定義屬性(CSS Custom Properties).

這裏須要對icon.svg進行修改, 將圖形個部分的顏色設置爲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>複製代碼

svg.icon.color.parts
svg.icon.color.parts

除此之外, 還有其餘一些樣式定義的形式, 更詳細的內容能夠閱讀Styling SVG Content with CSS.

實際使用

引用外部svg

上文介紹的是使用內聯svg, 但其實還可使用外部svg的.

<svg class="icon">
    <use xlink:href="/res/svg/icon.svg#icon-flag"/>
</svg>複製代碼

然而這種方法不兼容IE9~10, 但若是非要使用外部svg的形式, 能夠引入一個pollyfillsvg4everybody, 當運行在不支持外部svg的狀況下, 這個pollyfill會經過異步請求加載svg委文件並將其注入到頁面當中, 將引用方法轉換成內聯svg.

在ftl中使用

能夠在svg.ftl中定義一系列macro, 用以加載.svg文件.

<#macro svgicon path>
    <#include "${path}">
</#macro>

<#macro svgicon3 >
    <@svgicon "./icon3.svg"/>
</#macro>複製代碼

在頁面中引用demo.ftl:

<@svgicon1/>
<svg>
    <use xlink:href="#icon-italy"/>
</svg>複製代碼

在regular中使用

xlink:href是使用了命名空間的XML特性, 若是是寫在.html頁面的標籤, 該特性可以正常被瀏覽器解析並完成svg渲染. 若是該svg變量是經過DOM API建立出來的話, 則須要使用特定的方法進行處理(SVG with USE tag not rendering).

即須要利用createElementNSsetAttributeNS方法在建立的同時聲明命名空間.

var use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#icon-increase');
document.querySelector('#svgid').appendChild(use);複製代碼

只要是須要動態建立use元素, 都須要使用上面這種方法才能使SVG Sprite中的元素實例化. 但在目前的Regular(0.4.3)中, 不會對命名空間進行處理, 這意味着, 若是直接將<svg><use xlink:href/></svg>寫在Regular組件的模版中時, 該標籤是沒法正常渲染的. 爲此能夠增長一個指令r-xlink:href以完成手動設置命名空間的操做.

Regular.directive('r-xlink:href', function (elem, val) {
    if (val&& val.type === 'expression') {
        this.$watch(val, function (newVal) {
            elem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', newVal);
        });
    } else {
        elem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', val);
    }
});複製代碼

那麼在組件模版中就能夠像在普通.html中那樣使用SVG Sprite了. 固然, 首先得確保SVG Sprite被寫到頁面中.

<svg>
    <use r-xlink:href="#icon-italy"/>
</svg>複製代碼

在Regular的SVG 實踐中獲得了鄭海波大神的指點, 不然得繞更大的路才能把問題解決, 在此表示感謝.

小結

對比前文提到的CSS Sprite和Icon Font, SVG有着明顯的優點:

  • 放大縮小不會失真
  • 大小, 顏色等屬性自定義靈活
  • 體積小, 同時管理方便

雖然SVG Sprite有着高度的靈活性, 但於此同時, SVG兼容性有待考究, 同時其渲染性能也不及圖片和字體那麼高, 可能在某些狀況下不適用. 不過在通常的場景中, svg sprite還可以給開發帶來很大的便利的.

參考

  1. SVG元素參考
  2. SVG with USE tag not rendering
  3. 將來必熱:SVG Sprite技術介紹
  4. Styling SVG Content with CSS
  5. Icon System with SVG Sprites
相關文章
相關標籤/搜索