小程序中icon svg组件实现思路(支持换色和大小)
站长
· 阅读数 18
我们都知道icon在H5中可以使用unicode ,svg方案实现,通过iconfont我们可以很快的封装组件使用。unicode方案可以直接使用,但微信小程序中不支持svg标签,所以不能使用iconfont提供的svg方案,这里的需作一些调整。
预先看一下最终组件使用效果
<base-icon name="print" size="40rpx" color="red"></base-icon>
<base-icon name="print" size="80rpx" color="blue"></base-icon>
<base-icon name="share" size="80rpx" color="blue"></base-icon>
1.通过Image标签
通过微信小程序Image API我们了解到Image Src支持Svg格式,这样就好办了,我们直接下载Iconfont的svg文件,通过url引用就可以使用svg图标了。
<image
class="svg"
:style="{
'--svg-width': size,
}"
:src="svgData"
mode="scaleToFill"
></image>
2.如何支持换色?
首先需要把svg图标是去除底色,可以通过iconfont批量设置中去色。
2.1 Base64方案
把Svg的转成Base64,通过编码解码Base64,替换fill属性达到预想效果,可以通过提前定义好各个Svg的字符串内容 ,通过转Base64引入,解码Base64后,通过正则替换fill属性后转Base64后使用
import { encode, decode } from 'js-base64';
const BASE64_PREFIX = 'data:image/svg+xml;base64,';
export const getColorSVG = (svgBase64, color) => {
try {
svgBase64 = svgBase64.substring(
svgBase64.indexOf(',') + 1,
svgBase64.length
); // 取出第三部分
const svg = decode(svgBase64); // 解码得到svg代码
console.log('decode base64', svg);
if (/<svg /.test(svg)) {
// 先简单判断是一下否是一个svg
let newSvg;
if (/fill=".*?"/.test(svg)) {
newSvg = svg.replace(/fill=".*?"/, `fill="${color}"`); // SVG有默认色
} else {
newSvg = svg.replace(/<svg /, `<svg fill="${color}"`); // 无默认色
}
console.log('getColorSVG', newSvg);
return BASE64_PREFIX + encode(newSvg); // 替换完之后再组合回去
}
} catch (err) {
console.log('getColorSVG error: ', err);
}
return '';
};
赋值Svg代码:
2.2 二进制方案
二进制方案是通过微信FileSystemManager API,读取文件Svg Base64,后续与方案一同理。这样好处节省流程,便于后续开发。直接在/static/images/icons/目录下添加svg文件即可。
import { encode, decode } from 'js-base64';
// 默认svg文件所在文件夹
const svgDor = `/static/images/icons/`;
// 定义一个方法src数据方法
export const getSvgBase64 = (icon, color) => {
let path = `${svgDor}${icon}.svg`;
let str = '';
try {
// 使用微信等文件读取类
const fs = wx.getFileSystemManager();
// 先读取文件,decode再解析成svg,替换fill属性,再encode,得到新的base64
const svg = decode(fs.readFileSync(path, 'base64'));
let newSvg;
if (/fill=".*?"/.test(svg)) {
newSvg = svg.replace(/fill=".*?"/, `fill="${color}" `); // SVG有默认色,注意结尾跟一个空格
} else {
newSvg = svg.replace(/<svg /, `<svg fill="${color}" `); // 无默认色,注意结尾跟一个空格
}
// console.log('newSvg', /fill=".*?"/.test(svg), color, newSvg);
str = `data:image/svg+xml;base64,${encode(newSvg)}`;
} catch (e) {
console.log('read svg fail: ', e);
}
return str;
};
2.3封裝组件
这里以uniapp为例,你可以转对应的小程序效果是一样的
<template>
<image
class="svg"
:style="{
'--svg-width': size,
}"
:src="svgData"
mode="scaleToFill"
></image>
</template>
<script>
import { getSvgBase64 } from './file';
export default {
props: {
name: String,
color: {
type: String,
default: '#000',
},
size: {
type: String,
required: true,
},
},
// watch: {
// color: 'changeColor',
// },
computed: {
svgData() {
// console.log('BaseIcon#$###', getSvgBase64(this.name, this.color));
return getSvgBase64(this.name, this.color);
},
},
methods: {
changeColor() {},
},
};
</script>
<style>
.svg {
width: var(--svg-width, 48rpx);
height: var(--svg-width, 48rpx);
}
</style>
下载Svg文件:
引用组件示例:
<base-icon
name="print"
size="44rpx"
:color="COLOR_HEX.primary"
></base-icon>
参考链接: