组件描述
通过图标名称加载对应svg,size参数调整图标大小,color参数调整图标颜色
解决思路:
- 存svg获svg,对象方式
- 正则替换svg的fill值,不改变源文件,通过base64直接加载
- 缓存svg源文件,避免重复读取文件
一、手动上传svg文件
将项目需要的svg文件保存到static目录下,通过svg.js(如下图)将icon名称和路径映射,方便后续通过名称加载svg文件
提示:可以考虑在main.js文件里设置全局对象,不使用icon组件在不同页面也可以访问svg文件
typescript
import svg from './utils/svg.js'
Vue.prototype.$svg = svg;
二、使用Image组件加载图片资源
1.设置image
html
<image class="icon" :style="{ width: `${size || 18}px`, height: `${size || 18}px` }" :src="svgData"
mode="scaleToFill" />
2.组件参数
typescript
props: {
title: {
type: String,
default: '',
required: true,
},
size: {
type: String,
default: '18',
},
color: {
type: String,
default: '#999',
},
},
3.读取缓存对象
typescript
watch: {
color(newVal) {
let svgData = this.svgCache[this.$svg[this.title]];
if (svgData && newVal) {
let newFile = this.changeColor(svgData, newVal);
this.svgData = that.svgToBase64(newFile)
}
}
},
三、读取svg文件,正则替换fill的color值
动态更换svg颜色,原理就是修改svg的fill属性
1.读取svg文件,写入缓存对象
typescript
getSvgFile(src) {
//读取svg文件
let that = this;
const fs = wx.getFileSystemManager();
fs.readFile({
filePath: src,
encoding: 'UTF-8',
position: 0,
success(res) {
let data = res.data;
if (data) {
if (data instanceof ArrayBuffer) {
// 有些设备数据格式是ArrayBuffer需要转换成svg字符串
that.svgCache[src] = that.arrayBufferToStr(data);
} else {
that.svgCache[src] = data;
}
let newFile = that.changeColor(that.svgCache[src], that.color)
that.svgData = that.svgToBase64(newFile);
}
},
fail(res) {
console.error(res)
}
})
},
changeColor(data, color) {
// console.log(data);
let newSvg;
if (/fill=".*?"/.test(data)) {
newSvg = data?.replace(/fill=".*?"/g, `fill="${color}"`); // SVG有默认色
} else {
newSvg = data?.replace(/<svg /g, `<svg fill="${color}" `); // 无默认色
}
return newSvg
},
2.使用Uint8Array进行文件数据转换
替换color值的svg字符串是容易转换成base64,在不改动svg源文件情况下,image可以直接加载处理后的base64
typescript
arrayBufferToStr(buffer) {
let str = '';
const uint8Array = new Uint8Array(buffer);
for (let i = 0; i < uint8Array.length; i++) {
str += String.fromCharCode(uint8Array[i]);
}
return str;
},
svgToBase64(svg) {
const utf8 = new Uint8Array(svg.length);
for (let i = 0; i < svg.length; i++) {
utf8[i] = svg.charCodeAt(i);
}
// 使用Buffer进行Base64编码
const base64 = wx.arrayBufferToBase64(utf8.buffer);
// 返回带有data URI前缀的Base64字符串
return 'data:image/svg+xml;base64,' + base64;
},
引用
html
<icon :title="item.icon" size="20" :color="currentTab === index ? '#000000' : '#999999'"></icon>
参考: 动态设置svg颜色