本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!css
本文思路來自實際項目的重構總結,歡迎糾正和交流。若是對你有幫助,還請點贊👍收藏支持一下啦。html
最近在重構一個項目,主要是作 H5 端和小程序端,此次打算開始多作總結啦,以前已經總結一篇《如何優雅的管理 HTTP 請求和響應攔截器?》 。前端
若是你們還有其餘方案,歡迎一塊兒探討哈~ 喜歡本文的朋友給個贊👍鼓勵一下哈~git
本文介紹的項目是使用 Taro框架進行多端開發,目前主要適配 H5 端和微信小程序端。項目使用的字體圖標庫內部維護,目前託管在 iconfont 上。github
最近在重構的項目比較古老(其實也就去年的),項目中使用到的圖標早已更新 N 個迭代了,已經由單色圖標更新到多色圖標! 很明顯好看多了。typescript
這裏先按照 iconfont 的規則看看單色圖標和多色圖標使用上的區別:npm
單色圖標使用起來比較簡單(以 font-class 引用爲例),只須要 2 個步驟:json
//at.alicdn.com/t/font_8d5l8fzk5b87iudi.css
複製代碼
<i class="iconfont icon-xxx"></i>
複製代碼
多色圖標使用起來也很簡單(以 symbol 引用爲例),只須要 3 個步驟:小程序
//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js
複製代碼
<style type="text/css"> .icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } </style>
複製代碼
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xxx"></use>
</svg>
複製代碼
這兩種圖標在使用上都很是方便,那你們是否是會好奇,咱們寫本文的目的?後端
緣由是,微信小程序上不支持 SVG 字體圖標!😔 而多色圖標,是須要藉助 SVG 標籤來實現。
因而我在小程序文檔找了很久,也只看到了 <Image>
組件可以使用 SVG,介紹以下:
image圖片。支持 JPG、PNG、SVG、WEBP、GIF 等格式,2.3.0 起支持雲文件ID。
其屬性 src
的值爲圖片資源地址,這就意味着,不能使用 SVG 字體圖標了。所以咱們須要想一想變通的辦法。
(這裏不討論將 iconfont 上圖標下載爲圖片來引用的狀況)
既然咱們瞭解了單色圖標和多色圖標的使用方式:
div
標籤) + 對應字體圖標 class 名稱svg
標籤 + use
標籤設置 xlink:href
屬性首先立刻想到的是,能不能集合二者使用方式,實現任意標籤經過 class 名稱來使用多色圖標?
答案是能夠的,只須要對圖標文件進行格式轉換,即 將多色字體圖標轉換爲能經過class名稱來引用的字體圖標文件 。
那接下來只要看看如何實現格式轉換便可。
這邊我以其中一個頁面進行重構,最後將單色圖標全都換成新的多色 SVG 字體圖標,效果以下:
目前我嘗試了兩套方案,而且都順利實現效果,這邊先分享一下這兩種方案,而後再補充說明我選擇哪一個方案和緣由:
該方案實現的是手動將字體圖標庫文件轉換成能經過 class 名稱來引用的圖標庫。 使用到的工具備:
接下來開始試試:
這邊多下載了幾個,都是 svg 格式的文件,以下圖:
這一步是將零散個多個 SVG 多色圖標打包成一個字體圖標文件,這一步須要使用 icomoon.io/:
接下來就須要將打好的字體圖標進行 base64 壓縮,這邊使用transfonter.org/來操做。
第一步選擇前面打好的包裏面的 .ttf
文件:
設置參數,並導出文件:
通過前面幾個步驟,咱們如今已經有 2 個包:
接下來咱們開始將兩個包合併: 將第一個包 style.css 文件除 @font-face
的內容複製到第二個包 stylesheet.css 文件後面。
這樣就得到一份新的字體圖標文件,其實也能夠拷貝到一份新的 css 文件中。
咱們將前面修改後的文件更名爲 icon.scss
並引入到項目:
// app.scss
@import "./style/icon.scss";
複製代碼
代碼中使用圖標:
<View className="icon-exe-knowledge-ppt">
<View className='path1'></View>
<View className='path2'></View>
<View className='path3'></View>
<View className='path4'></View>
<View className='path5'></View>
<View className='path6'></View>
</View>
複製代碼
最後效果以下:
在使用方案一的時候,踩了好幾個坑,這邊挑兩個來講:
<View classname="path*"></View>
元素剛開始使用,圖標一直沒有出來,後面觀察字體圖標,它是在容器元素下不少個 path1
、 path2
等元素的僞類中去渲染圖標內容:
因此使用時須要手動添加一下。
這是由於手動加的 class 爲 path*
的 View
標籤自己是塊級元素,因此這裏只要簡單加個 display: flex
便可。
而且其字體大小,也是可使用 font-size
來設置:
display: flex;
font-size: 100px;
複製代碼
考慮到複用性,我將這些抽成一個 exe-svg-icon
組件:
import Taro from '@tarojs/taro';
import { View, Text } from '@tarojs/components';
import classNames from 'classnames';
function EXESvgIcon(params) {
const { icon = 'exe-none' } = params;
const containerStyle = {
display: 'inline-block'
}
return (
<View className={classNames('svg', icon)} style={containerStyle}> <View className='path1' style={containerStyle}></View> <View className='path2' style={containerStyle}></View> <View className='path3' style={containerStyle}></View> {/* 通常圖標 3 層,這邊多預留幾層,防止不夠用 */} <View className='path4' style={containerStyle}></View> <View className='path5' style={containerStyle}></View> <View className='path6' style={containerStyle}></View> <View className='path7' style={containerStyle}></View> <View className='path8' style={containerStyle}></View> <View className='path9' style={containerStyle}></View> </View>
)
}
export default EXESvgIcon;
複製代碼
到這邊,方案一實現完成。
因爲第一個方案使用起來比較繁瑣,因而我又再研究其餘簡單點的方案。
直到我看到 taro-iconfont-cli 這個庫。
在Taro框架中使用iconfont圖標,不依賴字體,支持多色彩。
目前支持平臺包括:
有如下特性:
按照文檔描述,只須要 3 個步驟,那麼試試看:
# Yarn
yarn add taro-iconfont-cli --dev
# Npm
npm install taro-iconfont-cli --save-dev
複製代碼
須要注意的是,若是使用的是 Taro 2.x,請安裝 **taro-iconfont-cli@2.1.0**
,並閱讀舊版的README.md。
經過命令生成 iconfont.json 配置文件:
npx iconfont-init
# 可傳入配置輸出路徑
# npx iconfont-init --output iconfont.json
複製代碼
此時項目根目錄會生成一個iconfont.json
的文件,內容以下:
{
"symbol_url": "請參考README.md,複製 http://iconfont.cn 官網提供的JS連接",
"save_dir": "./src/components/iconfont",
"use_typescript": false,
"platforms": "*",
"use_rpx": true,
"trim_icon_prefix": "icon",
"default_icon_size": 18,
"design_width": 750
}
複製代碼
symbol_url
值須要在 iconfont 中複製
經過命令,生成 Taro 標準組件:
npx iconfont-taro
# 可傳入配置文件路徑
# npx iconfont-taro --config iconfont.json
複製代碼
經過控制檯,咱們能夠看到 taro-iconfont-cli 爲每一個圖標單獨生成一個 Taro 組件:
按照文檔使用方法,使用的時候,只須要引入 IconFont
組件,經過 name
名稱來選擇對應圖標便可:
// 省略其餘代碼
import IconFont from '@components/Iconfont/index';
<IconFont name="exe-knowledge-ppt"></IconFont>
複製代碼
按照文檔提示,還有更多使用方法:
// 原色彩
<IconFont name="alipay" />
// 單色:紅色
<IconFont name="alipay" color="red" />
// 多色:紅色+橘色
<IconFont name="alipay" color={['red', 'orange']} size={300} />
// 不一樣格式的顏色寫法
<IconFont name="alipay" color={['#333', 'rgb(50, 124, 39)']} />
// 與文字對齊
<View style={{ display: 'flex', alignItems: 'center' }}> <Text>Hello</text> <IconFont name="alipay" /> </View>
複製代碼
因爲經過這種方式導出的圖標,是個單獨組件,使用時若是須要設置圖標大小,須要經過設置其 width
和height
屬性進行設置。
經過 font-size
屬性沒法設置字體圖標的大小。
此次只嘗試了這兩種方案,都能順利完成需求。若是你們有其餘方案,歡迎一塊兒評論區討論~
接下來以生成下面相同 20 個多色圖標爲標準,分析這兩種方案:
先看看對比結果:
手動轉換圖標文件 | 藉助 taro-iconfont-cli 庫實現 | |
---|---|---|
生成難易程度 | 複雜 | 簡單 |
使用難易程度 | 簡單 | 簡單 |
資源佔用程度 | 27kb | 420kb(項目未打包前) |
分析每一個項目:
二者使用起來都比較簡單:
資源佔用差別就很大了,分析下緣由:
考慮到目前項目所使用的字體圖標比較少(20 個之內),後續開發人員上手難度問題,我最終使用「taro-iconfont-cli」這套方案。 雖然這個方案生成的組件資源佔用會稍大,可是目前使用圖標較少,而且能夠經過打包工具、CDN 等經常使用優化方式進行優化。
本文經過一次簡單的項目重構,總結項目中小程序使用 SVG 多色圖標的方案,目的是爲了實如今小程序中可以正常使用 SVG 多色圖標,而且也爲內容愈來愈多獨立站點的項目積累經驗,畢竟各個項目具備相關性。
最後,「taro-iconfont-cli」方案目前已經在內部 npm 倉庫維護,採用版本控制,方便不一樣項目使用時減小衝突。
固然,本文是基於個人經驗總結,歡迎你們有更好的方案,一塊兒討論學習~~