视频链接:
片1
小程序原生的icon组件,只支持不到10个类型,那么如果我们需要更多的类型怎么办?如何实现图标的自定义?在阿里巴巴的图标网站上,有上百种甚至更多个图标,都是可以免费使用的,我们可以把这些图标用于小程序当中吗?答案肯定是可以的。
有人说图标不够用,可以直接使用图片。
使用图片也是可以的,但是这会有三个问题。一,图片在文本里面不方便布局;二,图片不能伸缩,放大之后会变虚有锯齿;三,图片需要在本地或网络上存储,使用起来不如图标只使用一个名称那么方便。
这节课我们就看一看,如何自定义实现图标,再了解一下自定义图标都有哪些方案。
片2
我们看一下,上面是微信小程序官方 icon 组件的文档网址。下面是这个组件的示例代码。这个组件属性是很简单的,一共只有三个属性:
1,type表示图标类型,目前只支持9种。
2,size表示大小,支持两种单位,rpx与px。如果值是数值类型,就是在默认使用px单位。rpx 是responsive pixel的简写,是屏幕自适应单位。rpx把屏幕分为750个单位,每个单位是1/750。在iPhone6机器上,屏幕宽度是350px,那么每个rpx就等于0.5个pixel。在iPhone6机器上,如果将size的值设置为60rpx,和30或30px,效果是一样的。
3,color是颜色样式,和css里面的color值定义是一样的
这里有一个关于color属性的问题需要注意,当我们改变一个图标的颜色时,我们改变的是什么呢?
改变的其实是它的所有像素的颜色。因为本质上图标它是一个像素的结合,为了更好的说明这个问题,我们看一段代码。
片3
上面是代码,下面是运行效果。第一行代码,当我们没有给组件设置背景样式的时候,图标中间那个对勾是白色的,但其实这个白色不是图标的颜色。第2行代码,当我们设置了背景颜色为灰色时,我们看到那个中间的对勾变成了灰色。也就是说,图标它中间那个部分是镂空的,我们说color改变的是图标所有像素的颜色,其中是不包括中间镂空的那个部分的。
接下来我们看相关问题。
片4
这是开发者社区上的一个问题,答案是可以的。图标之所以作为一个独立的组件存在,就是方便它和文本放在一起布局。具体的代码及运行效果,可以查看这节课的源码。
片5
在html中是没有icon标签的,小程序基于浏览器引擎渲染,那么它的icon组件是怎么实现的呢?
简单总结一下,大概有五个方案
第一种方案,使用图片。这是最简单粗暴的方法,每个图标对应一个图片。但是这种方法有三个明显的缺点:一,如果图标多的话,会造成大量http请求;二,不方便修改颜色;三,图标放大会变虚。
第二种方案,使用精灵图。
什么是精灵图?
这是一个字译。精灵图的英文叫Sprites,Sprite有精灵的意思,所以翻译成中文就是精灵图了。更确切的意译,应该是连续图片集。
精灵图是把一组图片以非重叠、最小化分布的方式,排列成一张图片,在加载的时候只加载一次,这就减少了http请求。
片6
看一下,这就是一张精灵图。它的信息描述的是一个爆炸效果,通过控制每次显示的纵横起点坐标及区域大小,就可以展示一个爆炸动画了。将这种技术应用于图标也是可以的。
在使用的时候,通过背景图片的定位和裁剪,只渲染图片的一小片区域。我们看一下示例代码:
片7
在这个代码中,background样式指定的是背景图片的地址及位置,因为这里是wxss样式,只能使用网络图片,不能使用本地图片。后面的位置信息之以为是负数,因为它们不是我们要展示的小区域在背景图中的位置,而是背景图片要向左上角方向移动的距离。
第三种方案,使用css样式绘制。
这也是一种方案,并且确实有人在使用。css本身有丰富的表现能力,是可以绘制图像的。举一个简单的例子:
片8
在这个代码中,是使用一个类样式,及一个伪无素样式完成了一个close图标的绘制。
这种方案每个图标都需要手写css样式代码,劳动量大。这种图标并不是字符,每个图标在绘制时需要统一一个中心点,否则使用时控制位置就比较麻烦。除了位置,大小与颜色也不方便控制。这并不是一个好的图标方案。
第四种方案,使用矢量字体。
前面的诸如http请求过多,图片变虚,不方便控制颜色等这些问题,在矢量字体方案中都得到了良好的解决。
当浏览器渲染一个汉字的时候,英文字符也是一样的,首先看font-family样式,确定需要使用的字体名是哪一个,由字体名确定使用电脑里的哪个字体文件渲染;接着以汉字的unicode在字体文件里查找对应的字符信息,每个unicode编码在字体文件中都有一个唯一对应的字符描述信息。
字体类型有两类:点阵字体和矢量字体。现在使用最广泛的是矢量字体。矢量字体又大概为分为三类:
1,Adobe主导的Type1
2,Apple和Microsoft主导的TrueType
3,Adobe、Apple和Microsoft三家主导的开源字体OpenType
在矢量字体文件里,每个unicode仅是编码的索引。每个字符描述信息是一个几何矢量绘图描述信息,以Type1为例,它使用三次贝塞尔曲线来描述字形,TrueType则使用二次贝塞尔曲线描述字形。由于矢量字体是绘制出来的,所以它可以实时填充任意颜色,可以无极缩放而没有锯齿。
回到我们的矢量字体图标方案上来。既然字符可以在字体文件里定义,图标为什么不可以呢?我们可以定义任何一个矢量图形,与一个unicode对应,哪怕这个unicode在其它字体中已经被使用过也没有关系。只要使用的是这个字体、这个文件,渲染出来就是我们提交的矢量图形效果。
阿里巴巴的图标网站iconfront.cn,不仅提供常用图标下载,还提供自定义矢量图标字体的生成与下载。我们可以在这个网站上搜索自己想要的图标、在线编辑,并下载样式文件,然后在小程序里使用。
片9 代码与运行效果
在这个代码中,@font-face是一种css模块,它可以将我们自定义的web字体,嵌入到应用当中。font-family样式,指定这个字体名为iconfont,这个名字是可以自定义的。.iconfont是我们声明的类样式,在这个类中指定使用新声明的iconfont这个字体。
.icon-sun是我们借助伪元素before实现的自定义图标样式,应用这个样式,代表使用自定义字体文件里的,unicode为e603的字符信息进行渲染。而e603对应的字符,是我们在iconfront网站上自定义设置的。
我们注意到在@font-face里面,有许多字体源。eot是微软IE浏览器专用的OpenType字体类型。ttf是TrueType字体。woff与woff2是移动开发专用的矢量字体格式,是对三种矢量字体格式的再封装,据说目前已被 93%以上的浏览器支持了。之所以链接这么多字体文件源,是为了兼容不同的浏览器宿主环境。
浏览器会选择自己支持的格式,从列表中的第一个开始尝试加载,一旦获得一个可用格式,它就不会再尝试其他文件了。在小程序里,建议使用 TTF 和 WOFF格式,WOFF2 在低版本的iOS上会不兼容。
第五种方案,使用svg矢量文件。
使用矢量图制作软件,可以直接导出svg格式的矢量图片,这是一种有路径绘制信息的文本描述文件。例如使用Sketch,就可以导出svg文件。但Sketch导出的文件有冗余信息,例如注释等,不简洁。Sketch是收费软件,可以免费试用。使用在线的Photoshop编辑器()也可以编辑、导出svg文件,这个工具不用安装,还可以免费使用,可以满足大多数图标编辑需求。
在iconfront网站上检索到的或编辑的图标,单击下载,选择svg格式,也能下载svg格式的文件,并且这个文件的内容是简洁的。我们拿这个文件找一个image2base64工具,将文件内容转为base64的字符串,然后就可以在小程序里使用这个base64字符串作为图片源,这样就可以实现自定义图标了。看一下这个代码:
片10
最上面是image转base64的一个工具网址,中间是代码,下面是运行效果。在这个代码中,width和height之所以设置为200,是因为这个图标本身的尺寸就是200,这个信息在下载的svg文件里可以看到。
这是使用svg作为图片源的方式。还有一种是使用canvas绘制svg信息,但这种绘制用于制作动画还可以,用于自定义图标有点大材小用。
片11
上面是腾讯团队编写的可以将svg信息绘制成图像的cax引擎,它的原理是基于canvas绘制。下面的链接是介绍如何使用它的,有兴趣可以看一下。
以上就是实现自定义图标的五种方案。其中以第四种方案,基于阿里巴巴图标网站iconfront的方案最为简单有效。在开发中首先推荐使用这种方案。
下面看第3个问题。
片12
有人以为这可能是由于安全域名导致的,就是说字体文件的url没有位于安全域名内,访问被拒绝了。其实不是的,在wxss内加载图片及字体文件资源,是允许使用外域的地址的。
如果图标是自定义实现的,要检查一下机型及嵌入的字体文件类型,可能是兼容性引起的。在小程序中,推荐使用ttf和woff格式的字体。如果使用的是这两种类型,问题仍然存在的话,可以考虑换svg格式的数据嵌入。
片13
直接可以从weui.io这个网站通过谷歌开发者工具查看源码找到资源地址,然后下载。或者在微信的官方文档上下载。
(见上面链接)这是Sketch设计稿的下载地址,包括了weui组件库中的所有设计元素。
上面是本课源码。下载时如果提示登陆,使用微信扫码就可以下载了。
最后给大家留一个作业:从iconfront.cn搜索两个图标,以自定义的方式用在自己的小程序项目中。答案我们下节课揭露。
好,今天这一课就到这里,主要介绍了icon组件,及几种自定义实现图标的方案,下一课我们介绍progress组件,及如何自定义实现一个环形进度条。有问题欢迎留言讨论。
2020年5月14日