Support multiple js frameworks
Vue 2.x, Vue 3.x, React >= 16.8 icon components are provided by default, and components that support other frameworks can be written through @yzfe/svgicon
diff --git a/404.html b/404.html new file mode 100644 index 00000000..b0c33dd2 --- /dev/null +++ b/404.html @@ -0,0 +1,23 @@ + + +
+ + +404
But if you don't change your direction, and if you keep looking, you may end up where you are heading.
Parameters (attributes) of the function to generate SVG icon data
export interface Props {
+ /** icon data */
+ data?: Icon
+ width?: string | number
+ height?: string | number
+ scale?: string | number
+ /** icon direction */
+ dir?: string
+ color?: string | string[]
+ /** gradient stop colors */
+ stopColors?: string[]
+ title?: string
+ fill?: boolean
+ /** is use original color */
+ original?: boolean
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string
+}
Get the key array of props
export declare function getPropKeys(): (keyof Props)[];
Generate icon data based on the incoming attributes
declare function svgIcon(props: Props): SvgIconResult;
Global options, affecting the default value of props
/** Global default options */
+export interface Options {
+ classPrefix?: string
+ // Is stroke default
+ isStroke?: boolean
+ isOriginalDefault?: boolean
+ /** 16px, defined in css */
+ defaultWidth?: string
+ defaultHeight?: string
+}
Modify the default options
export declare function setOptions(newOptions: Options): void;
/** Global default options */
+export interface Options {
+ classPrefix?: string;
+ isStroke?: boolean;
+ isOriginalDefault?: boolean;
+ /** 16px, defined in css */
+ defaultWidth?: string;
+ defaultHeight?: string;
+}
+export interface OriginalColor {
+ type: 'fill' | 'stroke';
+ color: string;
+}
+export interface IconData {
+ width?: number | string;
+ height?: number | string;
+ viewBox: string;
+ data: string;
+ originalColors?: OriginalColor[];
+ stopColors?: string[];
+ [key: string]: unknown;
+}
+export interface Icon {
+ name: string;
+ data: IconData;
+}
+export interface Props {
+ /** icon data */
+ data?: Icon;
+ width?: string | number;
+ height?: string | number;
+ scale?: string | number;
+ /** icon direction */
+ dir?: string;
+ color?: string | string[];
+ /** gradient stop colors */
+ stopColors?: string[];
+ title?: string;
+ fill?: boolean;
+ /** is use original color */
+ original?: boolean;
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string;
+}
+/** SvgIcon function result type */
+export interface SvgIconResult {
+ /** SVG content */
+ path: string;
+ /** viewBox */
+ box: string;
+ className: string;
+ style: Record<string, string | number>;
+}
+/** set default options */
+export declare function setOptions(newOptions: Options): void;
+export declare function getOptions(): Options;
+export declare function getPropKeys(): (keyof Props)[];
+/** get svgicon result by props */
+export declare function svgIcon(props: Props): SvgIconResult;
Run in the nodejs environment to generate the Icon
object (The value of props.data)
import { OptimizeOptions } from 'svgo';
+import { Icon } from './types';
+export type SvgoConfig = OptimizeOptions;
+/**
+ * generate svgicon object
+ * @export
+ * @param {string} source svg file content
+ * @param {string} filename svg icon file absolute path
+ * @param {(string | string[])} [svgRootPath] svg icon root path, to calc relative path
+ * @param {SVGO.Options} [svgoConfig] svgo config
+ * @returns {Promise<Icon>}
+ */
+export default function gen(source: string, filename: string, svgRootPath?: string | string[], svgoConfig?: OptimizeOptions): Promise<Icon>;
TIP: You can directly use
@yzfe/svgicon-gen
to generate icon data in advance and save it as a js file, so that you don't need to load icons with@yzfe/svgicon-loader
.
Load the SVG file as icon data (vue) or SVG icon component (react), the generated code can be customized
export interface LoaderOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'taro' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: unknown
+}
export interface PluginOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: SvgoConfig
+ /** Svg files to be excluded, use minimatch */
+ exclude?: string | string[]
+ /** Svg files to be included, use minimatch */
+ include?: string | string[]
+ /** Match query which import icon with query string */
+ matchQuery?: RegExp
+}
Parameters (attributes) of the function to generate SVG icon data
export interface Props {
+ /** icon data */
+ data?: Icon
+ width?: string | number
+ height?: string | number
+ scale?: string | number
+ /** icon direction */
+ dir?: string
+ color?: string | string[]
+ /** gradient stop colors */
+ stopColors?: string[]
+ title?: string
+ fill?: boolean
+ /** is use original color */
+ original?: boolean
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string
+}
Get the key array of props
export declare function getPropKeys(): (keyof Props)[];
Generate icon data based on the incoming attributes
declare function svgIcon(props: Props): SvgIconResult;
Global options, affecting the default value of props
/** Global default options */
+export interface Options {
+ classPrefix?: string
+ // Is stroke default
+ isStroke?: boolean
+ isOriginalDefault?: boolean
+ /** 16px, defined in css */
+ defaultWidth?: string
+ defaultHeight?: string
+}
Modify the default options
export declare function setOptions(newOptions: Options): void;
/** Global default options */
+export interface Options {
+ classPrefix?: string;
+ isStroke?: boolean;
+ isOriginalDefault?: boolean;
+ /** 16px, defined in css */
+ defaultWidth?: string;
+ defaultHeight?: string;
+}
+export interface OriginalColor {
+ type: 'fill' | 'stroke';
+ color: string;
+}
+export interface IconData {
+ width?: number | string;
+ height?: number | string;
+ viewBox: string;
+ data: string;
+ originalColors?: OriginalColor[];
+ stopColors?: string[];
+ [key: string]: unknown;
+}
+export interface Icon {
+ name: string;
+ data: IconData;
+}
+export interface Props {
+ /** icon data */
+ data?: Icon;
+ width?: string | number;
+ height?: string | number;
+ scale?: string | number;
+ /** icon direction */
+ dir?: string;
+ color?: string | string[];
+ /** gradient stop colors */
+ stopColors?: string[];
+ title?: string;
+ fill?: boolean;
+ /** is use original color */
+ original?: boolean;
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string;
+}
+/** SvgIcon function result type */
+export interface SvgIconResult {
+ /** SVG content */
+ path: string;
+ /** viewBox */
+ box: string;
+ className: string;
+ style: Record<string, string | number>;
+}
+/** set default options */
+export declare function setOptions(newOptions: Options): void;
+export declare function getOptions(): Options;
+export declare function getPropKeys(): (keyof Props)[];
+/** get svgicon result by props */
+export declare function svgIcon(props: Props): SvgIconResult;
Run in the nodejs environment to generate the Icon
object (The value of props.data)
import { OptimizeOptions } from 'svgo';
+import { Icon } from './types';
+export type SvgoConfig = OptimizeOptions;
+/**
+ * generate svgicon object
+ * @export
+ * @param {string} source svg file content
+ * @param {string} filename svg icon file absolute path
+ * @param {(string | string[])} [svgRootPath] svg icon root path, to calc relative path
+ * @param {SVGO.Options} [svgoConfig] svgo config
+ * @returns {Promise<Icon>}
+ */
+export default function gen(source: string, filename: string, svgRootPath?: string | string[], svgoConfig?: OptimizeOptions): Promise<Icon>;
TIP: You can directly use
@yzfe/svgicon-gen
to generate icon data in advance and save it as a js file, so that you don't need to load icons with@yzfe/svgicon-loader
.
Load the SVG file as icon data (vue) or SVG icon component (react), the generated code can be customized
export interface LoaderOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'taro' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: unknown
+}
export interface PluginOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: SvgoConfig
+ /** Svg files to be excluded, use minimatch */
+ exclude?: string | string[]
+ /** Svg files to be included, use minimatch */
+ include?: string | string[]
+ /** Match query which import icon with query string */
+ matchQuery?: RegExp
+}
=0)c=r.activeElement;else{var f=i.tabbableGroups[0],p=f&&f.firstTabbableNode;c=p||d("fallbackFocus")}if(!c)throw new Error("Your focus-trap needs to have at least one focusable element");return c},v=function(){if(i.containerGroups=i.containers.map(function(c){var f=gr(c,a.tabbableOptions),p=br(c,a.tabbableOptions),N=f.length>0?f[0]:void 0,I=f.length>0?f[f.length-1]:void 0,M=p.find(function(m){return le(m)}),P=p.slice().reverse().find(function(m){return le(m)}),z=!!f.find(function(m){return se(m)>0});return{container:c,tabbableNodes:f,focusableNodes:p,posTabIndexesFound:z,firstTabbableNode:N,lastTabbableNode:I,firstDomTabbableNode:M,lastDomTabbableNode:P,nextTabbableNode:function(x){var $=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,j=f.indexOf(x);return j<0?$?p.slice(p.indexOf(x)+1).find(function(G){return le(G)}):p.slice(0,p.indexOf(x)).reverse().find(function(G){return le(G)}):f[j+($?1:-1)]}}}),i.tabbableGroups=i.containerGroups.filter(function(c){return c.tabbableNodes.length>0}),i.tabbableGroups.length<=0&&!d("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(i.containerGroups.find(function(c){return c.posTabIndexesFound})&&i.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")},y=function w(c){var f=c.activeElement;if(f)return f.shadowRoot&&f.shadowRoot.activeElement!==null?w(f.shadowRoot):f},b=function w(c){if(c!==!1&&c!==y(document)){if(!c||!c.focus){w(h());return}c.focus({preventScroll:!!a.preventScroll}),i.mostRecentlyFocusedNode=c,Sr(c)&&c.select()}},S=function(c){var f=d("setReturnFocus",c);return f||(f===!1?!1:c)},g=function(c){var f=c.target,p=c.event,N=c.isBackward,I=N===void 0?!1:N;f=f||Ae(p),v();var M=null;if(i.tabbableGroups.length>0){var P=l(f,p),z=P>=0?i.containerGroups[P]:void 0;if(P<0)I?M=i.tabbableGroups[i.tabbableGroups.length-1].lastTabbableNode:M=i.tabbableGroups[0].firstTabbableNode;else if(I){var m=ft(i.tabbableGroups,function(B){var J=B.firstTabbableNode;return f===J});if(m<0&&(z.container===f||Oe(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!z.nextTabbableNode(f,!1))&&(m=P),m>=0){var x=m===0?i.tabbableGroups.length-1:m-1,$=i.tabbableGroups[x];M=se(f)>=0?$.lastTabbableNode:$.lastDomTabbableNode}else ge(p)||(M=z.nextTabbableNode(f,!1))}else{var j=ft(i.tabbableGroups,function(B){var J=B.lastTabbableNode;return f===J});if(j<0&&(z.container===f||Oe(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!z.nextTabbableNode(f))&&(j=P),j>=0){var G=j===i.tabbableGroups.length-1?0:j+1,q=i.tabbableGroups[G];M=se(f)>=0?q.firstTabbableNode:q.firstDomTabbableNode}else ge(p)||(M=z.nextTabbableNode(f))}}else M=d("fallbackFocus");return M},A=function(c){var f=Ae(c);if(!(l(f,c)>=0)){if(me(a.clickOutsideDeactivates,c)){s.deactivate({returnFocus:a.returnFocusOnDeactivate});return}me(a.allowOutsideClick,c)||c.preventDefault()}},C=function(c){var f=Ae(c),p=l(f,c)>=0;if(p||f instanceof Document)p&&(i.mostRecentlyFocusedNode=f);else{c.stopImmediatePropagation();var N,I=!0;if(i.mostRecentlyFocusedNode)if(se(i.mostRecentlyFocusedNode)>0){var M=l(i.mostRecentlyFocusedNode),P=i.containerGroups[M].tabbableNodes;if(P.length>0){var z=P.findIndex(function(m){return m===i.mostRecentlyFocusedNode});z>=0&&(a.isKeyForward(i.recentNavEvent)?z+1
@yzfe/svgicon-loader
or vite-plugin-svgicon
both provide component
and customCode
options to import svg files as components.
component
vue
Vue 3.x Componentreact
React Componentcustom
Custom generated code, used with customCode
// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, 'src/assets/svg'),
+ component: 'react',
+ })
+ ]
+})
Usage
import ArrowIcon from 'svg-icon-path/arrow.svg'
+export default funtion() {
+ return (
+ <div>
+ <ArrowIcon color="red" />
+ </div>
+ )
+}
Customize the generated code by setting the component
and customCode
options. The @yzfe/svgicon-loader
or vite-plugin-svgicon
has already generated a code snippet: const data = {/*iconData*/}
. Finally, this code snippet will be concatenated with the customCode
to form the final code.
// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, 'src/assets/svg'),
+ component: 'custom',
+ customCode: \`
+ import Vue from 'vue'
+ import { VueSvgIcon } from '@yzfe/vue-svgicon'
+
+ export default {
+ functional: true,
+ render(h, context) {
+ return h(VueSvgIcon, {
+ ...context.data,
+ data: data
+ })
+ }
+ }
+ \`
+ })
+ ]
+})
The above configuration loads the svg file as the code below
const data = {/*iconData*/}
+import Vue from 'vue'
+import { VueSvgIcon } from '@yzfe/vue-svgicon'
+
+export default {
+ functional: true,
+ render(h, context) {
+ return h(VueSvgIcon, {
+ ...context.data,
+ data: data
+ })
+ }
+}
WARNING
If you are using @yzfe/svgicon-loader
, you need to add babel-loader
to process the generated code.
// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, '../../packages/assets/svg'),
+ }),
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ // macth: xxx.svg?component
+ matchQuery: /component/,
+ svgFilePath: path.join(__dirname, '../../packages/assets'),
+ component: 'vue',
+ }),
+ svgicon({
+ include: ['**/assets/font-awesome/**/*.svg'],
+ svgFilePath: path.join(
+ __dirname,
+ '../../packages/assets/font-awesome'
+ ),
+ }),
+ ]
+})
Usage
// import as icon data
+import ArrowIconData from '@/assets/svg/arrow.svg'
+import FaArrowIconData from '@/assets/font-awesome/arrow.svg'
+
+// import as component
+import ArrowIcon from 'svg-icon-path/arrow.svg?component'
+
+// import as url
+import ArrowSvgUrl from 'svg-icon-path/arrow.svg?url'
If SVG file is imported as a component, the type definition of the component needs to be added.
// react
+declare module '@/assets/svg/*.svg' {
+ import { ReactSvgIconFC } from '@yzfe/react-svgicon'
+ const value: ReactSvgIconFC
+ export = value
+}
+
+// vue
+declare module '@/assets/svg/*.svg' {
+ import { VueSvgIcon } from '@yzfe/vue-svgicon'
+ const value: typeof VueSvgIcon
+ export = value
+}
If your project uses vue-cli
, it is recommended to use @yzfe/vue-cli-plugin-svgicon
for quick configuration.
# You will be prompted to fill in the SVG file path, the globally registered component tag name and the vue version
+vue add @yzfe/svgicon
If you have installed @yzfe/vue-cli-plugin-svgicon
, but this plugin is not invoked, you can invoke it manually.
vue invoke @yzfe/svgicon
After a successful invoke, the necessary dependencies and code will be automatically added, and a .vue-svgicon.config.js
file will be generated to configure @yzfe/svgicon-loader
and webpack aliases, as well as transformAssetUrls, etc.
const path = require('path')
+const svgFilePaths = ['src/assets/svgicon'].map((v) => path.resolve(v))
+const tagName = 'icon'
+
+module.exports = {
+ tagName,
+ svgFilePath: svgFilePaths,
+ svgoConfig: {},
+ pathAlias: {
+ '@icon': svgFilePaths[0],
+ },
+ transformAssetUrls: {
+ [tagName]: ['data'],
+ },
+ loaderOptions: {},
+}
<demo-wrap :title="$attrs.title" :style="{ color: 'orange' }">
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ color="red"
+ />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ color="green"
+ />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ color="blue"
+ />
+</demo-wrap>
Clock icon: the circle is the fill, the hour and minute hands are the stroke, Vue icon: the first path is the stroke, the second is the path is the fill
<demo-wrap :title="$attrs.title">
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="50"
+ height="50"
+ color="r-red"
+ />
+ <icon
+ data="@icon/clock.svg"
+ width="50"
+ height="50"
+ color="#8A99B2 r-#1C2330"
+ />
+ <!-- use css var -->
+ <icon
+ data="@icon/clock.svg"
+ width="50"
+ height="50"
+ color="#8A99B2 r-var(--color-bg-primary)"
+ />
+ <icon
+ data="@icon/vue.svg"
+ width="50"
+ height="50"
+ :fill="false"
+ color="#42b983 r-#42b983"
+ />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon
+ data="@icon/check.svg"
+ width="80"
+ height="80"
+ color="#42b983 r-white"
+ />
+ <icon
+ data="@icon/colorwheel.svg"
+ width="80"
+ height="80"
+ color="#FBAD20 #F5EB13 #B8D433 #6BC9C6 #058BC5 #34469D #7E4D9F #C63D96 #ED1944"
+ />
+ <!-- Use array -->
+ <icon
+ data="@icon/colorwheel.svg"
+ width="80"
+ height="80"
+ :color="[
+ 'rgba(0, 0, 100, .5)',
+ '#F5EB13',
+ '#B8D433',
+ '#6BC9C6',
+ '#058BC5',
+ '#34469D',
+ '#7E4D9F',
+ '#C63D96',
+ '#ED1944',
+ ]"
+ />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon data="@icon/colorwheel.svg" width="60" height="60" original />
+ <!-- overwrite original color -->
+ <icon
+ data="@icon/colorwheel.svg"
+ width="60"
+ height="60"
+ original
+ color="_ black _ black _"
+ />
+ <icon
+ data="@icon/colorwheel.svg"
+ width="60"
+ height="60"
+ original
+ color="_ r-black _ r-red _"
+ />
+ <icon data="@icon/gift.svg" width="60" height="60" original />
+</demo-wrap>
`,2),w=a(`The second and third color wheels modify certain colors based on the primary colors
<svg style="position: absolute; width: 0; opacity: 0">
+ <defs>
+ <linearGradient id="gradient-1" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="5%" stop-color="#57f0c2" />
+ <stop offset="95%" stop-color="#147d58" />
+ </linearGradient>
+ <linearGradient id="gradient-2" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="5%" stop-color="#7295c2" />
+ <stop offset="95%" stop-color="#252e3d" />
+ </linearGradient>
+ </defs>
+</svg>
+<demo-wrap :title="$attrs.title">
+ <icon
+ data="@icon/vue.svg"
+ width="100"
+ height="100"
+ color="url(#gradient-1) url(#gradient-2)"
+ ></icon>
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon
+ data="@icon/gift.svg"
+ width="60" height="60"
+ original
+ :stop-colors="['blue', 'green']" />
+</demo-wrap>
The
original
porp must to be true
<demo-wrap :title="$attrs.title" :style="{ fontSize: '12px' }">
+ <icon data="@fa/solid/arrow-up.svg" />
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon data="@fa/solid/arrow-up.svg" width="4em" height="4em" />
+ <icon data="@fa/solid/arrow-up.svg" width="4rem" height="4rem" />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon
+ :fill="false"
+ class="stroke-icon"
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ />
+</demo-wrap>
<style>
+.stroke-icon path[pid='0'] {
+ stroke-width: 10px;
+}
+</style>
<demo-wrap :title="$attrs.title">
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ dir="right"
+ />
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" dir="down" />
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" dir="left" />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon
+ class="icon"
+ data="@icon/colorwheel.svg"
+ width="80"
+ height="80"
+ original
+ :replace="(svg) => svg.replace('#34469D', 'var(--color-white)')"
+ />
+</demo-wrap>
This section provides a brief introduction to the configuration and usage of svgicon
. For more in-depth information, it is recommended to refer to the "In-Depth" section to gain a deeper understanding.
svgicon is a name
svgicon is SVG icon component and tool set. It turns SVG files into icon data (vue) or icon components (react), allowing you to happily use SVG icons in your projects, whether you are using vue, react, vue3.x or Other js frameworks. svgicon includes the following npm packages:
Generate the data required by the SVG icon component according to the incoming parameters (props)
SVG icon component for vue
SVG icon component for react
Generate icon data (icon name and processed SVG content) based on the content of the SVG file
Load the SVG file as icon data (vue) or SVG icon component (react), the generated code can be customized
vite plugin,like @yzfe/svgicon-loader
Preview SVG icon
A vue-cli plugin that can quickly configure svgicon
SVG innerHTML compatible (IE)
Use vite-plugin-svgicon
to load svg files as icon data
npm install vite-plugin-svgicon -D
// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, 'src/assets/svg'),
+ // If you are using react, it is recommended to configure the component option for react and load the svg file as react components.
+ component: 'react',
+ })
+ ]
+})
Use @yzfe/svgicon-loader
to load svg files as icon data
npm install @yzfe/svgicon-loader -D
// webpack.config.js
+{
+ module: {
+ rules: [
+ {
+ test: /\\.svg$/,
+ include: ['SVG file path'],
+ use: [
+ 'babel-loader',
+ {
+ loader: '@yzfe/svgicon-loader',
+ options: {
+ svgFilePath: ['SVG file path'],
+ // Custom svgo configuration
+ svgoConfig: null,
+ // If you are using react, it is recommended to configure the component option for react and load the svg file as react components.
+ component: 'react',
+ }
+ }
+ ]
+ },
+ ]
+ }
+}
Use vue-cli
import arrowData from 'svg-file-path/arrow.svg'
+// {name: 'arrow', data: {width: 16, height: 16, ...}}
+console.log(arrowData)
npm install @yzfe/svgicon @yzfe/vue-svgicon --save
// main.js
+import { VueSvgIcon } from '@yzfe/vue-svgicon'
+
+// Import style
+import '@yzfe/svgicon/lib/svgicon.css'
+// Global component
+Vue.component('icon', VueSvgIcon)
<template>
+ <div>
+ <icon :data="arrowData" />
+ <!-- It is recommended to configure transformAssetUrls,. You can directly pass in the svg file path. -->
+ <icon data="svg-file-path/arrow.svg" />
+ </div>
+</template>
+<script>
+import arrowData from 'svg-file-path/arrow.svg'
+export default {
+ data() {
+ return: {
+ arrowData
+ }
+ }
+}
+</script>
npm install @yzfe/svgicon @yzfe/vue-svgicon --save
// main.ts
+import { VueSvgIconPlugin } from '@yzfe/vue-svgicon'
+// Import style
+import '@yzfe/svgicon/lib/svgicon.css'
+// Global component
+app.use(VueSvgIconPlugin, {tagName: 'icon'})
<script setup lang="ts">
+import arrowData from 'svg-file-path/arrow.svg'
+</script>
+<template>
+ <div>
+ <icon :data="arrowData" />
+ <!-- It is recommended to configure transformAssetUrls,. You can directly pass in the svg file path. -->
+ <icon data="svg-file-path/arrow.svg" />
+ </div>
+</template>
npm install @yzfe/svgicon @yzfe/react-svgicon --save
import '@yzfe/svgicon/lib/svgicon.css'
import ArrowIcon from 'svg-file-path/arrow.svg'
+
+export default function FC() {
+ return (
+ <div>
+ <ArrowIcon color="red" />
+ </div>
+ )
+}
Other frameworks can use @yzfe/svgicon
to write icon components suitable for their frameworks, please refer to @yzfe/react-svgicon
.
import React from 'react'
+import {
+ svgIcon,
+ Props,
+ Options,
+ setOptions,
+ getPropKeys,
+ Icon,
+ IconData,
+} from '@yzfe/svgicon'
+
+interface ComponentProps extends Props {
+ [key: string]: unknown
+}
+
+class ReactSvgIcon extends React.PureComponent<ComponentProps> {
+ public render(): JSX.Element {
+ const props = this.props
+ const result = svgIcon(props)
+ const attrs: Record<string, unknown> = {}
+
+ if (props) {
+ const propsKeys = getPropKeys()
+ for (const key in props) {
+ if (propsKeys.indexOf(key as keyof Props) < 0) {
+ attrs[key] = props[key]
+ }
+ }
+ }
+
+ attrs.viewBox = result.box
+ attrs.className = (attrs.className || '') + \` \${result.className}\`
+ attrs.style = {
+ ...((attrs.style as Record<string, string>) || {}),
+ ...result.style,
+ }
+
+ return (
+ <svg
+ {...attrs}
+ dangerouslySetInnerHTML={{ __html: result.path }}
+ ></svg>
+ )
+ }
+}
+
+/** SvgIcon function component, define in @yzfe/svgicon-loader compile */
+interface ReactSvgIconFC extends React.FC<ComponentProps> {
+ iconName: string
+ iconData: IconData
+}
+
+export {
+ ReactSvgIcon,
+ ReactSvgIconFC,
+ Props,
+ Options,
+ Icon,
+ IconData,
+ setOptions,
+}
Use @yzfe/svgicon-viewer
to preview SVG files in any folder.
# Global installation
+yarn global add @yzfe/svgicon-viewer
# svgicon-viewer <svgFilePath> [metaFile]
+svgicon-viewer ./src/assets/svg
Use meta.json to add additional information. Currently, only one name field is supported, which can be used to describe the icon.
// meta.json demo
+{
+ "arrow": {
+ "name": "箭头"
+ }
+}
svgicon-viewer ./src/assets/svg ./src/assets/svg/meta.json
svgicon-viewer ./src/assets/svg -o ./dist
生成 SVG 图标数据函数的参数(属性)
export interface Props {
+ /** icon data */
+ data?: Icon
+ width?: string | number
+ height?: string | number
+ scale?: string | number
+ /** icon direction */
+ dir?: string
+ color?: string | string[]
+ /** gradient stop colors */
+ stopColors?: string[]
+ title?: string
+ fill?: boolean
+ /** is use original color */
+ original?: boolean
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string
+}
获取 props 的 key 数组
export declare function getPropKeys(): (keyof Props)[];
根据传入的属性生成图标数据
declare function svgIcon(props: Props): SvgIconResult;
全局配置,影响 props 的默认值
/** Global default options */
+export interface Options {
+ classPrefix?: string
+ // Is stroke default
+ isStroke?: boolean
+ isOriginalDefault?: boolean
+ /** 16px, defined in css */
+ defaultWidth?: string
+ defaultHeight?: string
+}
修改默认选项
export declare function setOptions(newOptions: Options): void;
/** Global default options */
+export interface Options {
+ classPrefix?: string;
+ isStroke?: boolean;
+ isOriginalDefault?: boolean;
+ /** 16px, defined in css */
+ defaultWidth?: string;
+ defaultHeight?: string;
+}
+export interface OriginalColor {
+ type: 'fill' | 'stroke';
+ color: string;
+}
+export interface IconData {
+ width?: number | string;
+ height?: number | string;
+ viewBox: string;
+ data: string;
+ originalColors?: OriginalColor[];
+ stopColors?: string[];
+ [key: string]: unknown;
+}
+export interface Icon {
+ name: string;
+ data: IconData;
+}
+export interface Props {
+ /** icon data */
+ data?: Icon;
+ width?: string | number;
+ height?: string | number;
+ scale?: string | number;
+ /** icon direction */
+ dir?: string;
+ color?: string | string[];
+ /** gradient stop colors */
+ stopColors?: string[];
+ title?: string;
+ fill?: boolean;
+ /** is use original color */
+ original?: boolean;
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string;
+}
+/** SvgIcon function result type */
+export interface SvgIconResult {
+ /** SVG content */
+ path: string;
+ /** viewBox */
+ box: string;
+ className: string;
+ style: Record<string, string | number>;
+}
+/** set default options */
+export declare function setOptions(newOptions: Options): void;
+export declare function getOptions(): Options;
+export declare function getPropKeys(): (keyof Props)[];
+/** get svgicon result by props */
+export declare function svgIcon(props: Props): SvgIconResult;
在 nodejs 环境中运行,生成 Icon
对象 (props.data 的值)
import { OptimizeOptions } from 'svgo';
+import { Icon } from './types';
+export type SvgoConfig = OptimizeOptions;
+/**
+ * generate svgicon object
+ * @export
+ * @param {string} source svg file content
+ * @param {string} filename svg icon file absolute path
+ * @param {(string | string[])} [svgRootPath] svg icon root path, to calc relative path
+ * @param {SVGO.Options} [svgoConfig] svgo config
+ * @returns {Promise<Icon>}
+ */
+export default function gen(source: string, filename: string, svgRootPath?: string | string[], svgoConfig?: OptimizeOptions): Promise<Icon>;
TIP: 你可以直接使用
@yzfe/svgicon-gen
预先生成图标数据,保存为 js 文件,这样可以不用@yzfe/svgicon-loader
加载图标了。
将 SVG 文件加载成图标数据(vue)或者 SVG 图标组件(react), 可以自定义生成的代码
export interface LoaderOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'taro' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: unknown
+}
export interface PluginOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: SvgoConfig
+ /** Svg files to be excluded, use minimatch */
+ exclude?: string | string[]
+ /** Svg files to be included, use minimatch */
+ include?: string | string[]
+ /** Match query which import icon with query string */
+ matchQuery?: RegExp
+}
@yzfe/svgicon-loader
或者 vite-plugin-svgicon
都提供 component
和 customCode
选项将 SVG 文件作为组件导入。
component
选项可选值 vue
Vue 3.x 组件react
React 组件custom
自定义生成的代码, 与 customCode
配搭使用// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, 'src/assets/svg'),
+ component: 'react',
+ })
+ ]
+})
用法
import ArrowIcon from 'svg-icon-path/arrow.svg'
+export default funtion() {
+ return (
+ <div>
+ <ArrowIcon color="red" />
+ </div>
+ )
+}
通过设置 component
为 custom
和配置 customCode
来自定义生成的代码。@yzfe/svgicon-loader
或 vite-plugin-svgicon
已预先生成代码片段,const data = {/*iconData*/}
,最后会将这段代码与 customCode
拼接作为最终的代码。
// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, 'src/assets/svg'),
+ component: 'custom',
+ customCode: \`
+ import Vue from 'vue'
+ import { VueSvgIcon } from '@yzfe/vue-svgicon'
+
+ export default {
+ functional: true,
+ render(h, context) {
+ return h(VueSvgIcon, {
+ ...context.data,
+ data: data
+ })
+ }
+ }
+ \`
+ })
+ ]
+})
上述配置将 SVG 文件加载为下面的代码:
const data = {/*iconData*/}
+import Vue from 'vue'
+import { VueSvgIcon } from '@yzfe/vue-svgicon'
+
+export default {
+ functional: true,
+ render(h, context) {
+ return h(VueSvgIcon, {
+ ...context.data,
+ data: data
+ })
+ }
+}
WARNING
如果使用的是 @yzfe/svgicon-loader
, 需要加上 babel-loader
处理生成的代码。
// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, '../../packages/assets/svg'),
+ }),
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ // 匹配: xxx.svg?component
+ matchQuery: /component/,
+ svgFilePath: path.join(__dirname, '../../packages/assets'),
+ component: 'vue',
+ }),
+ svgicon({
+ include: ['**/assets/font-awesome/**/*.svg'],
+ svgFilePath: path.join(
+ __dirname,
+ '../../packages/assets/font-awesome'
+ ),
+ }),
+ ]
+})
用法
// 导入为图标数据
+import ArrowIconData from '@/assets/svg/arrow.svg'
+import FaArrowIconData from '@/assets/font-awesome/arrow.svg'
+
+// 导入为组件
+import ArrowIcon from 'svg-icon-path/arrow.svg?component'
+
+// 导入为路径
+import ArrowSvgUrl from 'svg-icon-path/arrow.svg?url'
如果配置 SVG 文件作为组件导入,需要加上组件的类型定义。
// react
+declare module '@/assets/svg/*.svg' {
+ import { ReactSvgIconFC } from '@yzfe/react-svgicon'
+ const value: ReactSvgIconFC
+ export = value
+}
+
+// vue
+declare module '@/assets/svg/*.svg' {
+ import { VueSvgIcon } from '@yzfe/vue-svgicon'
+ const value: typeof VueSvgIcon
+ export = value
+}
如果你的项目使用 vue-cli
, 推荐使用 @yzfe/vue-cli-plugin-svgicon
进行快速配置。
# 将会提示你填写 SVG 文件路径,全局注册的组件标签名称和 vue 的版本
+vue add @yzfe/svgicon
如果已经安装了 @yzfe/vue-cli-plugin-svgicon
, 但是没有调用到这个插件,你可以手动调用。
vue invoke @yzfe/svgicon
成功调用后,会自动添加必要的依赖和代码,另外还会生成 .vue-svgicon.config.js
文件,用来配置 @yzfe/svgicon-loader
和 webpack
别名,还有 transformAssetUrls
等。
const path = require('path')
+const svgFilePaths = ['src/assets/svgicon'].map((v) => path.resolve(v))
+const tagName = 'icon'
+
+module.exports = {
+ tagName,
+ svgFilePath: svgFilePaths,
+ svgoConfig: {},
+ pathAlias: {
+ '@icon': svgFilePaths[0],
+ },
+ transformAssetUrls: {
+ [tagName]: ['data'],
+ },
+ loaderOptions: {},
+}
<demo-wrap :title="$attrs.title" :style="{ color: 'orange' }">
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ color="red"
+ />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ color="green"
+ />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ color="blue"
+ />
+</demo-wrap>
颜色值加上 r-
前缀,反转当前 fill 属性
时钟图标:圆形是填充,时针分针是描边, Vue 图标:第一个 path 是描边,第二个是 path 是填充
<demo-wrap :title="$attrs.title">
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="50"
+ height="50"
+ color="r-red"
+ />
+ <icon
+ data="@icon/clock.svg"
+ width="50"
+ height="50"
+ color="#8A99B2 r-#1C2330"
+ />
+ <!-- use css var -->
+ <icon
+ data="@icon/clock.svg"
+ width="50"
+ height="50"
+ color="#8A99B2 r-var(--color-bg-primary)"
+ />
+ <icon
+ data="@icon/vue.svg"
+ width="50"
+ height="50"
+ :fill="false"
+ color="#42b983 r-#42b983"
+ />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon
+ data="@icon/check.svg"
+ width="80"
+ height="80"
+ color="#42b983 r-white"
+ />
+ <icon
+ data="@icon/colorwheel.svg"
+ width="80"
+ height="80"
+ color="#FBAD20 #F5EB13 #B8D433 #6BC9C6 #058BC5 #34469D #7E4D9F #C63D96 #ED1944"
+ />
+ <!-- Use array -->
+ <icon
+ data="@icon/colorwheel.svg"
+ width="80"
+ height="80"
+ :color="[
+ 'rgba(0, 0, 100, .5)',
+ '#F5EB13',
+ '#B8D433',
+ '#6BC9C6',
+ '#058BC5',
+ '#34469D',
+ '#7E4D9F',
+ '#C63D96',
+ '#ED1944',
+ ]"
+ />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon data="@icon/colorwheel.svg" width="60" height="60" original />
+ <!-- overwrite original color -->
+ <icon
+ data="@icon/colorwheel.svg"
+ width="60"
+ height="60"
+ original
+ color="_ black _ black _"
+ />
+ <icon
+ data="@icon/colorwheel.svg"
+ width="60"
+ height="60"
+ original
+ color="_ r-black _ r-red _"
+ />
+ <icon data="@icon/gift.svg" width="60" height="60" original />
+</demo-wrap>
`,2),w=a(`第二和第三个色轮是在原色的基础上修改某些颜色
<svg style="position: absolute; width: 0; opacity: 0">
+ <defs>
+ <linearGradient id="gradient-1" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="5%" stop-color="#57f0c2" />
+ <stop offset="95%" stop-color="#147d58" />
+ </linearGradient>
+ <linearGradient id="gradient-2" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="5%" stop-color="#7295c2" />
+ <stop offset="95%" stop-color="#252e3d" />
+ </linearGradient>
+ </defs>
+</svg>
+<demo-wrap :title="$attrs.title">
+ <icon
+ data="@icon/vue.svg"
+ width="100"
+ height="100"
+ color="url(#gradient-1) url(#gradient-2)"
+ ></icon>
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon
+ data="@icon/gift.svg"
+ width="60" height="60"
+ original
+ :stop-colors="['blue', 'green']" />
+</demo-wrap>
original
必须是 true 才有效果
<demo-wrap :title="$attrs.title">
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon
+ :fill="false"
+ class="stroke-icon"
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ />
+</demo-wrap>
<style>
+.stroke-icon path[pid='0'] {
+ stroke-width: 10px;
+}
+</style>
<demo-wrap :title="$attrs.title" :style="{ fontSize: '12px' }">
+ <icon data="@fa/solid/arrow-up.svg" />
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon data="@fa/solid/arrow-up.svg" width="4em" height="4em" />
+ <icon data="@fa/solid/arrow-up.svg" width="4rem" height="4rem" />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" />
+ <icon
+ data="@fa/solid/arrow-up.svg"
+ width="36"
+ height="36"
+ dir="right"
+ />
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" dir="down" />
+ <icon data="@fa/solid/arrow-up.svg" width="36" height="36" dir="left" />
+</demo-wrap>
<demo-wrap :title="$attrs.title">
+ <icon
+ class="icon"
+ data="@icon/colorwheel.svg"
+ width="80"
+ height="80"
+ original
+ :replace="(svg) => svg.replace('#34469D', 'var(--color-white)')"
+ />
+</demo-wrap>
本节内容主要是简单的介绍 svgicon 配置和使用,建议查看【深入】这一节了解更多。
svgicon 是一个名称
svgicon 是 SVG 图标组件和工具集,将 SVG 文件变成图标数据(vue)或者图标组件(react),让你可以愉快的在项目中使用 SVG 图标,无论你是使用 vue, react, vue3.x, taro 还是其他 js 框架。svgicon 包括了以下的 npm 包:
根据传入的参数(props)生成 SVG 图标组件需要的数据
适用于 Vue 的 SVG 图标组件
适用于 React 的 SVG 图标组件
适用于 TaroJs 的 SVG 图标组件
根据 SVG 文件内容,生成图标数据(图标名称和处理过的 SVG 内容)
将 SVG 文件加载成图标数据(vue)或者 SVG 图标组件(react), 可以自定义生成的代码
vite 插件,功能与 @yzfe/svgicon-loader 类似
预览 SVG 图标
vue-cli 插件,可以快速的配置 svgicon
SVG innerHTML 兼容(IE)
使用 vite-plugin-svgicon 加载 SVG 文件为图标数据
npm install vite-plugin-svgicon -D
// vite.config.ts
+import { defineConfig } from 'vite'
+import svgicon from 'vite-plugin-svgicon'
+
+export default defineConfig({
+ plugins: [
+ svgicon({
+ include: ['**/assets/svg/**/*.svg'],
+ svgFilePath: path.join(__dirname, 'src/assets/svg'),
+ // 如果是使用 React,建议配置 component 选项为 react, 加载 SVG 文件为 react 组件
+ component: 'react',
+ })
+ ]
+})
使用 @yzfe/svgicon-loader 加载 SVG 文件为图标数据
npm install @yzfe/svgicon-loader -D
// webpack.config.js
+{
+ module: {
+ rules: [
+ {
+ test: /\\.svg$/,
+ include: ['SVG 文件路径'],
+ use: [
+ 'babel-loader',
+ {
+ loader: '@yzfe/svgicon-loader',
+ options: {
+ svgFilePath: ['SVG 文件路径'],
+ // 自定义 svgo 配置
+ svgoConfig: null,
+ // 如果是使用 React,建议配置 component 选项为 react, 加载 SVG 文件为 react 组件
+ component: 'react',
+ }
+ }
+ ]
+ },
+ ]
+ }
+}
使用 vue-cli
import arrowData from 'svg-file-path/arrow.svg'
+// {name: 'arrow', data: {width: 16, height: 16, ...}}
+console.log(arrowData)
npm install @yzfe/svgicon @yzfe/vue-svgicon --save
// main.js
+import { VueSvgIcon } from '@yzfe/vue-svgicon'
+
+// 引入 css 样式
+import '@yzfe/svgicon/lib/svgicon.css'
+// 注册全局组件
+Vue.component('icon', VueSvgIcon)
<template>
+ <div>
+ <icon :data="arrowData" />
+ <!-- 建议配置 transformAssetUrls, 可以直接传入 SVG 文件路径 -->
+ <icon data="svg-file-path/arrow.svg" />
+ </div>
+</template>
+<script>
+import arrowData from 'svg-file-path/arrow.svg'
+export default {
+ data() {
+ return: {
+ arrowData
+ }
+ }
+}
+</script>
npm install @yzfe/svgicon @yzfe/vue-svgicon --save
// main.ts
+import { VueSvgIconPlugin } from '@yzfe/vue-svgicon'
+// 引入 css 样式
+import '@yzfe/svgicon/lib/svgicon.css'
+// 注册全局组件
+app.use(VueSvgIconPlugin, {tagName: 'icon'})
<script setup lang="ts">
+import arrowData from 'svg-file-path/arrow.svg'
+</script>
+<template>
+ <div>
+ <icon :data="arrowData" />
+ <!-- 建议配置 transformAssetUrls, 可以直接传入 SVG 文件路径 -->
+ <icon data="svg-file-path/arrow.svg" />
+ </div>
+</template>
npm install @yzfe/svgicon @yzfe/react-svgicon --save
import '@yzfe/svgicon/lib/svgicon.css'
import ArrowIcon from 'svg-file-path/arrow.svg'
+
+export default function FC() {
+ return (
+ <div>
+ <ArrowIcon color="red" />
+ </div>
+ )
+}
npm install @yzfe/svgicon @yzfe/taro-svgicon
TaroJs 使用方式与 React 一致,请参考 React 一节
其他 js 框架可以通过 @yzfe/svgicon
编写适用于其框架的图标组件,可以参考 @yzfe/react-svgicon
.
import React from 'react'
+import {
+ svgIcon,
+ Props,
+ Options,
+ setOptions,
+ getPropKeys,
+ Icon,
+ IconData,
+} from '@yzfe/svgicon'
+
+interface ComponentProps extends Props {
+ [key: string]: unknown
+}
+
+class ReactSvgIcon extends React.PureComponent<ComponentProps> {
+ public render(): JSX.Element {
+ const props = this.props
+ const result = svgIcon(props)
+ const attrs: Record<string, unknown> = {}
+
+ if (props) {
+ const propsKeys = getPropKeys()
+ for (const key in props) {
+ if (propsKeys.indexOf(key as keyof Props) < 0) {
+ attrs[key] = props[key]
+ }
+ }
+ }
+
+ attrs.viewBox = result.box
+ attrs.className = (attrs.className || '') + \` \${result.className}\`
+ attrs.style = {
+ ...((attrs.style as Record<string, string>) || {}),
+ ...result.style,
+ }
+
+ return (
+ <svg
+ {...attrs}
+ dangerouslySetInnerHTML={{ __html: result.path }}
+ ></svg>
+ )
+ }
+}
+
+/** SvgIcon function component, define in @yzfe/svgicon-loader compile */
+interface ReactSvgIconFC extends React.FC<ComponentProps> {
+ iconName: string
+ iconData: IconData
+}
+
+export {
+ ReactSvgIcon,
+ ReactSvgIconFC,
+ Props,
+ Options,
+ Icon,
+ IconData,
+ setOptions,
+}
使用 @yzfe/svgicon-viewer
可以预览任意文件夹的 SVG 文件。
# 全局安装
+yarn global add @yzfe/svgicon-viewer
# svgicon-viewer <svgFilePath> [metaFile]
+svgicon-viewer ./src/assets/svg
使用 meta.json 可以添加额外的信息,目前只支持一个 name 字段,可以用来描述图标。默认读取 SVG 文件路径下的 meta.json
// meta.json demo
+{
+ "arrow": {
+ "name": "箭头"
+ }
+}
svgicon-viewer ./src/assets/svg ./src/assets/svg/meta.json
添加 --output (alias: -o) 会生成静态 html 页面到指定的输出目录
svgicon-viewer ./src/assets/svg -o ./dist
生成 SVG 图标数据函数的参数(属性)
export interface Props {
+ /** icon data */
+ data?: Icon
+ width?: string | number
+ height?: string | number
+ scale?: string | number
+ /** icon direction */
+ dir?: string
+ color?: string | string[]
+ /** gradient stop colors */
+ stopColors?: string[]
+ title?: string
+ fill?: boolean
+ /** is use original color */
+ original?: boolean
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string
+}
获取 props 的 key 数组
export declare function getPropKeys(): (keyof Props)[];
根据传入的属性生成图标数据
declare function svgIcon(props: Props): SvgIconResult;
全局配置,影响 props 的默认值
/** Global default options */
+export interface Options {
+ classPrefix?: string
+ // Is stroke default
+ isStroke?: boolean
+ isOriginalDefault?: boolean
+ /** 16px, defined in css */
+ defaultWidth?: string
+ defaultHeight?: string
+}
修改默认选项
export declare function setOptions(newOptions: Options): void;
/** Global default options */
+export interface Options {
+ classPrefix?: string;
+ isStroke?: boolean;
+ isOriginalDefault?: boolean;
+ /** 16px, defined in css */
+ defaultWidth?: string;
+ defaultHeight?: string;
+}
+export interface OriginalColor {
+ type: 'fill' | 'stroke';
+ color: string;
+}
+export interface IconData {
+ width?: number | string;
+ height?: number | string;
+ viewBox: string;
+ data: string;
+ originalColors?: OriginalColor[];
+ stopColors?: string[];
+ [key: string]: unknown;
+}
+export interface Icon {
+ name: string;
+ data: IconData;
+}
+export interface Props {
+ /** icon data */
+ data?: Icon;
+ width?: string | number;
+ height?: string | number;
+ scale?: string | number;
+ /** icon direction */
+ dir?: string;
+ color?: string | string[];
+ /** gradient stop colors */
+ stopColors?: string[];
+ title?: string;
+ fill?: boolean;
+ /** is use original color */
+ original?: boolean;
+ /** Replace content, usually replace color */
+ replace?: (svgInnerContent: string) => string;
+}
+/** SvgIcon function result type */
+export interface SvgIconResult {
+ /** SVG content */
+ path: string;
+ /** viewBox */
+ box: string;
+ className: string;
+ style: Record<string, string | number>;
+}
+/** set default options */
+export declare function setOptions(newOptions: Options): void;
+export declare function getOptions(): Options;
+export declare function getPropKeys(): (keyof Props)[];
+/** get svgicon result by props */
+export declare function svgIcon(props: Props): SvgIconResult;
在 nodejs 环境中运行,生成 Icon
对象 (props.data 的值)
import { OptimizeOptions } from 'svgo';
+import { Icon } from './types';
+export type SvgoConfig = OptimizeOptions;
+/**
+ * generate svgicon object
+ * @export
+ * @param {string} source svg file content
+ * @param {string} filename svg icon file absolute path
+ * @param {(string | string[])} [svgRootPath] svg icon root path, to calc relative path
+ * @param {SVGO.Options} [svgoConfig] svgo config
+ * @returns {Promise<Icon>}
+ */
+export default function gen(source: string, filename: string, svgRootPath?: string | string[], svgoConfig?: OptimizeOptions): Promise<Icon>;
TIP: 你可以直接使用
@yzfe/svgicon-gen
预先生成图标数据,保存为 js 文件,这样可以不用@yzfe/svgicon-loader
加载图标了。
将 SVG 文件加载成图标数据(vue)或者 SVG 图标组件(react), 可以自定义生成的代码
export interface LoaderOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'taro' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: unknown
+}
export interface PluginOptions {
+ svgFilePath?: string | string[]
+ /** load as a component */
+ component?: 'react' | 'vue' | 'custom'
+ /** custom code when load as a custom component */
+ customCode?: string
+ svgoConfig?: SvgoConfig
+ /** Svg files to be excluded, use minimatch */
+ exclude?: string | string[]
+ /** Svg files to be included, use minimatch */
+ include?: string | string[]
+ /** Match query which import icon with query string */
+ matchQuery?: RegExp
+}