在项目开发过程中,以svg图片引入时,会遇到当hover态时图片颜色修改的场景,我们可能需要去引入另一张不同颜色的svg图片,或者用css方式修改,为了方便这种情况,需要封装svg组件来自定义宽高和颜色,优化使用。
SVG (Scalable Vector Graphics) 是一种基于 XML 的矢量图形格式,用于描述二维图形和图像。与传统的栅格图像(如 JPEG、PNG)不同,SVG 使用数学公式来定义图形,因此可以无损地进行缩放和放大,并保持图像的清晰度和质量。
以下是一些关于 SVG 的特点和用途:
SVG 图像可以在各种图像编辑器(如 Adobe Illustrator、Inkscape)中创建和编辑,并嵌入到 HTML 文件中进行展示。通过 CSS 和 JavaScript,SVG 图像可以与网页的其他元素和样式进行集成和调整。
vite-plugin-svg-icons 是一个 Vite 插件,用于在 Vite 2 项目中方便地使用 SVG 图标。它可以自动将 SVG 图标文件转换为 Vue 组件,并且提供了一些配置选项来自定义生成的组件。
具体来说,vite-plugin-svg-icons 提供了以下功能:
npm install vite-plugin-svg-icons -D
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import path from "path";
export default defineConfig({
plugins: [
vue(),
createSvgIconsPlugin({
// 指定目录(svg存放目录)
iconDirs: [path.resolve(process.cwd(), "src/assets/svgs")],
// 使用 svg 图标的格式(name为图片名称)
symbolId: "icon-[name]",
//生成组件插入位置 只有两个值 boby-last | body-first
inject: 'body-last'
})
],
})
import 'virtual:svg-icons-register';
<template>
<svg
aria-hidden="true"
:width="width"
:height="height"
:fill="color"
>
<use :xlink:href="`#icon-${name}`"/>
</svg>
</template>
<script setup lang="ts">
defineProps<{
name: string,
width: string,
height: string,
color?: string
}>();
</script>
<template>
<SvgIcon name="close" width="24" height="24"></SvgIcon>
</template>
<script setup>
import SvgIcon from "@/components/svg-icon/svg-icon.vue";
</script>
问题:
● vite-plugin-svg-icons插件自动封装的组件只能选择插入到body前或后
如果项目中某个部分使用了shadow-dom,由于样式隔离的问题,使用svg组件不显示
解决:通过id(如上图为__svg__icons__dom)获取插件自动封装的组件dom元素,插入到shodaw-dom下即可解决
● 原本svg图片的宽高失效,需要重新设置宽高,而且不能直接改变颜色,想要改变颜色必须修改原svg图片,将其fill属性删掉或者置为空(“”)
CSS 中的 mask 属性用于创建遮罩效果,它可以通过另一个图像或者 SVG 图像来定义遮罩的形状。mask 属性可以应用于任何可视元素,并将遮罩应用于元素的内容和背景。
mask属性详情
<template>
<div
class="bot-svg-icon"
:style="svgStyle"
></div>
</template>
<script setup lang="ts">
import {computed, ref} from 'vue';
const props = withDefaults(defineProps<{
url: string,
width: string|number,
height: string|number,
color?: string,
}>(), {
color: 'var(--bot-color-black-1)',
});
const svgStyle = computed(() => ({
width: props.width + 'px',
height: props.height + 'px',
backgroundColor: props.color
maskImage: `url(${props.url})`,
}));
</script>
<style scoped>
.bot-svg-icon {
display: inline-block;
mask-repeat: no-repeat;
mask-size: cover;
}
</style>
问题:原本的svg图片宽高失效,需要重新设置宽高,但是可以不用修改原svg文件就可改变颜色。
动态导入地址导致的问题:在本地图片显示正常,打包后部署,图片不能显示,如下例:
//第一种情况:在html中时候,本地运行和打包后线上运行都ok。
<img src="@/assets/close.svg" alt="" >
//第二种情况:用动态数据,本地运行ok,打包后线上运行不显示
const path = "@/assets/close.svg";
// 如果是vue3+webpack可以使用require引入,但vite没有require
<img :src="path">
// 第三种情况:用动态数据且本地和线上访问都可显示
const path = new URL("@/assets/close.svg", import.meta.url).href;
<img :src="path">
// 第四种情况:用动态数据且本地和线上访问都可显示
import close from "@/assets/close.svg";
<img :src="close">
参考vite官方文档:静态资源处理