<template>
<component :is="currentComponent" ref="svgRef" :class="props.class" />
</template>
<script setup lang="ts">
import type { Component } from 'vue';
import { computed, ref, useAttrs, watch } from 'vue';
import { uuid } from '@/utils';
const modules = import.meta.globEager('@/assets/images/webPuc/svgs/*.svg', {
as: 'component',
});
const attrs = useAttrs();
const props = defineProps({
name: {
type: String,
require: true,
},
class: {
type: String,
default: 'webPuc_svg',
},
useViewBox: {
type: Boolean,
default: false,
},
});
const currentComponent = computed<Component>(() => {
const fileName = `/${props.name}.svg`;
const currentKey = Object.keys(modules).find((key) => {
return key.endsWith(fileName);
});
try {
return modules[currentKey] as Component;
} catch (error) {
throw new Error(`not found svg file:${fileName}`);
}
});
const svgRef = ref<any>();
watch(svgRef, (newVal) => {
if (newVal) {
Object.entries({ ...attrs, ...props }).forEach(([k, v]) => {
if (v !== undefined) {
newVal.$el?.setAttribute(k, String(v));
}
});
try {
/* 生成的svg代码没有viewBox属性,需要额外添加 */
if (!attrs.viewBox && !props.useViewBox) {
newVal.$el?.setAttribute(
'viewBox',
`0 0 ${newVal.$el.getAttribute('width')} ${newVal.$el.getAttribute(
'height'
)}`
);
}
const flagMap = {};
if (!newVal?.$el) return;
newVal.$el.innerHTML = newVal.$el.innerHTML.replace(
/url\(#\w{1}\)/g,
(key: string) => {
const k = key.slice(5, -1);
flagMap[k] = uuid();
return `url(#${flagMap[k]})`;
}
);
newVal.$el.innerHTML = newVal.$el.innerHTML.replace(
/id="\w{1}"/g,
(key: string) => {
const k = key.slice(4, -1);
return `id="${flagMap[k]}"`;
}
);
} catch (error) {
window.$wsLogs.error('catched an error', error);
}
}
});
</script>
<style scoped lang="less">
svg {
width: auto;
height: auto;
}
</style>