You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

126 lines
2.6 KiB

<template>
<div
class="svg-icon-wrapper"
:style="{ width: size + 'px', height: size + 'px' }"
@click="handleClick"
@mouseenter="isHovered = true"
@mouseleave="isHovered = false"
>
<div
class="svg-icon"
v-html="svgContent"
:style="{
'--icon-color': isHovered ? hoverColor : color,
'--icon-hover-color': hoverColor
}"
></div>
</div>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
// SVG文件路径(必须)
path: {
type: String,
required: true,
validator: value => value.endsWith('.svg')
},
// 图标大小(像素)
size: {
type: Number,
default: 24
},
// 默认颜色
color: {
type: String,
default: '#333333'
},
// 悬停颜色
hoverColor: {
type: String,
default: '#409EFF'
},
// 禁用状态
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
svgContent: '',
isHovered: false
}
},
watch: {
path: {
immediate: true,
handler: 'loadSvg'
}
},
methods: {
async loadSvg() {
try {
// 使用动态import加载SVG文件
const response = await fetch(this.path)
if (!response.ok) throw new Error('SVG加载失败')
this.svgContent = await response.text()
// 如果SVG中有fill属性,替换为currentColor以便CSS控制
this.svgContent = this.svgContent.replace(/fill="[^"]*"/g, 'fill="currentColor"')
} catch (error) {
console.error('加载SVG图标失败:', error)
this.svgContent = ''
}
},
handleClick(event) {
if (!this.disabled) {
this.$emit('click', event)
}
}
}
}
</script>
<style scoped>
.svg-icon-wrapper {
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s;
}
.svg-icon-wrapper:hover {
opacity: 0.8;
}
.svg-icon {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: var(--icon-color);
transition: color 0.3s;
}
.svg-icon:hover {
color: var(--icon-hover-color);
}
.svg-icon-wrapper[disabled] {
cursor: not-allowed;
opacity: 0.5;
}
.svg-icon >>> path {
fill: currentColor;
}
.svg-icon >>> circle {
fill: currentColor;
}
</style>