如何優雅的在微信小程序使用 SVG 字體圖標

本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!css

本文思路來自實際項目的重構總結,歡迎糾正和交流。若是對你有幫助,還請點贊👍收藏支持一下啦。html

最近在重構一個項目,主要是作 H5 端和小程序端,此次打算開始多作總結啦,以前已經總結一篇《如何優雅的管理 HTTP 請求和響應攔截器?》 。前端

若是你們還有其餘方案,歡迎一塊兒探討哈~ 喜歡本文的朋友給個贊👍鼓勵一下哈~git

1、需求思考和方案設計

本文介紹的項目是使用 Taro框架進行多端開發,目前主要適配 H5 端和微信小程序端。項目使用的字體圖標庫內部維護,目前託管在 iconfont 上。github

1. 問題分析

最近在重構的項目比較古老(其實也就去年的),項目中使用到的圖標早已更新 N 個迭代了,已經由單色圖標更新到多色圖標 很明顯好看多了。typescript

這裏先按照 iconfont 的規則看看單色圖標和多色圖標使用上的區別:npm

單色圖標的使用

單色圖標使用起來比較簡單(以 font-class 引用爲例),只須要 2 個步驟:json

  • 第一步:拷貝項目下面生成的fontclass代碼:
//at.alicdn.com/t/font_8d5l8fzk5b87iudi.css
複製代碼
  • 第二步:挑選相應圖標並獲取類名,應用於頁面:
<i class="iconfont icon-xxx"></i>
複製代碼

多色圖標的使用

多色圖標使用起來也很簡單(以 symbol 引用爲例),只須要 3 個步驟:小程序

  • 第一步:拷貝項目下面生成的symbol代碼:
//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js
複製代碼
  • 第二步:加入通用css代碼(引入一次就行):
<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 上圖標下載爲圖片來引用的狀況)

2. 方案設計

既然咱們瞭解了單色圖標和多色圖標的使用方式:

  • 單色圖標:任意標籤(如 div 標籤) + 對應字體圖標 class 名稱
  • 多色圖標:使用 svg 標籤 + use 標籤設置 xlink:href 屬性

首先立刻想到的是,能不能集合二者使用方式,實現任意標籤經過 class 名稱來使用多色圖標?

答案是能夠的,只須要對圖標文件進行格式轉換,即 將多色字體圖標轉換爲能經過class名稱來引用的字體圖標文件 。

那接下來只要看看如何實現格式轉換便可。

2、重構後的效果

這邊我以其中一個頁面進行重構,最後將單色圖標全都換成新的多色 SVG 字體圖標,效果以下:

3、方案一:手動轉換圖標文件

目前我嘗試了兩套方案,而且都順利實現效果,這邊先分享一下這兩種方案,而後再補充說明我選擇哪一個方案和緣由:

該方案實現的是手動將字體圖標庫文件轉換成能經過 class 名稱來引用的圖標庫。 使用到的工具備:

  1. icomoon:icomoon.io/ 用來打包圖標。
  2. transfonter: transfonter.org/ 用來生成 base64 格式的圖標。

接下來開始試試:

步驟一:經過 iconfont 下載須要的 SVG 格式的圖標

這邊多下載了幾個,都是 svg 格式的文件,以下圖:

步驟二:打包字體圖標

這一步是將零散個多個 SVG 多色圖標打包成一個字體圖標文件,這一步須要使用 icomoon.io/

步驟三:字體圖標進行 Base64 編碼

接下來就須要將打好的字體圖標進行 base64 壓縮,這邊使用transfonter.org/來操做。

第一步選擇前面打好的包裏面的 .ttf 文件:

設置參數,並導出文件:

步驟四:合併字體圖標

通過前面幾個步驟,咱們如今已經有 2 個包:

  • 第一個包:icomoon 生成的包

  • 第二個包:transfonter 生成的包

接下來咱們開始將兩個包合併: 將第一個包 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;

複製代碼

到這邊,方案一實現完成。

4、方案二:藉助第三方庫實現

因爲第一個方案使用起來比較繁瑣,因而我又再研究其餘簡單點的方案。

直到我看到 taro-iconfont-cli 這個庫。

在Taro框架中使用iconfont圖標,不依賴字體,支持多色彩。

目前支持平臺包括:

  • 微信小程序
  • 支付寶小程序
  • 百度小程序
  • 頭條小程序
  • QQ小程序
  • H5

有如下特性:

  • 一鍵生成標準組件,多端支持
  • 使用方便,import便可
  • 支持多色彩
  • 支持自定義顏色
  • 支持 ES6 和 TypeScript 兩種模式

按照文檔描述,只須要 3 個步驟,那麼試試看:

步驟一:安裝 taro-iconfont-cli

# 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 標準組件

經過命令,生成 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>
複製代碼

踩坑記錄

  1. 字體大小設置問題

因爲經過這種方式導出的圖標,是個單獨組件,使用時若是須要設置圖標大小,須要經過設置其 widthheight屬性進行設置。

經過 font-size屬性沒法設置字體圖標的大小。

5、方案對比和選擇

此次只嘗試了這兩種方案,都能順利完成需求。若是你們有其餘方案,歡迎一塊兒評論區討論~

接下來以生成下面相同 20 個多色圖標爲標準,分析這兩種方案:

先看看對比結果:

手動轉換圖標文件 藉助 taro-iconfont-cli 庫實現
生成難易程度 複雜 簡單
使用難易程度 簡單 簡單
資源佔用程度 27kb 420kb(項目未打包前)

分析每一個項目:

1. 對比生成難易程度

  • 「手動轉換圖標文件」須要每次將圖標單獨下載,再進行打包,當圖標數量較多,其工做量就較大。
  • 「taro-iconfont-cli」只需設置字體圖標庫地址,自動下載並生成組件,較爲方便。

2. 對比使用難易程度

二者使用起來都比較簡單:

  • 「手動轉換圖標文件」爲元素添加 class 名稱便可。
  • 「taro-iconfont-cli」爲元素添加 name 屬性。

3. 對比資源佔用狀況

資源佔用差別就很大了,分析下緣由:

  • 「手動轉換圖標文件」是將圖標從新打包,最後生成的都是 base64 編碼的內容,相對較小。
  • 「taro-iconfont-cli」是爲每一個圖標生成一個組件,單獨一個文件,還有附加各個平臺的文件,所以較大。

4. 選擇方案

考慮到目前項目所使用的字體圖標比較少(20 個之內),後續開發人員上手難度問題,我最終使用「taro-iconfont-cli」這套方案。 雖然這個方案生成的組件資源佔用會稍大,可是目前使用圖標較少,而且能夠經過打包工具、CDN 等經常使用優化方式進行優化。

6、本文總結

本文經過一次簡單的項目重構,總結項目中小程序使用 SVG 多色圖標的方案,目的是爲了實如今小程序中可以正常使用 SVG 多色圖標,而且也爲內容愈來愈多獨立站點的項目積累經驗,畢竟各個項目具備相關性。

最後,「taro-iconfont-cli」方案目前已經在內部 npm 倉庫維護,採用版本控制,方便不一樣項目使用時減小衝突。

固然,本文是基於個人經驗總結,歡迎你們有更好的方案,一塊兒討論學習~~

參考文章

相關文章
相關標籤/搜索