SVG(Scalable Vector Graphics,可缩放矢量图形)是一种基于可扩展标记语言(XML)的图形格式,用于描述二维矢量图形。它由W3C制定,是一个开放标准。
SVG概述:
- SVG允许3种图形物件类型:矢量图形、栅格图像以及文本。
- SVG提供的功能集涵盖了嵌套转换、裁剪路径、Alpha通道、滤镜效果、模板对象以及可扩展性。
- SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式。
SVG的优点: 1.矢量图形缩放不会失真(像素点数量不变而导致图像出现模糊、锯齿等),而光栅图形(PNG、JPG)缩放会导致失真。
- 矢量图形:基于矢量的点、线、形状和数学公式来构建的图形,该图形是没有像素的,放大缩小不会失真。
- 光栅图形:由像素点构建的图像---微小的彩色方块,大量像素点可以形成高清图像,比如照片。图像像素越多,质量越高。
-
SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
-
SVG图像中的文本是可选的,同时也是可搜索的,且可以与 JavaScript 技术一起运行
SVG的缺点:
-
SVG复杂度越高渲染速度就会越慢(任何过度使用DOM的应用都不快)
-
SVG不适合游戏应用,只能结合Canvas来实现
-
SVG不能动态的修改动画内容
使用
在网页中使用SVG有多种方法。以下是一些常见的方法:
- 直接嵌入HTML中:你可以直接将SVG代码嵌入到HTML文档中。这种方法允许你使用CSS和JavaScript直接与SVG元素交互。
html
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
- 使用
<img>
标签 :如果你有一个.svg
文件,你可以像使用其他图像格式一样使用它。
html
<img src="path/to/your/image.svg" alt="Description of SVG">
- 使用CSS背景:SVG也可以作为CSS背景图像使用。
css
.svg-background {
background-image: url('path/to/your/image.svg');
}
- 使用
<object>
或<embed>
标签:这两种方法允许你嵌入外部SVG文件,并保持文件的交互性。
html
<object data="path/to/your/image.svg" type="image/svg+xml"></object>
或
html
<embed src="path/to/your/image.svg" type="image/svg+xml">
- 使用
<iframe>
:你可以在<iframe>
中加载SVG文件。
html
<iframe src="path/to/your/image.svg"></iframe>
- 使用JavaScript:你可以使用JavaScript动态地创建SVG元素并添加到DOM中。
在vite 中使用 svg 插件
使用svg 插件这部分,有两个比较有名的插件 分别是unplugin-icons
和 vite-plugin-svg-icons
都是用于处理 SVG 图标的 Vite 插件,但它们有一些不同的特点和用途。
unplugin-icons
-
功能丰富 :除了支持本地 SVG 图标,它还支持
iconify
图标库,这意味着你可以直接从数千个图标中选择并按需导入。 -
按需导入:只有在代码中实际使用的图标才会被包含在最终的构建中,这有助于减少最终的包大小。
-
自动组件化:它可以自动将图标转换为 Vue 或 React 组件,使得在组件中使用图标变得非常简单。
-
扩展性:支持自定义加载器和解析器,这意味着你可以扩展它以支持其他图标库或格式。
-
与其他 unplugin 插件集成 :例如,
unplugin-auto-import
集成,可以自动导入和注册图标组件。
vite-plugin-svg-icons
-
专注于本地 SVG:这个插件主要是为了处理和优化项目中的本地 SVG 图标。
-
SVG 精灵图:它会将所有的 SVG 图标合并为一个 SVG 精灵图,这可以减少 HTTP 请求并提高性能。
-
预加载:当项目运行时,所有图标都会预先生成,这意味着在首次加载时,所有的图标都已经可用。
-
高性能:内置缓存,只有在文件被修改时才会重新生成。
-
简单的 API:它提供了一个简单的 API 来配置和使用,使得在 Vite 项目中使用 SVG 图标变得非常简单。
总结
-
如果你主要关心的是使用
iconify
图标库或需要一个功能丰富且可扩展的解决方案,那么unplugin-icons
可能是一个更好的选择。 -
如果你主要关心的是优化和管理项目中的本地 SVG 图标,并希望利用 SVG 精灵图的优势,那么
vite-plugin-svg-icons
可能更适合你。
- 对svg 精灵图的讲解 SVG 雪碧图(SVG Sprite)是一种将多个 SVG 图标合并到单个 SVG 文件中的技术。这个合并后的文件被称为 SVG 雪碧图,它可以减少 HTTP 请求,提高性能,并使图标的管理更加方便。
以下是创建和使用 SVG 雪碧图的一般步骤:
创建 SVG 雪碧图:
-
收集 SVG 图标:首先,收集所有要包含在雪碧图中的 SVG 图标文件。这些图标可以来自不同的来源,通常是独立的 SVG 文件。
-
合并 SVG 图标 :使用工具或脚本将这些独立的 SVG 文件合并成一个单独的 SVG 雪碧图文件。合并后的文件中,每个图标通常包含在
<symbol>
元素中,并分配一个唯一的标识符(id
)。 -
定义雪碧图符号 :在合并的 SVG 文件中,你需要使用
<symbol>
元素定义每个图标。每个<symbol>
元素都有一个id
,这个id
通常用于引用图标。 -
保存雪碧图 :将合并后的 SVG 文件保存到你的项目中,通常命名为
sprite.svg
或类似的名称。
在 HTML 中使用 SVG 雪碧图:
-
引入 SVG 雪碧图 :在你的 HTML 文件中,使用
<svg>
元素引入 SVG 雪碧图文件。通常,你会将雪碧图嵌入到页面的某个位置,例如在<body>
的末尾。html<svg class="hidden"> <use xlink:href="sprite.svg#icon-id"></use> </svg>
上面的代码中,
xlink:href
属性指定了要使用的雪碧图文件(sprite.svg
),并通过#
指定要使用的图标的标识符(icon-id
)。 -
使用图标 :在页面的其他地方,你可以使用
<svg>
元素来引用和显示图标。html<svg class="icon"> <use xlink:href="sprite.svg#icon-id"></use> </svg>
在这个例子中,
xlink:href
属性仍然用于指定要使用的图标,而class
属性用于定义图标的样式。
CSS 样式:
你可以使用 CSS 样式来控制 SVG 图标的大小、颜色和其他样式属性。通常,你可以为 SVG 图标添加一个类,并为这个类定义样式。
css
.icon {
width: 24px;
height: 24px;
fill: currentColor; /* 使用当前文本颜色填充图标 */
}
总的来说,SVG 雪碧图是一种优化前端项目的方式,特别是对于图标资源。它可以减少请求次数,提高性能,并简化图标的管理和使用。
具体使用 -- unplugin-icons
安装插件
bash
npm i -D unplugin-icons
使用 unplugin-icons
插件中有一个 customCollections
属性,用来做自定义图标的加载
但 SVG 是一个 XML 格式的文件,而不是 JavaScript。为了在 JavaScript 或 TypeScript 中使用它,我们需要将其转换为一个 JavaScript 可以理解和处理的格式 所以还需要一个 SVG 文件解析的 loader
因此,unplugin-icons
提供了一个内置的 FileSystemIconLoader,这是一个专门为 SVG 设计的 loader。有了他帮助我们了简化和优化 SVG 的加载和处理过程,使其可以轻松地在前端项目中使用。
整体简单使用配置
这里列出了最基本常见的配置,更多的配置可以参考文档
js
// vite.config.ts
import { defineConfig } from 'vite'
import Icons from 'unplugin-icons/vite'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
export default defineConfig({
// ...
plugins: [
Icons({
// @default 默认vue3
// compiler:'vue3',
/**
* 按需引入这个选项会自动为你的应用安装必要的运行时。这意味着你不需要手动导入或注册图标组件,它们会自动被引入并可用。
* */
autoInstall: true,
/**
* 这个选项允许你定义自己的图标集合。每个集合都是一个键值对,其中键是集合的名称,值是一个加载器函数,用于加载和处理图标。
*/
customCollections: {
/**
* FileSystemIconLoader
* 第一个参数是 SVG 图标的路径,文件名(不包括扩展名)将被用作图标的名称
* 第二个参数是这是一个处理函数,用于处理加载的 SVG 内容。在这个例子中,它将 SVG 的开头替换为 <svg fill="currentColor" 。
* 这意味着图标的颜色会使用 CSS 的 currentColor 值,从而允许你通过 CSS 控制图标的颜色。
*/
home: FileSystemIconLoader(path.resolve('src', 'assets/home'), (svg) =>
svg.replace(/^<svg /, '<svg fill="currentColor" ')
)
}
})],
})
- 在vue 页面上使用时候 导入格式遵守
~icons/{collection}/{icon}
其中collection
表示在上面配置项中customCollections
字段的 key 集合,icon
表示集合路径下svg
文件
vue
<template>
<HomeSettingSvg />
<HomeSettingSvg style="font-size: 2em; color: red"/>
</template>
<script setup lang="ts">
// 导入 svg 图标
import HomeSettingSvg from 'virtual:icons/home/setting' // 写法一
// import HomeSettingSvg from '~icons/home/setting' // 写法二
</script>
- 也提供了在导入时候指定 样式用法
vue
<template>
<!-- <HomeSettingSvg /> -->
<span v-html="HomeSettingSvg" />
</template>
<script setup lang="ts">
// 导入 svg 图标
import HomeSettingSvg from 'virtual:icons/home/setting?raw&width=1em&height=1em'
// import HomeSettingSvg from '~icons/home/setting'
</script>
说明如果你用了 ts 发现手动时候导入报错 ,你需要配置声明如下
ts
declare module 'virtual:icons/*'
按需引入(推荐)
在使用的时候不想每次都导入进来 也提供了按需引入的方式 需要配置插件 unplugin-vue-components/vite
提供了配合使用的按需导入的 resolvers
'unplugin-icons/resolver'
js
// vite.config.ts
import { defineConfig } from 'vite'
import Icons from 'unplugin-icons/vite'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import path from 'path'
export default defineConfig({
// ...
plugins: [
Icons({
// @default 默认vue3
// compiler:'vue3',
/**
* 按需引入这个选项会自动为你的应用安装必要的运行时。这意味着你不需要手动导入或注册图标组件,它们会自动被引入并可用。
* */
autoInstall: true,
/**
* 这个选项允许你定义自己的图标集合。每个集合都是一个键值对,其中键是集合的名称,值是一个加载器函数,用于加载和处理图标。
*/
customCollections: {
/**
* FileSystemIconLoader
* 第一个参数是 SVG 图标的路径,文件名(不包括扩展名)将被用作图标的名称
* 第二个参数是这是一个处理函数,用于处理加载的 SVG 内容。在这个例子中,它将 SVG 的开头替换为 <svg fill="currentColor" 。
* 这意味着图标的颜色会使用 CSS 的 currentColor 值,从而允许你通过 CSS 控制图标的颜色。
*/
home: FileSystemIconLoader(path.resolve('src', 'assets/home'), (svg) =>
svg.replace(/^<svg /, '<svg fill="currentColor" ')
)
}
}),
Components({
// Auto register Element Plus components
// 自动导入 Element Plus 组件
resolvers: [
ElementPlusResolver(),
// 自动导入 svg 图标 用来配合 `unplugin-icons` 使用的
IconsResolver({
// prefix: 'icon', // 自动引入的Icon组件统一前缀,默认为 i,设置false为不需要前缀
enabledCollections: ['home'] // 这是可选的,默认启用 Iconify 支持的所有集合
})
],
// 指定生成的 组件的 ts 文件目录
dts: path.resolve('types', 'components.d.ts'),
directives: true
})],
})
配置之后使用
vue
<template>
<!--[prefix]-[customCollections]-[icons] -->
<i-home:setting />
</template>
<script setup lang="ts">
</script>
插件 vite-plugin-svg-icons
安装
bash
yarn add vite-plugin-svg-icons -D
# or
npm i vite-plugin-svg-icons -D
# or
pnpm install vite-plugin-svg-icons -D
简单使用
js
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default () => {
return {
plugins: [
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), 'src/icons')],
// 指定symbolId格式
symbolId: 'icon-[dir]-[name]',
/**
* 自定义插入位置
* @default: body-last
*/
inject?: 'body-last' | 'body-first'
/**
* custom dom id
* @default: __svg__icons__dom__
*/
customDomId: '__svg__icons__dom__',
}),
],
}
}
在 src/main.ts 内引入注册脚本
ts
import 'virtual:svg-icons-register'
完成上面配置后可以 到这里 svg 雪碧图已经生成
但是使用前推荐封装一个全局 svg 的vue 组件 ,在目录 /src/components/SvgIcon.vue
,封装参考这篇
vue
<!-- src/components/SvgIcon/index.vue -->
<script setup lang="ts">
const props = defineProps({
prefix: {
type: String,
default: "icon",
},
iconClass: {
type: String,
required: false,
},
color: {
type: String,
},
size: {
type: String,
default: "1em",
},
});
const symbolId = computed(() => `#${props.prefix}-${props.iconClass}`);
</script>
<template>
<svg
aria-hidden="true"
class="svg-icon"
:style="'width:' + size + ';height:' + size"
>
<use :xlink:href="symbolId" :fill="color" />
</svg>
</template>
<style scoped>
.svg-icon {
display: inline-block;
outline: none;
width: 1em;
height: 1em;
vertical-align: -0.15em; /* 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果 */
fill: currentColor; /* 定义元素的颜色,currentColor是一个变量,这个变量的值就表示当前元素的color值,如果当前元素未设置color值,则从父元素继承 */
overflow: hidden;
}
</style>
使用
vue
<!-- src/components/HelloWorld.vue -->
<template>
<el-button type="info"><svg-icon icon-class="block"/>SVG 本地图标</el-button>
</template>
更多可以参考文档
获取svg 的途径
可以从阿里图标库进行下载 合适的svg 图片 ,或者使用 iconify
网站上的图标,使用这个网站上图标需要手动安装图标库,如名,直接安装 iconify
整个库,这个库大约在 120MB 左右大小,当然你不需要担心,在生产环境只会打包你所使用到的图标
bash
npm i -D @iconify/json
如果觉得这样下载过于庞大也可以指定下载的使用的svg 图标库,将图标集的名字替换 xxx 即可其中xxx 如图配合npm 去搜索看库是否实际存在
bash
npm i -D @iconify-json/xxx
基础使用 iconify-json
安装完适合的 iconify-json
图标库,接下来使用
vue
<template>
<IconIcBaseline5g />
</template>
<script setup lang="ts">
import IconIcBaseline5g from '~icons/ic/baseline-5g'
</script>
配合 unplugin-icons 使用
如果你决定使用 @iconify/json
那么可以配合 unplugin-icons
, unplugin-icons
配置中提供了自动 安装图标库集合指令 autoInstall: true
,当你运行项目时候会自动帮你安装使用的图标集合指令
现在我想按需引入的话,需要在 unplugin-vue-components
中的 IconsResolver
进行配置 enabledCollections: ['home', 'ic']
这是可选的,默认启用 Iconify 支持的所有集合,例如按照 unplugin-icons
规则使用 @iconify/ic
的图标集合,并且也已经配置了 自动导入
html
<i-ic:baseline-5g />
js
// vite.config.ts
import { defineConfig } from 'vite'
import Icons from 'unplugin-icons/vite'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import path from 'path'
export default defineConfig({
// ...
plugins: [
Icons({
// @default 默认vue3
// compiler:'vue3',
/**
* 按需引入这个选项会自动为你的应用安装必要的运行时。这意味着你不需要手动导入或注册图标组件,它们会自动被引入并可用。
* */
autoInstall: true,
/**
* 这个选项允许你定义自己的图标集合。每个集合都是一个键值对,其中键是集合的名称,值是一个加载器函数,用于加载和处理图标。
*/
customCollections: {
/**
* FileSystemIconLoader
* 第一个参数是 SVG 图标的路径,文件名(不包括扩展名)将被用作图标的名称
* 第二个参数是这是一个处理函数,用于处理加载的 SVG 内容。在这个例子中,它将 SVG 的开头替换为 <svg fill="currentColor" 。
* 这意味着图标的颜色会使用 CSS 的 currentColor 值,从而允许你通过 CSS 控制图标的颜色。
*/
home: FileSystemIconLoader(path.resolve('src', 'assets/home'), (svg) =>
svg.replace(/^<svg /, '<svg fill="currentColor" ')
)
}
}),
Components({
// Auto register Element Plus components
// 自动导入 Element Plus 组件
resolvers: [
ElementPlusResolver(),
// 自动导入 svg 图标 用来配合 `unplugin-icons` 使用的
IconsResolver({
// prefix: 'icon', // 自动引入的Icon组件统一前缀,默认为 i,设置false为不需要前缀
enabledCollections: ['ic'] // 这是可选的,默认启用 Iconify 支持的所有集合 以ic 模块为例
})
],
// 指定生成的 组件的 ts 文件目录
dts: path.resolve('types', 'components.d.ts'),
directives: true
})],
})
使用 vue 组件 @iconify/vue
如果使用的是vue3
bash
npm install --save-dev @iconify/vue
使用导入组件
js
import { Icon } from '@iconify/vue';
在vue 上使用
html
<Icon icon="mdi-light:home" />
这样使用之后会发现 使用svg 请求了连接 https://api.iconify.design/mdi-light.json?icons=home
当第二次刷新页面时候却没有了额外请求 此时会发现在 local storage 中多了两个 svg 信息
有这个额外请求的原因在当你使用 @iconify/vue
这个库时,它会默认地从 Iconify 的 CDN 加载图标。这意味着当你在你的 Vue 项目中使用一个图标时,它实际上是从 Iconify 的服务器上动态加载的,而不是直接从你的项目中加载的。这就是为什么会有一个 HTTP 请求的原因。
这种方法的优点是,你不需要在你的项目中包含所有的图标,从而减少了项目的大小。只有当你实际使用到某个图标时,它才会被加载。
但是,如果你不希望有这个 HTTP 请求,或者你希望图标离线可用,你可以考虑下载所需的图标并将其包含在你的项目中,或者使用其他不依赖 CDN 的图标解决方案。
使用本地 @iconify
图标库集合
以 ic 这个集合为例子下载集合
bash
npm install --save-dev @iconify-icons/ic
使用
vue
<template>
<Icon :icon="baseline5g" />
</template>
<script setup lang="ts">
import baseline5g from '@iconify-icons/ic/baseline-5g'
</script>
自定义自己的 cdn svg 集合网站
js
import { IconifyAPI } from '@iconify/vue';
// 设置自定义的 API endpoint
IconifyAPI.setAPIConfig('your-icon-set-name', {
// 你的 CDN URL,其中 {prefix} 和 {name} 是占位符
// {prefix} 是图标集的名称,{name} 是图标的名称
url: 'https://your-cdn.com/path/{prefix}/{name}.json',
});
总结
svg 是一种基于可扩展标记语言(XML)的图形格式,具有 不会失真 ,更小的体积。为了在项目中更好的使用 svg, vite + vue 这种形式下 有三种
unplugin-icons
, 能够识别本地 svg 文件,并且可以配合 iconify 图标库,利用 unplugin-auto-import
可以实现自动下载 使用到的 iconify 图标集
vite-plugin-svg-icons
, 针对本地 svg 图标插件管理,通过配合 封装的 svg 组件,利用其精灵图的特性可以优化 svg 数量
@iconify/vue
,一个已经封装好的 vue 组件用来直接使用 iconify 图标库,支持cdn 加载图片,并且会将加载后的图标存储在本地,也可以使用 本地下载好的 iconify 图标库