1
0

svg.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <template>
  2. <div class="svg-container" v-html="processedSvg" :style="containerStyle"></div>
  3. </template>
  4. <script setup>
  5. import { ref, watch, computed } from 'vue';
  6. const props = defineProps({
  7. // SVG图片的URL
  8. svgUrl: {
  9. type: String,
  10. required: true
  11. },
  12. // 要设置的颜色
  13. color: {
  14. type: String,
  15. default: '#262626'
  16. },
  17. // SVG宽度
  18. width: {
  19. type: String,
  20. default: '16px'
  21. },
  22. // SVG高度
  23. height: {
  24. type: String,
  25. default: '16px'
  26. }
  27. });
  28. const rawSvg = ref('');
  29. const processedSvg = ref('');
  30. const error = ref(null);
  31. // 容器样式
  32. const containerStyle = computed(() => ({
  33. width: props.width,
  34. height: props.height,
  35. display: 'inline-block'
  36. }));
  37. // 加载SVG
  38. const loadSvg = async () => {
  39. try {
  40. error.value = null;
  41. const response = await fetch(props.svgUrl);
  42. if (!response.ok) {
  43. throw new Error(`无法加载SVG: ${response.statusText}`);
  44. }
  45. rawSvg.value = await response.text();
  46. } catch (err) {
  47. error.value = err.message;
  48. console.error('加载SVG时出错:', err);
  49. }
  50. };
  51. // 处理SVG并修改颜色
  52. const updateSvgColor = () => {
  53. if (!rawSvg.value) return;
  54. // 创建临时DOM元素来处理SVG
  55. const parser = new DOMParser();
  56. const doc = parser.parseFromString(rawSvg.value, 'image/svg+xml');
  57. const svgElement = doc.querySelector('svg');
  58. if (!svgElement) {
  59. processedSvg.value = rawSvg.value;
  60. return;
  61. }
  62. // 移除可能影响颜色的属性
  63. svgElement.removeAttribute('fill');
  64. svgElement.removeAttribute('stroke');
  65. // 添加CSS类以便通过样式控制
  66. svgElement.classList.add('dynamic-svg');
  67. // 修改所有路径和形状的颜色
  68. const elements = svgElement.querySelectorAll('path, circle, rect, polygon, polyline, line, ellipse');
  69. elements.forEach(el => {
  70. // 保存原始颜色以便可能的恢复
  71. if (!el.dataset.originalFill) {
  72. el.dataset.originalFill = el.getAttribute('fill') || '';
  73. }
  74. if (!el.dataset.originalStroke) {
  75. el.dataset.originalStroke = el.getAttribute('stroke') || '';
  76. }
  77. // 设置新颜色
  78. if (el.dataset.originalFill && el.dataset.originalFill !== 'none') {
  79. el.setAttribute('fill', props.color);
  80. }
  81. if (el.dataset.originalStroke && el.dataset.originalStroke !== 'none') {
  82. el.setAttribute('stroke', props.color);
  83. }
  84. });
  85. // 将处理后的SVG转换回字符串
  86. const serializer = new XMLSerializer();
  87. processedSvg.value = serializer.serializeToString(svgElement);
  88. };
  89. // 监听属性变化并重新加载/处理SVG
  90. watch(() => props.svgUrl, loadSvg, { immediate: true });
  91. watch(() => props.color, updateSvgColor);
  92. watch(rawSvg, updateSvgColor);
  93. </script>
  94. <style scoped>
  95. .svg-container {
  96. overflow: hidden;
  97. }
  98. /* 备用样式,在直接修改属性不生效时使用 */
  99. :deep(.dynamic-svg) {
  100. width: 100%;
  101. height: 100%;
  102. }
  103. /* 可以根据需要添加更多样式 */
  104. </style>