在vue3+ts+vite中使用svg图片

目录

前言

步骤

1.安装svg-sprite-loader,这里使用的是6.0.11版本

2.项目的svg图片存放在src/icons下,我们在这里创建两个文件index.ts和index.vue(在哪创建和文件名字并没有任何要求)

 3.在index.ts中加入下列代码(如果报错找不到fs模块请跳转到文章末尾 附录-导入@type/node)

4.在svgIcon.vue中加入下列代码

5.在src/main.ts导入组件

6.在vite.config.ts中导入index.ts,在defineConfig()中加入createSvg(),如下所示

7.配置完毕,我们可以用以下方式导入自己的svg图片

附录-导入@type/node


前言

SVG(Scalable Vector Graphics)是一种用于描述二维矢量图像的XML语言。它可以实现图像的高质量缩放和无损放大,因此被广泛应用于Web开发和图形设计领域。

SVG的优点之一是它具有跨平台和跨浏览器的兼容性。由于SVG图像是基于XML的,所以可以在任何支持SVG的浏览器中进行渲染和显示。这使得开发人员能够创建只需一次编码就能在各种设备上完美呈现的图像。

与其他图像格式(如JPEG和PNG)相比,SVG的文件大小较小,因为它使用的是矢量图形而不是像素。这意味着SVG图像可以无损放大或缩小,而不会失真。这对于需要在不同屏幕尺寸和分辨率上显示一致的图像非常有用。

SVG提供了丰富的绘图和动画功能,可以通过CSS或JavaScript进行样式和交互控制。使用SVG,开发人员可以创建复杂的图形、图表和动态效果,以及响应用户事件和用户界面交互。

在使用SVG时,可以直接编写SVG标记或使用专业的图形编辑工具生成SVG文件。SVG标签可以用于绘制各种形状,例如线条、矩形、圆形、椭圆和路径。此外,SVG还支持渐变、滤镜、文字和图像嵌入等功能,使得图像呈现更加丰富和多样化。

除了静态图像,SVG还可以用于创建动画效果。通过使用SVG的内置动画元素和事件处理,可以实现平滑的过渡、旋转、缩放和颜色变换等效果。这使得SVG成为创建交互式和动态图像的理想选择。

总之,SVG是一种强大的图像格式,适用于各种场景,包括图形设计、数据可视化、动态图像和Web应用程序等。它的优势在于可伸缩性、跨平台兼容性和丰富的绘图和动画功能。无论是您希望创建静态图像还是交互式动画,SVG都是一个值得考虑的选择。

步骤

1.安装svg-sprite-loader,这里使用的是6.0.11版本

npm install svg-sprite-loader

2.项目的svg图片存放在src/icons下,我们在这里创建两个文件index.ts和index.vue(在哪创建和文件名字并没有任何要求)

 3.在index.ts中加入下列代码(如果报错找不到fs模块请跳转到文章末尾 附录-导入@type/node)

import { readFileSync, readdirSync } from "fs";
let idPerfix = "";
const svgTitle = /<svg([^>+].*?)>/;
const clearHeightWidth = /(width|height)="([^>+].*?)"/g;
const hasViewBox = /(viewBox="[^>+].*?")/g;
const clearReturn = /(\r)|(\n)/g;
// 查找svg文件
function svgFind(e) {
    const arr = [];
    const dirents = readdirSync(e, { withFileTypes: true });
    for (const dirent of dirents) {
        if (dirent.isDirectory()) arr.push(...svgFind(e + dirent.name + "/"));
        else {
            const svg = readFileSync(e + dirent.name)
                .toString()
                .replace(clearReturn, "")
                .replace(svgTitle, ($1, $2) => {
                    let width = 0,
                        height = 0,
                        content = $2.replace(clearHeightWidth, (s1, s2, s3) => {
                            if (s2 === "width") width = s3;
                            else if (s2 === "height") height = s3;
                            return "";
                        });
                    if (!hasViewBox.test($2))
                        content += `viewBox="0 0 ${width} ${height}"`;
                    return `<symbol id="${idPerfix}-${dirent.name.replace(
                        ".svg",
                        ""
                    )}" ${content}>`;
                })
                .replace("</svg>", "</symbol>");
            arr.push(svg);
        }
    }
    return arr;
}
// 生成svg
export const createSvg = (path: any, perfix = "icon") => {
    if (path === "") return;
    idPerfix = perfix;
    const res = svgFind(path);
    return {
        name: "svg-transform",
        transformIndexHtml(dom: String) {
            return dom.replace(
                "<body>",
                `<body><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">${res.join(
                    ""
                )}</svg>`
            );
        },
    };
};

4.在svgIcon.vue中加入下列代码

<template>
  <svg :class="svgClass" v-bind="$attrs" :style="{ color: color, fontSize: size }">
    <use :href="iconName"></use>
  </svg>
</template>
​
<script setup lang="ts">
import { computed } from "vue";
const props = defineProps({
  name: {
    type: String,
    required: true,
  },
  color: {
    type: String,
    default: "",
  },
  size: {
    type: Number,
  },
});
const iconName = computed(() => `#icon-${props.name}`);
const svgClass = computed(() => {
  if (props.name) return `svg-icon icon-${props.name}`;
  return "svg-icon";
});
</script>
​
<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  fill: currentColor;
  vertical-align: middle;
}
</style>

5.在src/main.ts导入组件

import { createApp } from "vue";
import App from "./App.vue";
​
import svgIcon from "@/icons/index.vue";
​
createApp(App)
    .component('svg-icon', svgIcon)
    .mount("#app");

6.在vite.config.ts中导入index.ts,在defineConfig()中加入createSvg(),如下所示

import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
​
//这里会报svgIcon.ts不在tsconfig.config.json文件列表中,在tsconfig.config.json的include里加
//"./src/icons/svgIcon.ts"就行,不加对npm run dev没影响
import { createSvg } from "./src/icons/index";
​
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), createSvg('./src/icons/svg/')],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
});

tsconfig.node.json配置

{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts","src/icons/"]
}

7.配置完毕,我们可以用以下方式导入自己的svg图片

   <svg-icon
        :name="你自己的svg文件名"
        class="svg-container"
        :size="48"
        :color="active == item.path ? '#253FE4' : '#A8B2F4'"
   ></svg-icon>

注意 svg文件 删除所有fill字段 反之可能导致颜色不生效(示例)

<svg width="48" height="48" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<g id="&#232;&#174;&#190;&#229;&#164;&#135;&#231;&#138;&#182;&#230;&#128;&#129; 1">
<rect width="48" height="48" rx="8"  />
<path id="Vector" d="M33.4286 12H14.5714C13.8894 12 13.2354 12.2709 12.7532 12.7532C12.2709 13.2354 12 13.8894 12 14.5714V30C12 30.682 12.2709 31.336 12.7532 31.8183C13.2354 32.3005 13.8894 32.5714 14.5714 32.5714H23.1429V34.2857H17.1429C16.9155 34.2857 16.6975 34.376 16.5368 34.5368C16.376 34.6975 16.2857 34.9155 16.2857 35.1429C16.2857 35.3702 16.376 35.5882 16.5368 35.7489C16.6975 35.9097 16.9155 36 17.1429 36H30.8571C31.0845 36 31.3025 35.9097 31.4632 35.7489C31.624 35.5882 31.7143 35.3702 31.7143 35.1429C31.7143 34.9155 31.624 34.6975 31.4632 34.5368C31.3025 34.376 31.0845 34.2857 30.8571 34.2857H24.8571V32.5714H33.4286C34.1106 32.5714 34.7646 32.3005 35.2468 31.8183C35.7291 31.336 36 30.682 36 30V14.5714C36 13.8894 35.7291 13.2354 35.2468 12.7532C34.7646 12.2709 34.1106 12 33.4286 12ZM14.5714 13.7143H33.4286C33.6559 13.7143 33.8739 13.8046 34.0347 13.9653C34.1954 14.1261 34.2857 14.3441 34.2857 14.5714V26.5714H13.7143V14.5714C13.7143 14.3441 13.8046 14.1261 13.9653 13.9653C14.1261 13.8046 14.3441 13.7143 14.5714 13.7143ZM34.2857 30C34.2857 30.2273 34.1954 30.4453 34.0347 30.6061C33.8739 30.7668 33.6559 30.8571 33.4286 30.8571H14.5714C14.3441 30.8571 14.1261 30.7668 13.9653 30.6061C13.8046 30.4453 13.7143 30.2273 13.7143 30V28.2857H34.2857V30Z" fill="white"/>
</g>
</svg>

 

附录-导入@type/node

1.安装@type/node

npm install @types/node

2.在tscongfig.json中加入"types": ["node"],如下所示

{
  "extends": "@vue/tsconfig/tsconfig.web.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    },
    "types": ["node"]
  },

  "references": [
    {
      "path": "./tsconfig.config.json"
    }
  ]
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值