本文介紹使用圖示字型和SVG取代雪碧圖的方法。雪碧圖是很多網站經常用到的一種技術,但是它有缺點:高清屏會模糊、無法動態變化如hover時候反色。而使用圖示字型可以完美解決上述問題,同時具備相容性好,生成的檔案小等優點。
雪碧圖
雪碧圖例項:淘寶PC端
將多張小圖放至一張大圖
使用的時候,通過background-position調整顯示的位置,如下圖所示:
雪碧圖的使用方法
使用雪碧圖唯一的優點,可以說就是減少瀏覽器的請求次數。因為瀏覽器同一時間能夠載入的資源數是一定的,IE 8是6個,Chrome是6個,Firefox是8個。為了驗證,寫了以下html結構:(這部份雖然有點跑題,但是很要必要深究一下)
驗證Chrome同時載入個數的html–很多張很大的圖片
然後在Chrome的開發者工具裡面的Timeline可以看到Chrome確實是6個6個載入的,每次最多載入6個:
Chrome同時最多載入資源數為6個
雪碧圖的製作方法可以用node的一個的包css-sprite,十分地方便。只要將圖示做好,放到相應的資料夾裡面,寫好配置檔案執行,就能夠生成相應的圖片和css,無需自己手動去調整位置等css屬性。詳見css-sprite
然而,使用雪碧圖存在不可避免的缺點
雪碧圖的缺點
高清屏會失真
在2x的裝置畫素比的螢幕上例如mac,如果要達到和文字一樣的清晰度,圖片的寬度需要實際顯示大小的兩倍,否則看起來會比較模糊:讀者可以對比左邊文字和右邊圖片裡文字的清晰度
右邊圖片裡的文字比左邊字型的文字模糊
特別是現在手機絕大部份是高清屏了,例如iphone 6 plus的解析度達到了1920 * 1080,所以為了高清屏,使用雪碧圖可能要準備多種規格的圖片。
雪碧圖不方便變化
雪碧圖是一張靜態的圖片,當他生成的那天就註定了他要以什麼樣的方式展示,因此我不能動態地改變他的顏色,無法讓他變大(可能會失真),無法像文字一樣加一個陰影效果等等。例如下面的選單,hover或者選中的時候反色:
選中或者hover時反色
或者是某一天UI要換顏色、某一天老總掛了,為表哀悼,為個公司的網站要換個灰色調。使用雪碧圖時,所有的圖示都得重新制作。
使用圖示字型可以完美解決上面的問題
圖示字型icon font
圖示字型就是將圖示作成一個字型,使用時與普通字型無異,可以設定字號大小、顏色、透明度等等,方便變化,最大優點是擁有字型的向量無失真特點,同時可以相容到IE 6。還有一個優點是生成的檔案特別小,215個圖示的生成的ttf字型檔案才41KB
一個圖示字型裡面的元素
如何製作圖示字型
需要準備PS和AI,開啟UI圖,選中圖示的圖層,通常它是設計師畫的一個形狀:
1. 選中圖示的圖層
然後執行:檔案->匯出->Illustrator,如下左圖所示,將生成一個AI檔案。用AI開啟剛剛生成的檔案,執行File->Scripts->SaveDocsAsSVG,如下右圖所示,將生成一個SVG檔案:
2. 左: PS裡匯出AI檔案,右:AI裡面匯出SVG
接下來,藉助一個第三方的網站製作圖示icomoon.io,進入app頁面,選擇匯入icon,將剛剛生成的svg上傳上去
3. 上傳到icomoon
最後生成字型並下載:
4. 生成幾種規格的字型
使用的時候通過@font-face引入,根據圖示的編碼就可以在頁面中使用了。
然而在實際的操作中並沒有像上面說的那麼順利,會遇到很多阻礙,筆者也是摸索了很久才總結了一套實用的經驗,這也是其它介紹圖示字型的教程沒有提及到的,看其它很多教程可能會在實際使用中遇到很多坑。
坑1:圖示字型只支援單路徑
通常情況下,設計師在製作圖示的時候是用多個路徑組合出來的,在上面的匯出的svg也是帶有多個路徑的,開啟svg檔案就可以知道,它是由幾個path組成的:
匯出的svg檔案是由幾個path組成的
但是字型只支援單路徑, 一個解決辦法是手辦修改svg檔案,把多個path合併成一個,這就要求對svg格式比較熟悉。但是這種方法吃力不討好,只適用比較簡單的情況,複雜的圖示最後合併的效果很難做到和原先的一模一樣。
有一個比較智慧的辦法,就是使用PS的合併形狀元件的功能:
使用PS合併形狀元件
這樣子生成的svg就是單路徑的,有時候會遇到“合併形狀元件”的選單項是置灰的,只要把圖層的小眼睛點掉再開啟就可以了(或者可能本身就是單路徑的)。
坑2:有些圖示是多個圖層組成的
一開始不知道,所以比較笨的方法是分別生成幾個svg之後,再去手動去合併svg。其實PS有一個合併形狀的功能,選中多個形狀後,右鍵“合併形狀”:
使用PS合併多個形狀圖層
坑3:生成的SVG填充可能被置為none
有時候會遇到生成了svg,但是上傳上去是空的,檢查一下svg檔案發現是fill被置為none了,如下所示:
生成的svg是fill:none
這個時候需要手動改一下svg檔案,把fill:none改成隨便一個色值即可,如fill:#000000.
使用一個指令碼自動匯出svg
在上面的操作中,都是要先執行PS匯出再到AI裡面執行匯出,其實有一個指令碼,能夠自動執行這兩步:PSD to SVG, 支援PS CS6,不支援CC,還可以把這個指令碼設定一個快捷方式,用起來非常方便。使用這個指令碼需要注意的是圖層的命名不能帶中文,不然會出錯,所以通常把圖層複製到一個新的檔案裡面進行操作。
使用PSD to SVG增加便利
現在重點說下,圖示字型的使用和一些注意事項
圖示字型的使用
通過font-face匯入自定義字型,可以參考字型下載後的demo。然後,把所有使用圖示字型的span/a標籤都加一個.icon的類,.icon類設定font-family為font-face定義的字型名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@font-face { font-family: 'icon-font'; src: url('fonts/icon-font.eot'); src: url('fonts/icon-font.eot#iefix') format('embedded-opentype'), url('fonts/icon-font.ttf') format('truetype'), url('fonts/icon-font.woff') format('woff'), url('fonts/icon-font.svg#icon-font') format('svg'); font-weight: normal; font-style: normal; } .icon{ font-family: "icon-font": } |
最後,每個圖示使用它在相應的編碼或者HTML實體:
圖示字型的兩種使用方法
其中,e9d3是當前圖示在這個字型裡面的十六進位制編碼。在普通字型裡,0的編碼是0x16,即48,為0的ascii編碼。
在使用過程中遇到的坑:
1. webkit瀏覽器會在加緣加粗1個畫素
如下,讀者可找下區別:
左邊的圖示邊緣多了一個畫素,右邊是正常的
這個問題在間距比較小的時候就會比較明顯,例如上圖第二個圖示中間。解決文案是加一個font-smoothing的屬性:
1 2 3 4 |
.icon{ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } |
2. 注意快取
後續加了新的圖示字型,如果不做處理的話,已經載入過的瀏覽器可能會有快取,導致新的圖示字型不會重新下載,所以需要處理這個問題。最簡單的就是在上面的@font-face匯入的url裡面新增一個版本號的引數:
1 |
src: url('fonts/icon-font.eot?hadf22'); |
3. 多人協作
icomoon免費版的資料是儲存在瀏覽器的本地資料庫的, 商業版交點錢可以把資料放在雲端,從而實現多人協作。免費版也可以實現多人協作,方法是將別人生成的字型svg導進去再新增,生成新的svg字型,同樣別人要再上傳的時候先上傳這個svg。商業版使用的時候需要注意多人同時操作的情況,有可能會同時生成相同的編碼。阿里也提供了一個線上的圖示字型制作網站:http://www.iconfot.cn,和icommon相比,沒有提供編碼的方式只能夠使用HTML實體的方式。另外icommon還提供了線上編輯的功能還有大量圖示的搜尋功能,商業版提供woff2字型下載。
圖示字型的缺點
圖示字型有一個顯而易見的缺點,不支援多色圖示。因為它是一個字型,決定了它只能是單色的。如果實再是要使用多色的圖示,甚至帶一些特殊效果的那就使用SVG吧。
結合使用SVG
對於多色的圖示,可以在頁面插入一個SVG:
左邊的location的圖示就是使用了svg,效果比直接貼一張PNG好很多
SVG的相容性,除了IE 8不支援,其它的都還好。況且現在很多新專案都不再相容IE 8了,不然連個border-radius都用不了。
有幾種使用SVG的方法:
1. 直接copy到頁面
例如,後端如果用的是JSP,那麼可以藉助include功能:
1 |
<%@ include file="loc-svg.jsp"%> |
loc-svg.jsp裡面的內容就是svg:
藉助jsp巢狀svg
這樣做的缺點是瀏覽器沒辦法快取,同時會阻礙頁面的載入。優點是由於是內聯的,可以直接用CSS控制svg的樣式
2. 使用embed/object
1 |
<embed src="loc.svg" width="100" height="200"/> |
除此之外,還可以使用img標籤,將svg的路徑作為src屬性,這種方法的缺點是沒辦法用CSS控制樣式。還可以轉化為base64的方式。更多使用SVG的方式參見:Using SVG
當小個的SVG過多的時候,可能要考慮把多個小的SVG合併成一個SVG,就像雪碧圖那樣:
3. 合併SVG
如下所示:通過一個個的symbol,將多個svg合在了一起,同時將每個symbol svg定義一個id,使用的時候會用到
1 2 3 4 |
<svg> <symbol viewBox="0 0 101.5 57.9" id="active-triangle"><path fill="#15c0f1" d="M100.4.5L50.7 57.1 1.1.5h99.3z"/> <symbol viewBox="0 0 101.5 57.9" id="logo"><path fill="#15c0f1" d="M120.4.5L50.7 57.1 1.1.5h99.3z"/> </svg> |
使用的時候通過外鏈的辦法將svg引到頁面上,如要用到上面定義的logo,通過“檔名#ID”的方式:
1 2 3 |
<svg viewBox="0 0 100 100"> <use xlink:href="icon.svg#logo"></use> </svg> |
然而蛋疼的IE不支援外鏈,但是有人寫了個外掛,可以讓IE支援,原理是檢測到瀏覽器不支援外鏈的時候就將其外鏈替換成相應的svg內容,詳見svg for everybody
使用SVG的還有highCharts和d3.js等。
至此,整個流程說明完畢~ 圖示字型和SVG結合使用,提升網站的高清體驗。