likes
comments
collection
share

小程序中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>

小程序中icon svg组件实现思路(支持换色和大小)

1.通过Image标签

小程序中icon svg组件实现思路(支持换色和大小)

通过微信小程序Image API我们了解到Image Src支持Svg格式,这样就好办了,我们直接下载Iconfont的svg文件,通过url引用就可以使用svg图标了。

<image
    class="svg"
    :style="{
      '--svg-width': size,
    }"
    :src="svgData"
    mode="scaleToFill"
  ></image>

2.如何支持换色?

首先需要把svg图标是去除底色,可以通过iconfont批量设置中去色。

小程序中icon svg组件实现思路(支持换色和大小)

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代码:

小程序中icon 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文件:

小程序中icon svg组件实现思路(支持换色和大小)

引用组件示例:

<base-icon
  name="print"
  size="44rpx"
  :color="COLOR_HEX.primary"
></base-icon>

参考链接:

github.com/daofeng-cod…