评论

动态设置svg颜色

通过自定义组件,动态的设置svg图片的颜色,不用每种颜色svg都引入项目一次。

背景

小程序的想要使用不同颜色的svg只能通过引入多个svg文件。之前就有过动态改变svg颜色的需求,这几天看到也有其他同学想拥有这个功能。就想着能不能自己造一个。

解决方案

需求:
1.可以动态设置svg颜色。
2.最好不要改动svg源文件。
3.使用方便。

调查:
1.svg文件的颜色可以通过fill=“{color}”的值设置。所以基本思路就是,用正则替换改变color值,实现颜色的变化。

2.不想改变源文件,所以考虑以utf-8的格式读取svg文件,然后用正则替换后,将其转化为base64格式直接显示,而不是替换后写回文件。了解了一下,image已经支持base64。

3.为了使用方便,功能实现后,考虑做成自定义组件。

代码

代码部分并不复杂,就三步: 读取文件,正则替换, base64编码。其中base64编码部分使用Dorian大佬分享的工具,非常感谢!

  • 使用wx.getFileSystemManager()读取文件
    const fs = wx.getFileSystemManager()
    
    getSvgFile(src, color) {
    	let that = this;
    	fs.readFile({
    		filePath: src,
    		encoding: 'UTF-8',
    		position: 0,
    		success(res) {
    			let sourceFile = res.data;
    		},
    		fail(res) {
    			console.error(res)
    		}
    	})
    },
    
  • 正则替换(考虑到部分svg没有默认fill属性,所以在svg头部主动增加了fill属性)
    changeColor(sourceFile, color) {
    	let newSvg;
    	if (/fill=".*?"/.test(sourceFile)) {
    		newSvg = sourceFile.replace(/fill=".*?"/g, `fill="${color}"`);  // SVG有默认色
    	} else {
    		newSvg = sourceFile.replace(/<svg /g, `<svg fill="${color}" `); // 无默认色
    	}
    	return newSvg
    }
    
  • base64编码
    import { Base64 } from './base64.js';
    const base64 = new Base64()
    
    getSvgFile(src, color) {
    	let that = this;
    	fs.readFile({
    		filePath: src,
    		encoding: 'UTF-8',
    		position: 0,
    		success(res) {
    			let sourceFile = res.data;
    			let newFile = that.changeColor(sourceFile, color);
    			let svgBase64File = base64.encode(newFile);
    			that.setData({
    				svgData: 'data:image/svg+xml;base64,' + svgBase64File
    			})
    		},
    		fail(res) {
    			console.error(res)
    		}
    	})
    },
    
    

到这里主体功能完成,再封装成自定义组件就完工啦。自定义组件的代码片段可以自取:
https://developers.weixin.qq.com/s/GrQhtZmg7yCJ

使用方法及效果

1.打开代码片段,把svg文件夹复制到自己项目的component文件夹下

2.在需要引入svg的页面引入组件

3.使用svg标签,可以自定义宽高,和颜色,以及文件路径。

color也支持使用JS动态控制,实现颜色变化的效果。

4.目前就用了阿里icon的一些svg进行测试。有bug请多多反馈,也希望大家能提出更好的思路。

最后一次编辑于  2022-10-14  
点赞 7
收藏
评论

6 个评论

  • ⅴ
    2023-05-05

    对应了iOS真机不显示的问题:

    https://developers.weixin.qq.com/s/8gRJHYmK77Hv

    2023-05-05
    赞同 1
    回复 1
    • 三逝
      三逝
      11-12
      encoding改成 二进制 binary
      11-12
      回复
  • R_trAp
    R_trAp
    03-29

    和我之前的做法一样,当时还担心转canvas后有底色呢

    03-29
    赞同
    回复
  • Evan 一飞同学
    Evan 一飞同学
    03-25

    感谢分享

    03-25
    赞同
    回复
  • 程晓明
    程晓明
    03-21

    有些svg文件需要自己手动修改一下,不过好使

    03-21
    赞同
    回复
  • Hello World
    Hello World
    2023-05-02

    直接用fontawesome插件来不是更简单,可以填充颜色(Doutone双色),设置动画等

    2023-05-02
    赞同
    回复 1
    • ⅴ
      2023-05-05
      主要是不想引入太多svg文件。
      2023-05-05
      回复
  • K
    K
    2023-01-11

    真机上不显示,楼主有遇到这个问题吗

    2023-01-11
    赞同
    回复 5
    • K
      K
      2023-01-11
      已解决,打扰了
      2023-01-11
      回复
    • 翻斗一霸👑
      翻斗一霸👑
      2023-03-04回复K
      您好,我也有这个问题,请问您是怎么解决的呢?真机上安卓没问题,ios不显示
      2023-03-04
      回复
    • @Patrick Lee
      @Patrick Lee
      2023-03-27
      大佬,你怎么解决那个ios真机不显示的?
      2023-03-27
      回复
    • ...
      ...
      2023-03-27
      encoding改成 二进制  binary
      2023-03-27
      1
      回复
    • 三逝
      三逝
      11-12回复翻斗一霸👑
      encoding改成 二进制 binary
      11-12
      回复
登录 后发表内容