92 lines
1.9 KiB
Vue
92 lines
1.9 KiB
Vue
<script setup lang="ts">
|
||
import { px2vh } from '@/utils'
|
||
|
||
const props = withDefaults(
|
||
defineProps<{
|
||
name: string
|
||
size?: string | number
|
||
width?: string | number | 'auto'
|
||
height?: string // 高度,不传默认为正方形svg height = width
|
||
fill?: string
|
||
rotate?: string | number
|
||
style?: { [key: string]: string }
|
||
loading?: boolean
|
||
onClick?: (...args: any[]) => void
|
||
}>(),
|
||
{
|
||
width: '30',
|
||
},
|
||
)
|
||
const emit = defineEmits(['click'])
|
||
|
||
defineOptions({ inheritAttrs: false })
|
||
|
||
const { size, width, height } = toRefs(props)
|
||
|
||
const _width = computed(() => (width.value === 'auto' ? 'auto' : px2vh(size.value || width.value)))
|
||
const _height = computed(() => (height.value ? px2vh(size.value || height.value) : _width.value))
|
||
const _style = computed(() => ({
|
||
...props.style,
|
||
width: _width.value,
|
||
height: _height.value,
|
||
transform: `rotate(${props.rotate}deg)`,
|
||
fill: props.fill,
|
||
}))
|
||
|
||
const url = computed(() => {
|
||
const ext = props.name.includes('.') ? '' : '.svg'
|
||
return `${import.meta.env.VITE_OSS_URL}/icon/${props.name}${ext}`
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<i
|
||
:class="{
|
||
'x-icon': true,
|
||
'is-loading': loading,
|
||
'x-auto': width === 'auto',
|
||
}"
|
||
v-bind="$attrs"
|
||
:style="_style"
|
||
aria-hidden="true"
|
||
@click="e => (props.onClick ? props.onClick(e) : emit('click', e))"
|
||
>
|
||
<img :src="url" :style="{ width: width === 'auto' ? 'auto' : '100%' }" />
|
||
</i>
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
.x-icon {
|
||
display: inline-block;
|
||
position: relative;
|
||
&.is-loading {
|
||
animation: rotating 2s linear infinite;
|
||
}
|
||
|
||
@keyframes rotating {
|
||
0% {
|
||
transform: rotateZ(0);
|
||
}
|
||
100% {
|
||
transform: rotateZ(360deg);
|
||
}
|
||
}
|
||
|
||
img {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
user-select: none;
|
||
-webkit-user-drag: none;
|
||
height: 100%;
|
||
}
|
||
|
||
&.x-auto {
|
||
position: unset;
|
||
img {
|
||
position: unset;
|
||
}
|
||
}
|
||
}
|
||
</style>
|