阿里iconfont挂了之后...小程序项目内维护图标的方案
最近项目迭代要加些页面,在蓝湖上下好图标素材准备上传到阿里iconfont上去。打开网站一看,好家伙,维护中…
使用方法和源码可以直接跳到 我的方法-使用。
前言
但我还是菜鸟的时候,公司的老前端和我说,我挂了阿里都不会挂,叫我放心用阿里的iconfont。现在阿里挂了,图标没法换,项目没发上线,要是被老板发现了,我也要一起挂了。
怎么办?突然想到了后台管理项目的图标管理方案,使用svg雪碧图。可是看了一下小程序的文档,小程序不支持svg标签,只能使用image载入src,这样的话就不能改颜色了…
这可不行,于是百度了一下,找到了2种方法。
百度来的方法
drop-shadow
使用css的drop-shadow
属性可以让我们给一个元素添加长得一摸一样的阴影,给阴影设置个颜色,把源元素隐藏起来只显示阴影不就达到换色的效果了吗。
emmm,试了一下,在开发者工具上果然可以,拿起iphone调试一看,一片空白….
为什么呢?搜索了一下社区,原来在ios上,如果把源元素隐藏了,阴影也不会被渲染。还好底下评论有解决方案,给加一个transform:translateZ(0);
强制gpu渲染。于是又试了一下,效果也不太理想,ios上有的图标出来了,有的出不来,android上是彻底出不来了。
那只能换个思路,源元素隐藏阴影出不来,这样的话网上有人通过设置border-right
使源元素始终显示,这样行不行呢?试了一下,android正常了,ios还是上一个方法的样子,有的出的来,有的出不来。排查了一下这些图标,出的来的都是线条贴边占满整个svg的图标,现在我又不能控制ui提供svg是啥样,设置阴影换颜色的方法只能放弃了。
mask
css里可以给元素设置一个mask然后改变背景颜色可以曲线实现svg换色
1 | .colorful { |
实际试了一下,还是老样子,android可以,ios不行。
我的方法
这下就难住了,真的要提桶跑路了吗。绝望的时候看了一下之前的小程序使用阿里iconfont方案mini-program-iconfont-cli,发现作者的这个方案其实就是拉取存在阿里iconfont的svg,读取修改svg的字符串,通过组件传入颜色用js改变svg字符串的颜色属性,最后内联到标签的background-image
上
1 | <!--close-circle--> |
有了思路就好说了,剩下的都是体力活,不过在开始编码之前先要明确一下需求。
需求
- 兼容项目之前的iconfont组件写法,最好能做到无痛平替。
- 兼容原生小程序和uniapp。
- 图标能传入高度(size),且能根据高度算出宽度,使其能保持宽高比。
- 传入颜色(color)时能改变图标颜色,不传入不改变颜色使其保持源图标源颜色。
编写过程
首先为了兼容原生小程序和uniapp,就必须得使用原生的小程序组件来写。在uniapp项目的src/wxcomponents
下新建一个iconfont原生组件。
上面的需求有几个prop参数,size默认给个18、color颜色、还有一个就是让组件做到用的是哪个图标的name。在data里需要一个变量svgStyle存处理好的backgroundImage
字符串和宽高。
1 | Component({ |
wxml里就很简单,放个容器标签就行
1 | <view class="svg_icon" wx:if="{{svgStyle}}" style="{{svgStyle}};"></view> |
wxss里设置组件host为行内元素就行
1 | :host{ |
当这个组件加载时首先要通过小程序的api和图标name读取放在项目内的svg字符串,然后做一些处理。这里我把svg图标都放在uniapp项目下的src/static/icon
中。
1 | { |
然后通过svg自带的宽高和传入的size得倒页面中实际的宽度,并替换掉源svg中的宽高属性。宽高一般在svg标签上,用正则提取。
1 | // ... |
接下来需要处理svg的颜色。svg的颜色属性fill一般放在svg标签上,如果有多个路径,可能也会在别的标签上,为了保险起见,我们都替换掉。而且还要移除一些影响展示效果的属性,如opacity什么的。根据需求不传color的时候不改颜色,这里要做一下判断处理。
1 | // ... |
最后需要把标签转译一下放到backgound-image
里,并加上宽高苏醒设置到svgStyle
上。最后就大功告成了。
1 | // ... |
使用
源码地址 mp-svg-icon
首先将图标放在static目录的img文件夹下
- unapp 的static在src下
- 原生小程序的static在项目根目录下
下载好组件源码后,uniapp一定要放在src/wxcomponents
里,原生无所谓。
想全局使用原生组件的话需要在page.json里注册组件
uniapp在globalStyle
的usingComponents
注册
1 | { |
原生小程序直接在usingComponents
注册
1 | { |
最后在页面中使用就行
1 | <view> |
需要注意的是size为px单位,如果是蓝湖750的设计稿需要除以2。
最后
一点想法
- 小程序为什么这么麻烦?
- 阿里iconfont不可靠,就算好了也不敢用了。
阿里iconfont挂了之后...小程序项目内维护图标的方案