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.
 
 
 
 

175 lines
4.0 KiB

<template>
<div class="svg-icon-wrapper" :style="wrapperStyle" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<div class="svg-icon" v-html="svgContent" :style="{
'--icon-color': (hoverEffect || isActive) ? activeColor : defaultColor,
'--icon-hover-color': activeColor
}"></div>
<!-- :style="iconStyle" -->
</div>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
// 图标路径(必须)
iconPath: {
type: String,
required: true
},
// 默认颜色
defaultColor: {
type: String,
default: '#606266'
},
// 激活颜色(传入后才允许变色)
activeColor: {
type: String,
default: null
},
// 是否开启悬停变色
hoverEffect: {
type: Boolean,
default: false
},
// 图标大小
size: {
type: [String, Number],
default: '14px'
},
// 是否当前激活状态
isActive: {
type: Boolean,
default: false
}
},
data() {
return {
svgContent: '',
isHovering: false,
currentColor: this.defaultColor
}
},
computed: {
wrapperStyle() {
return {
width: typeof this.size === 'number' ? `${this.size}px` : this.size,
height: typeof this.size === 'number' ? `${this.size}px` : this.size,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center'
}
},
iconStyle() {
return {
width: '100%',
height: '100%',
color: this.currentColor,
transition: 'color 0.3s ease'
}
},
shouldChangeColor() {
return this.activeColor && (this.hoverEffect || this.isActive)
}
},
watch: {
isActive(newVal) {
console.log(newVal, 'newVal---');
if (this.shouldChangeColor) {
this.currentColor = newVal ? this.activeColor : this.defaultColor
console.log(this.currentColor, 'this.currentColor--');
}
},
defaultColor(newVal) {
if (!this.isHovering && !this.isActive) {
this.currentColor = newVal
}
},
activeColor() {
this.updateColorState()
}
},
methods: {
async loadSvg() {
try {
const response = await fetch(this.iconPath)
this.svgContent = await response.text()
this.processSvg()
} catch (error) {
console.error('Failed to load SVG:', error)
}
},
processSvg() {
// 确保SVG没有自带颜色,以便用CSS控制
this.$nextTick(() => {
const svgElement = this.$el.querySelector('svg')
if (svgElement) {
// 更彻底地移除颜色属性
svgElement.removeAttribute('fill')
svgElement.removeAttribute('style')
const paths = svgElement.querySelectorAll('path, circle, rect, polygon')
paths.forEach(el => {
el.removeAttribute('fill')
})
svgElement.style.fill = 'currentColor'
svgElement.style.width = '100%'
svgElement.style.height = '100%'
}
})
},
handleMouseEnter() {
this.isHovering = true
this.updateColorState()
},
handleMouseLeave() {
this.isHovering = false
this.updateColorState()
},
updateColorState() {
if (this.activeColor) {
if (this.isActive) {
this.currentColor = this.activeColor
} else {
this.currentColor = this.isHovering && this.hoverEffect ?
this.activeColor :
this.defaultColor
}
} else {
this.currentColor = this.defaultColor
}
}
},
created() {
this.loadSvg()
}
}
</script>
<style scoped>
.svg-icon-wrapper {
cursor: pointer;
}
.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 {
display: inline-flex;
}
.svg-icon>>>svg {
fill: currentColor;
}
</style>