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

如果有帮到你,请点个赞吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容