ReactNative中iconfont使用詳解

以下Rn指代ReactNative

1.iconfont簡介

  • 什么是iconfont
    iconfont顯示成圖形圖標的字體,因為字體是矢量化圖形,具有分辨率無關的特性,在任何分辨率和ppi下面,都可以做到完美縮放,不像傳統位圖如:png,jpg一樣,放大后會有鋸齒或者模糊。
  • 為什么使用iconfont
    對比圖片大小來說容量更小,支持樣式修改(大小,顏色),適應多分辨率,網上有很多現成的iconfont資源可以使用。
image.png

2.在Rn中使用iconfont

簡單介紹完iconfont,現在說說在Rn中整么用它。
這里推薦使用react-native-vector-icons
react-native-vector-icons會把字體文件轉換成相應的iconSets在Rn供我們使用。

安裝react-native-vector-icons

npm i --save react-native-vector-icons

ios下配置

用xCode打開項目目錄下的ios,為了管理字體,我們新建一個fonts目錄,字體文件統一放在里面,把字體文件拖進這個文件夾。會有彈框提示并且記得Add to targets選中當前項目。

image.png

確保Build Phases的Copy Bundle REsources中有字體文件

image.png

接著修改info.plist,在information Property List下新增Fonts provided by application,在Fonts provided by application下在增加字體文件,到這里ios就配置好了。

image.png

android配置

安卓下會從android/app/src/main/assets/fonts目錄讀取字體文件,所以我們需要把字體文件*.ttf放在這個目錄下,然后在android/app/build.gradle文件中按需增加下面的配置。

//使用內置的iconSets
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
//使用自定義iconSets
project.ext.vectoricons = [
   iconFontNames: [ 'iconfont.ttf'] // Name of the font files you want to copy
]

使用內置的iconSets

import Icon from 'react-native-vector-icons/FontAwesome';
<Icon name='rocket' size={60} color="#4F8EF7" />

上面的方式引用的是react-native-vector-icons內置的一種iconSets, 除了FontAwesome還有其他iconSets,可以到react-native-vector-icons查看

內置的iconSets

雖然內置了很多iconSets給我們使用,但往往我們做項目時一般都會使用自己的iconfont,整么使用自己的iconfont呢?我們看源碼

源碼分析
react-native-vector-icons/FontAwesome這個返回的是一個iconSets,簡單理解這個iconSets是一個可以幫我們顯示字體圖標的組件。其中name對應圖標在glyphMap.json文件中對應的key。(看到這里,glyphMap.json是什么鬼???)

看react-native-vector-icons/FontAwesome的源碼

/**
 * FontAwesome icon set component.
 * Usage: <FontAwesome name="icon-name" size={20} color="#4F8EF7" />
 */

import createIconSet from './lib/create-icon-set';
import glyphMap from './glyphmaps/FontAwesome.json';

const iconSet = createIconSet(glyphMap, 'FontAwesome', 'FontAwesome.ttf');

export default iconSet;

createIconSet(glyphMap, fontFamily, fontFile)
參數說明:
glyphMap: json對象(key是圖標的name, value是圖標對應的10進制數)
fontFamily: 字體庫對應的fontFamily
fontFile:字體文件名稱(注意這里只聲明字體庫名稱,字體庫路徑分平臺配置)
看glyphMap對應的glyphmaps/FontAwesome.json

{
  "glass": 61440,
  "music": 61441,
  "search": 61442,
  "envelope-o": 61443,
  "heart": 61444,
  "star": 61445,
}

總結一下:
就是根據字體文件(.ttf|.otf)和glyphMap.json創建對應的IconSets,所以要想使用自定義的iconfont我們需要準備這兩樣東西。

使用自定義的iconSets

看完上面的源碼分析,我們開始自定義iconSets,
先準備一套iconfont,作者習慣使用阿里巴巴矢量圖標庫,這里就拿這個來作為??
選取你需要的圖標,添加為一個項目,如下。

image.png

項目默認的fontFamily為iconfont,還記得上面創建iconSets函數的第二個參數嗎,每次對應的就是這個。
這里我修改一下。

image.png
image.png

下載項目,里面的iconfont.ttf就是我們需要的iconfont了。

image.png

回想一下,創建createIconSet需要的東西,還少了glyphMap,glyphMap整么來呢。看這里

image.png

其中e69b是圖標對應的16進制unicode我們需要的是10進制,所以把它轉換一下, 下面使用的是js

parseInt("e69b", 16)
59035

每個圖標都需要轉換一次很麻煩,所以基于阿里巴巴圖標矢量庫下載的文件,我用js寫了一個生成json的工具類。把剛下載下來的iconfont.css,iconfont.json, genJson.js放在同一目錄。?node執行genJson.js,所需要的json對象就被寫入iconfont.json中了。

/*iconfont.css*/
...省略...
.ica {
  font-family:"ica" !important;
  font-size:16px;
  font-style:normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-all:before { content: "\e696"; }

.icon-back:before { content: "\e697"; }

.icon-cart:before { content: "\e698"; }

.icon-category:before { content: "\e699"; }

.icon-close:before { content: "\e69a"; }

.icon-comments:before { content: "\e69b"; }


/*genJson.js*/
const path = require('path');

const oldPath = path.resolve(__dirname, 'iconfont.css');
const newPath = path.resolve(__dirname, 'iconfont.json');

var gen = module.exports = function () {
    const readline = require('readline');
    const fs = require('fs');

    const fRead = fs.createReadStream(oldPath);
    const fWrite = fs.createWriteStream(newPath, {flags: 'w+', defaultEncoding: 'utf8'});

    const objReadLine = readline.createInterface({
        input: fRead
    });

    var ret = {};

    objReadLine.on('line', line => {
        line = line && line.trim();
        if( !line.includes(":before") || !line.includes("content") ) return;
        var keyMatch = line.match(/\.(.*?):/);
        var valueMatch = line.match(/content:.*?\\(.*?);/);
        var key = keyMatch && keyMatch[1];
        var value = valueMatch && valueMatch[1];
        value = parseInt(value, 16);
        key && value && (ret[key] = value);
    });

    objReadLine.on('close', () => {
        console.log('readline close');
        fWrite.write(JSON.stringify(ret), 'utf8');
    });
};

gen();

創建iconSets需要的東西都準備好了,開始創建吧。

/*iconfont.json*/
{
  "icon-comments":  59035,
  "icon-close": 59034
}
/*iconSets.js*/

import createIconSet from 'react-native-vector-icons/lib/create-icon-set';
import glyphMap from './assets/fonts/iconfont.json';

const iconSet = createIconSet(glyphMap, "ica", 'iconfont.ttf');

export default iconSet;

/* componet.js*/
...
import Icon from './iconSets';
<Icon name='icon-comments' size={60} color="#4F8EF7" />

運行一下,看字體顯示出來了

image.png

項目相關代碼放在github上了,請移步react-native-iconfont-demo

如果有幫到你,請點個贊吧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容