Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

当页面同时使用多个相同图标出现 ID 冲突导致 SVG无法正常显示 #122

Open
WangJincheng4869 opened this issue Sep 8, 2023 · 6 comments

Comments

@WangJincheng4869
Copy link

svgo 中可以添加前缀,但只能解决使用不同图标,如果使用相同的图标依旧会有ID冲突问题。

@WangJincheng4869
Copy link
Author

WangJincheng4869 commented Sep 8, 2023

没法解决,所以我弃用该插件自己进行实现,基本代码如下

const instance = getCurrentInstance()!;

图标的样式
const iconStyle = computed(() => {
  let style: StyleValue = {};
  let transform = '';
  if (props.rotate) {
    transform += `rotate(${props.rotate}) `;
  }
  if (props.rotateX) {
    transform += `rotateX(${props.rotateX}) `;
  }
  if (props.rotateY) {
    transform += `rotateY(${props.rotateY}) `;
  }
  if (transform) {
    style.transform = transform;
  }
  return style;
});

watchEffect(() => {
  import(`../../assets/svg/${props.name}.svg?raw`).then(dom => {
    let svgDom = dom.default
      .replace(/(id=")(.*?")/gi, `$1${instance.uid}-$2`)
      .replace(/(url\(#)(.*?\))/gi, `$1${instance.uid}-$2`)
      .replace(/(href="#)(.*?")/gi, `$1${instance.uid}-$2`);
    console.log(instance.uid);
    if (iconStyle.value.transform) {
      let parser = new DOMParser();
      let doc = parser.parseFromString(svgDom, 'image/svg+xml');
      let svg = doc.querySelector('svg')!;
      svg.style.transform = iconStyle.value.transform;
      iconDom.value = svg.outerHTML;
    } else {
      iconDom.value = svgDom;
    }
  });
});

@How2j-online
Copy link

这样封装一下

<script setup lang="ts">
defineOptions({
  name: "SvgIcon"
});
import type { Component } from "vue";
import { computed } from "vue";

const props = defineProps<{
  name: string;
}>();
const modules = import.meta.glob("@/assets/icons/*.svg", {
  as: "component",
  eager: true
});
// icon lower name
const newName = computed(() => {
  return props.name.toLowerCase();
});
// 获取对应svg组件
const currentComponent = computed(() => {
  const fileName = `/${newName.value}.svg`;
  let findMod;
  for (const path in modules) {
    const mod = modules[path];
    if (path.endsWith(fileName)) {
      findMod = mod as Component;
    }
  }
  return findMod;
});
</script>

<template>
  <component :is="currentComponent"></component>
</template>

<style scoped lang="less"></style>

我的版本

"vite-svg-loader": "^4.0.0",
"vue": "^3.3.4",
"typescript": "~5.1.6",

@WangJincheng4869
Copy link
Author

这样封装一下

<script setup lang="ts">
defineOptions({
  name: "SvgIcon"
});
import type { Component } from "vue";
import { computed } from "vue";

const props = defineProps<{
  name: string;
}>();
const modules = import.meta.glob("@/assets/icons/*.svg", {
  as: "component",
  eager: true
});
// icon lower name
const newName = computed(() => {
  return props.name.toLowerCase();
});
// 获取对应svg组件
const currentComponent = computed(() => {
  const fileName = `/${newName.value}.svg`;
  let findMod;
  for (const path in modules) {
    const mod = modules[path];
    if (path.endsWith(fileName)) {
      findMod = mod as Component;
    }
  }
  return findMod;
});
</script>

<template>
  <component :is="currentComponent"></component>
</template>

<style scoped lang="less"></style>

我的版本

"vite-svg-loader": "^4.0.0",
"vue": "^3.3.4",
"typescript": "~5.1.6",

你这段代码可以解决 svg 代码里用到 id,页面上重复使用图标,会出现 id 重复而无法正常显示的情况吗?

@raohuiyong
Copy link

raohuiyong commented Jan 26, 2024

svgo有个插件配置prefixIds,为每个id添加前缀(前缀根据文件名生成)。可以保持id的唯一

@WangJincheng4869
Copy link
Author

svgo有个插件配置prefixIds,为每个id添加前缀(前缀根据文件名生成)。可以保持id的唯一

只能解决不同图标的问题,如果一个图标被多次引用,依旧冲突

@Dylan0916
Copy link

I'm also facing this problem. is there any solution for this lib?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants