组件描述
通过图标名称加载对应svg,size参数调整图标大小,color参数调整图标颜色
解决思路:
- 存svg获svg,对象方式
- 正则替换svg的fill值,不改变源文件,通过base64直接加载
- 缓存svg源文件,避免重复读取文件
一、手动上传svg文件
将项目需要的svg文件保存到static目录下,通过svg.js(如下图)将icon名称和路径映射,方便后续通过名称加载svg文件
提示:可以考虑在main.js文件里设置全局对象,不使用icon组件在不同页面也可以访问svg文件
import svg from './utils/svg.js'
Vue.prototype.$svg = svg;
二、使用Image组件加载图片资源
1.设置image
<image class="icon" :style="{ width: `${size || 18}px`, height: `${size || 18}px` }" :src="svgData"mode="scaleToFill" />
2.组件参数
props: {title: {type: String,default: '',required: true,},size: {type: String,default: '18',},color: {type: String,default: '#999',},},
3.读取缓存对象
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文件,写入缓存对象
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
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;},
引用
<icon :title="item.icon" size="20" :color="currentTab === index ? '#000000' : '#999999'"></icon>
参考: 动态设置svg颜色