最近在使用
ionic3
和Angular
开发一款App。开发体验还是挺好的。期间遇到如何在项目中使用自定义图标字体文件的问题,经过研究,找到了一个解决方法,记录一下。
问题描述
ionic
项目提供了一套丰富的图标库,在ionic3中也进行了升级。虽然很实用,但是在实际项目中,还是需要根据视觉稿来增加图标。
通常,我们都会使用@font-face
导入自定的字体文件。那么我们怎么将这些图标融入到ionic3的项目中去呢?
下面以ionic3
中的tabs
组件作为例子,提出一种解决方式。
话说问题是解决了,但是看起来其实并不优雅,不过能解决问题。=.=||
理解ionic3
中的图标组件
ionic icon的使用
ionic3中提供图标使用的方式有不少,其中非常重要的组件是:ion-icon
,基本的使用方法如下:
<ion-icon name="heart" ></ion-icon>
name
属性是图标的名称,这样ionic就会在这个标签处渲染生成一个图标。其他的用法,还有:
根据不同的设计风格使用不同的图标(
ios
ormd
-->Material Design)设置图标的不同状态
作为特定组件的属性
ionic也为自己的图标库提供了一个预览的页面,Ionicons
tabs
组件中使用icon
在例子中,tabs
组件使用图标的方式,是这样的:
<ion-tabs>
<ion-tab tabIcon="heart" [root]='tabPage1'></ion-tab>
<ion-tab tabIcon="alarm" [root]="tabPage2"></ion-tab>
<ion-tab tabIcon="at" [root]="tabPage3"></ion-tab>
</ion-tabs>
通过设置tabIcon
属性,就可以使用图标库中指定的图标。
仔细看一下渲染后的html结构,你会发现,ion-tab
其实是在模板中加入了ion-icon
组件:
那么,ionic是如何根据一个name
属性,就链接到他的图标库中的图标呢?
ionic使用图标的原理
由于ionic3使用了Angular作为框架开发,因此ion-icon
要么是组件,要么是指令。所以我们看看它的源码,是如何实现图标文件的使用的。
源码传送门:ion-icon
从源码中我们可以看到,ionic把ion-icon
定义为一个指令,有三个步骤:
进行平台风格(
ios
、md
)判断和状态的判断。-
根据判断的结果,将输入的图标名称,进一步组合成为如下形式的格式化文本
ion-{平台风格标识}-{图标名}-{修饰}
将上一步得到的格式文本,添加到元素的
class
属性中。
至此,也很好理解了,通过一个css类,就可以使用图标库中的字体定义(@font-face
)
ionic将自己的图标字体的scss文件放在ionicons.scss中,定义字体名称为Ionicons
。
而图标库则成为另外一个git项目,相关的类型放在ionicons-icon.scss中。在github
中打开源码文件,ctrl+f
搜索heart
,可以看到css是这样的:
.ion-ios-heart:before { content: "\f443"; }
.ion-ios-heart-outline:before { content: "\f442"; }
通过伪元素,指明了对应的图标字体。-outline
后缀指明的是轮廓形状的图标。
知道了这些,我们就可以自定义字体文件和css类,从而让ion-icon
也支持我们自定义的图标了。
准备工作
图标文件
图标文件,一般大家都会用illustrator矢量设计软件设计,然后导出.svg
格式的文件。
要打包成字体文件,也有不少工具,常用的是阿里出品的 iconfont。具体使用方法,网站上讲解的非常清楚,这里就不多说了。
当你上传自己的图标svg
文件,导入项目,下载完成后,会得到一堆文件。
有3种方式,可以使用图标:
unicode
最原始的方式,但是兼容性好。fontclass
使用伪元素和css类的方式,与ionic一样,兼容限制ie8+symbol
唯一支持保留颜色的方式,但是兼容性需要考虑(支持svg的设备和浏览器可以)
在例子中,我们选用fontclass
足矣。
部署文件
将生成的字体文件拷贝到ionic项目src
目录下assets
中(具体目录根据项目的要求,这里只是例子)的fonts
目录里。
然后,书写一份.scss
文件,内容如下:
@import "ionicons-variables";
$jpicons-font-path: $font-path !default;
@font-face {
font-family: "jp-icon";
src: url('#{$jpicons-font-path}/iconfont.eot?t=1493779389504'); /* IE9*/
src: url('#{$jpicons-font-path}/iconfont.eot?t=1493779389504#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('#{$jpicons-font-path}/iconfont.woff?t=1493779389504') format('woff'), /* chrome, firefox */
url('#{$jpicons-font-path}/iconfont.ttf?t=1493779389504') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('#{$jpicons-font-path}/iconfont.svg?t=1493779389504#jp-iconfont') format('svg'); /* iOS 4.1- */
}
.jp-icon {
font-family:"jp-icon" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
字体名和路径等等,根据需要自定义就可以了。
下一步,就可以定义自己的类名了,由于例子使用Material Design
风格,因此,定义如下:
.ion-md-jpicon__evalTab:before { content: "\e64e"; }
.ion-md-jpicon__recTab:before { content: "\e650"; }
.ion-md-jpicon__storeTab:before { content: "\e651"; }
名字的定义按照之前提到的格式化文本的形式就可以,这里由于想说明清楚的原因,我把名字定义的略复杂了一点,实际使用中可以按自己需要修改。
最后别忘了一点,在你的基础样式表,比如:app.scss
中导入这个scss
文件。
@import '../assets/fonts/jpicons.scss';
无论怎样,当你准备好这些文件时,下一步就可以使用自己的图标字体啦。
使用字体
在tabs
组件中,可以很方便的使用定义好的字体:
<ion-tabs class="jp-tabs" >
<ion-tab tabIcon="jpicon__storeTab" [root]="store" tabTitle="精选推荐" tabUrlPath="store" >
</ion-tab>
<ion-tab tabIcon="jpicon__recTab" [root]="recommend" tabTitle="应用场景" tabUrlPath="recommend" >
</ion-tab>
<ion-tab tabIcon="jpicon__evalTab" [root]="evaluation" tabTitle="深度评测" tabUrlPath="evaluation" >
</ion-tab>
</ion-tabs>
在tabs组件的.scss
文件中,我们重新定义在该tabs组件下使用的字体名称:
.jp-tabs{
.tab-button{
&>ion-icon{
font-family:"jp-icon" !important; /*指定在当前组件中的ion-icon使用的字体名称*/
}
}
}
此外,如果有定义图标字体颜色的需求,简单粗暴的方式是:
.tabs-md .tab-button[aria-selected=true]{
color:$jp-color;
.tab-button-icon{
color:$jp-color;
}
}
当一个tab被选中时,ionic会修改对应组件元素上的aria-selected
,值是true/false
。
运行ionic serve
,查看渲染后的效果:
再看html代码,可以验证上面所讲到的内容。
总结
如果自定义组件和指令是不是也可以实现图标字体的使用?我想是可以的。
本文只是提供了一种方法而已,不太优雅,但是可以解决问题。好处是,可以使用ionic中的一些关于图标的功能,例如,在tabs
组件中,可以设置tabLayout
属性来决定图标和文字的布局关系,如果要自己开发布局等功能,当然可行,但是需要花费时间。作为一种实现,本文的介绍也算作一种方式吧。但作为研究和推敲原理,我想应该更深入的发现更好的方式。
个人能力有限,如果有什么错漏,请大家批评指正,之后会再补充内容。