繼前面介紹過ICON-FONT的制作后,找了幾個ICON庫都是國外的
今天偶然發現阿里巴巴的圖標矢量庫,www.iconfont.cn
用了之后感覺很強大,豐富的圖標庫(集合阿里媽媽&淘寶的圖標庫),還支持自己上傳,關鍵還能生成你項目專用的CDN,速度不言而喻,支持國產。下面引用介紹
轉載請注明來源:Web前端(W3Cways.com) - Web前端學習之路 » 阿里UX矢量圖標庫–最強大的矢量圖標庫(Icon font制作力薦工具)
使用SVG來代替Web Iconfont(圖形字體化)
從最開始的,使用img圖片到后來的使用css sprite(web前端工程師必須掌握的技巧–CSS Sprites技術(附基礎操作教程))來減少服務器請求,到現在流行使用的圖形字體化iconfont(阿里UX矢量圖標庫–最強大的矢量圖標庫(Icon font制作力薦工具))
但是,Iconfont存在一些弊端:
- 瀏覽器將其視為文字進行抗鋸齒優化,有時得到的效果並沒有想象中那么銳利。 尤其是在不同系統下對文字進行抗鋸齒的算法不同,可能會導致顯示效果不同。
- Icon Font 作為一種字體,Icon 顯示的大小和位置可能要受到
font-size
、line-height
、word-spacing
等等 CSS 屬性的影響。 Icon 所在容器的 CSS 樣式可能對 Icon 的位置產生影響,調整起來很不方便。 - 使用上存在不便。首先,加載一個包含數百圖標的 Icon Font,卻只使用其中幾個圖標,非常浪費加載時間。 如果是自己制作 Icon Font 以及把多個 Icon Font 中用到的圖標整合成一個 Font 也非常不方便。當然使用阿里UX矢量圖標庫可以解決這個問題
- 為了實現最大程度的瀏覽器支持,可能要提供至少四種不同類型的字體文件。包括TTF、WOFF、EOT 以及一個使用 SVG 格式定義的字體。如果是自己制作的話,可能要頭疼死
SVG優勢
- SVG是矢量圖形文件,可以隨意改變大小,而不影響圖標質量。
- 可以用CSS樣式來自由定義圖標顏色,比如顏色/尺寸等效果。
- 所有的SVG可以全部在一個文件中,節省HTTP請求 。
- 使用SMIL、CSS或者是javascript可以制作充滿靈性的交互動畫效果。
由於SVG也是一種XML節點的文件,所以可以使用gzip的方式把文件壓縮到很小。
開發者們想出了多種使用 SVG 的技巧來解決/緩解上述問題,下面我們來逐個盤點目前常見的使用方法。
img/object 標簽
使用 img 和 object 標簽直接引用 SVG 是早期常見的使用方法。 這種方法的缺點主要在於要求每個圖標都單獨保存成一個 SVG 文件,使用時也是單獨請求的。 如果在頁面中使用的多個圖標,每個都是單獨請求的話會產生很多請求數,增加服務端的負載和拖慢頁面加載速度, 因此現在很少使用了。
不過,在 IE 中可以使用 object 標簽實現最后討論的 SVG Defs/Symbols 的效果。
Inline SVG
所謂 Inline SVG,就是直接把 SVG 寫入 HTML 中,這種方法簡單直接,而且具有最強的可調性。 使用這種方法,你可以使用 CSS 的fill屬性和stroke屬性來控制填充顏色和邊線的顏色, 如果 SVG 圖標包含多個部分,你甚至可以設置每個部分的樣式。同時,使用 JavaScript 修改 SVG 和生成動畫效果都可以實現。
Inline SVG 作為 HTML 文檔的一部分,不需要單獨請求。臨時需要修改某個圖標的形狀也比較方便。 但是 Inline SVG 使用上比較繁瑣,需要在頁面中插入一大塊 SVG 代碼因此不適合手寫,圖標復用起來也比較麻煩。
好在我們大部分的頁面都是由某種模板渲染出來的,無論是使用 PHP、Jinja2 還是 ERuby 模板語言, 都可以定義一個函數來幫我們 include 這些 SVG。因此在很多情況下是很好的解決方案, 其不適合的主要使用場景就是純靜態頁面或者前后端分離客戶端頁面。
Data URIs
Data URIs 是一種不怎么常見的技巧。之前我們在 CSS 里定義元素的背景圖片時,常使用像下面這種方式
.icon { backgound-image: url(icons/a.png) /* ... */ }
而現在,url
當中可以放置的可以不僅僅是指向資源的 URL 鏈接,而可以是數據本身。使用 Data URIs,無論是圖片還是 SVG, 你都可以將其編碼為 base64 並直接寫入 CSS。譬如
.icon{ background: url(data:text/svg+xml;base64,<base64 encoded data>) }
關於 base64 編碼,之前我寫過一篇使用Data URIs來提高你的網站速度使用這種方法,SVG Icon 使用起來和 Icon Font 一樣只需要為元素添加 CSS 即可,所有的資源都可以整合在一個 CSS 文件中,
不需要額外引用 SVG 文件。
如果你在使用 Gulp 或者 Grunt 這樣的 Build 工具,那么將 SVG 整合到一個 CSS
當中是可以非常方便地自動化完成的。這個任務只有簡單的字符串和編碼處理,基本不需要依賴非 JavaScript 的庫和資源。
使用這種方法的缺點是不能方便地使用 CSS 修改 Icon 的顏色和邊線屬性。
SVG Sprite
目前,一些提供制作 Icon Font 功能的網站 (如icomoon) 已經提供輸出 SVG Sprites 功能了。
SVG Sprites 可以看做上述 Data URIs 方法和之前使用位圖的 Sprite 方法的組合。
在 Icon Font 還沒普及、圖標還主要依靠位圖顯示的時候,前端工程師都會使用 Sprite 來減少圖片請求的次數。 其原理很簡單:將所有的圖標以一定的間隔排列起來組成一整張大圖片,使用時對於某個 Icon,編寫如下所示的 CSS。
.icon-a { background-image: url(/path/to/pic/contains/all/icons.png); background-position: 0 120px !important; width: 24px; height: 24px; }
上述 CSS 通過設定background-position
調整大圖片在背景中的位移,只將某個單個 Icon 暴露出來,其他部分都切掉。 對於所有的 Icon 都寫成這樣的 CSS 即可使用了。基礎的 SVG Sprite 其實只是將原來的位圖改成了 SVG。
SVG Sprite 相比於原來的位圖 Sprite 的一個優點就是可以通過 CSS 調整 Icon 顯示的大小。 使用時還可以 Fallback 到位圖的 Sprite,因此有極好的瀏覽器兼容性。 不過和 Data URIs 方法一樣它同樣存在不能方便調整顏色樣式的問題。目前輔助生成 SVG Sprites 的工具有 grunt-iconizr、
gulp-svg-sprites 等。
使用這兩個工具,只需將用到的 SVG 放到某個文件夾中就可以自動被拼合成 Sprite 並輸出對應 CSS。
兩個工具都支持生成 PNG 格式的位圖作為 Fallback,缺點是生成位圖要依賴phantomjs
這個重量級 JS 庫。
SVG Defs/Symbols
SVG Defs 和 Symbols 的原理類似,這里着重介紹一下 SVG Symbols 的使用, SVG Defs/Symbols 本質上是對 Sprite 的進一步優化。之前,我們需要使用相對位置來控制哪個圖標被顯示出來, 但是其實 SVG 本身的定義允許你以某一種方式直接引用 SVG 中的某一部分。
將多個圖標整合成一個 SVG 中的多個 Symbols 之后是下面這樣的
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="circle-cross" viewBox="0 0 32 32"> <title>circle-cross icon</title> <path d="M16 1.333q2.99 0 5.703 1.161t4.677 3.125 3.125 4.677 1.161 5.703-1.161 5.703-3.125 4.677-4.677 3.125-5.703 1.161-5.703-1.161-4.677-3.125-3.125-4.677-1.161-5.703 1.161-5.703 3.125-4.677 4.677-3.125 5.703-1.161zm0 2.667q-2.438 0-4.661.953t-3.828 2.557-2.557 3.828-.953 4.661.953 4.661 2.557 3.828 3.828 2.557 4.661.953 4.661-.953 3.828-2.557 2.557-3.828.953-4.661-.953-4.661-2.557-3.828-3.828-2.557-4.661-.953zm3.771 6.885q.552 0 .948.391t.396.943-.396.948l-2.833 2.833 2.833 2.823q.396.396.396.938 0 .552-.396.943t-.948.391-.938-.385l-2.833-2.823-2.823 2.823q-.385.385-.948.385-.552 0-.943-.385t-.391-.938q0-.563.385-.948l2.833-2.823-2.833-2.833q-.385-.385-.385-.938t.391-.948.943-.396.948.396l2.823 2.833 2.833-2.833q.396-.396.938-.396z"/> </symbol> <symbol id="circle-check" viewBox="0 0 32 32"> <title>circle-check icon</title> <path d="M16 1.333q2.99 0 5.703 1.161t4.677 3.125 3.125 4.677 1.161 5.703-1.161 5.703-3.125 4.677-4.677 3.125-5.703 1.161-5.703-1.161-4.677-3.125-3.125-4.677-1.161-5.703 1.161-5.703 3.125-4.677 4.677-3.125 5.703-1.161zm0 2.667q-2.438 0-4.661.953t-3.828 2.557-2.557 3.828-.953 4.661.953 4.661 2.557 3.828 3.828 2.557 4.661.953 4.661-.953 3.828-2.557 2.557-3.828.953-4.661-.953-4.661-2.557-3.828-3.828-2.557-4.661-.953zm4.49 7.99q.552 0 .943.391t.391.943-.396.948l-5.656 5.656q-.385.385-.938.385-.563 0-.948-.385l-2.833-2.823q-.385-.385-.385-.948 0-.552.391-.943t.943-.391.948.396l1.885 1.885 4.708-4.719q.396-.396.948-.396z"/> </symbol> <!-- .... --> </svg>
每個 Symbol 設置一個 id 作為引用時的名字。使用 id 引用這個 SVG 中的 Icon 有兩種方式。第一種,將上述 SVG 作為 body 的第一個元素插入在 HTML 中 (Chrome 存在一個
bug 導致不在這里顯示不出圖像),
此后,在需要顯示某個 Icon 的地方插入下面的代碼即可:
<svg class="icon"> <use xlink:href="#circle-cross"></use> </svg>
這里的use標簽直接使用#circle-cross這個 id 引用了 SVG 中的圖標。這種方式的瀏覽器兼容性較好。
第二種方式,這種方式不需要在 body 開始的地方插入 SVG,而是使用完整路徑引用 Icon。
<svg class="icon"> <use xlink:href="/img/posts/svg-icons.svg#circle-check"></use> </svg> <svg class="icon"> <use xlink:href="/img/posts/svg-icons.svg#circle-cross"></use> </svg>
顯示出來的效果就是下面這個樣子 (可以使用瀏覽器的 Debug 工具來檢視下面的代碼)。
這種方式使用上跟img標簽沒有什么太大的差別了。好處在於所有的圖標都在一個文件中,因此只會請求一次。 這種不需要像 Sprite 那樣繁瑣的設置圖片的位移。使用 id 命名圖標並使用時直接使用 id 引用既直觀又簡單。 其靈活性和 Inline SVG 幾乎一樣——你可以設置顏色、邊線樣式、大小等等。 視瀏覽器的不同,有時你需要使用作為 SVG 標簽的開始。
<svg xmlns="http://www.w3.org/2000/svg">
對於 IE 則需要使用object
標簽代替<svg><use>
。關於兼容性討論詳見
這篇文章。
除了前面提到過的幾個 Gulp 和 Grunt 的插件都已經支持 SVG Defs/Symbols 了之外,這里再推薦一個更輕量的 Gulp 插件
gulp-svg-symbols。如果只使用 SVG Symbols 而無需 Sprite 支持,
那么使用 gulp-svg-symbols 可以免去對 phantomjs
的依賴。