封装组件,改变svg颜色,不使用插件的轻量解决方案

405 阅读1分钟

最近在nuxt3项目中,用到的图标需要改变颜色。在以往的vue项目中使用的是插件:svg-sprite-loader。由于本次项目本身就是轻量级的项目,不想下载太多插件,便想写一个轻量的组件改变svg颜色

思路:

1.本次主要使用css filter属性中的drop-shadow方法

  • 该方法就是给元素设置光影效果
  • drop-shadow的参数分别是:水平偏移量,垂直便宜,羽化半径,颜色
  • 比如:
  <img class="icon" src="./test.svg" alt="" srcset="">
  ...
body{
  background-color: lightyellow;
}
.icon{
  filter: drop-shadow(80px 80px 10px red);
}
  • 上面代码的效果是:

  • 如果我们把羽化半径设置为0,那么效果是这样:
filter: drop-shadow(80px 80px 0px red);

  • 这样就实现了图标改变颜色的效果

2.替换img图片

  • 再隐藏img图标,把通过css生成的图标放在img的位置上,就完成图标变色效果了
<div class="wrap">
  <img class="icon" src="./test.svg" alt="" srcset="">
</div>
<style>
  body{
    background-color: lightyellow;
  }
  .icon{
    /* 88px是图标大小,想左偏移 */
    filter: drop-shadow(88px 0 0 red);
    /* 将img向右移出显示区域 */
    margin-left: -88px;
  }
  .wrap{
    /* 裁剪移出的img */
    overflow: hidden;
    display: inline-block;
    /* 设置为和图标相同大小 */
    width: 88px;
    height: 88px;
  }
</style>
  • 实现的效果:

封装组件

组件的适用范围:

  • 不需要更改svg的fill属性
  • 也可以更改png的图标(本次代码写死了.svg后缀)
  • 更改后的图标都是一个色

实现代码:

<template>
  <div class="svg-icon" :style="{ height: hei, width: wid }">
    <!-- ':src' 引入图片从根目录引入,写绝对路径无法找到图片 -->
    <img :src="`/assets/svg/${name}.svg`" 
      :style="{ filter: `drop-shadow(0 -${hei} 0 ${color})`, marginTop: hei }"
      alt="">
  </div>
</template>
<script lang="ts">
import { defineComponent, computed } from "vue"
export default defineComponent({
  props: {
    name: {  // 图片名称
      type: String,
      required: true,
      default: ''
    },
    color: {
      type: String,
      default: '#666' // 默认值
    },
    size: {
      type: [String,Number],
      default: ''
    },
    width: {
      type: [String,Number],
      default: '18px'  // 默认值
    },
    height: {
      type: [String,Number],
      default: '18px'
    },
  },
  setup(props) {
    const wid = computed(() => {
      return addUnit(props.size || props.width)
    })
    const hei = computed(() => {
      return addUnit(props.size || props.height)
    })
    // 添加像素单位
    const addUnit = (num:string|number):string=>{
      if (typeof num ==='number') return num + 'px'
      if (num.indexOf('px')===-1) return num + 'px'
      return num
    }
    return {
      wid,
      hei
    }
  }
})
</script>
<style scoped>
.svg-icon {
  overflow: hidden;
  display: inline-block;

}
img {
  width: 100%;
  height: 100%;
}
</style>

使用与效果:

<SvgIcon name="test" size="50" color="blue"/>