Open brickspert opened 4 years ago
虽然 antd 提供了大量的 Icon 图标,但是在平时的设计稿中,会出现各种设计师自定义的 Icon,对于这类图标,怎样处理更好呢?
svg 也是一种图片,可以作为 img 的 src 使用。
img
src
通过配置 url-loader 的配置,我们可以直接引用 svg 资源。
url-loader
{ test: /\.(png|jpg|gif|svg)$/, use: [{ loader: 'url-loader', options: { limit: 8192 } }] }
import customSvg from '../assets/images/xxx.svg'; <img src={customSvg} />
color
font-size
参见官方文档
在 antd v3.9.0 之后,提供了一个 createFromIconfontCN 方法,方便开发者调用在 iconfont.cn 上自行管理的图标。
createFromIconfontCN
首先你需要在 iconfont 上创建自己的图标库,并上传自定义的 Icon,然后就可以通过自定义组件使用了。
iconfont 上新建图标库比较简单,我就不赘述了。我讲一下在上传自定义 Icon 时的几个坑。
Q:自定义 SVG 上传后,显示为空白。
如果 SVG 图标不是封闭的,上传到 iconfont 之后,会显示为空白。那什么是封闭呢?大概就是图标有缺口~
比如下面的线条就是非封闭的,上传到 iconfont 就变成空白了。
我们只需要选中该图标,进行“轮廓化”处理即可。
Q:自定义 SVG 上传后,图标显示不全。
如果 SVG 图标由多个部分组成,但是没有进行“轮廓化”,那上传到 iconfont 之后,可能会显示不全。比如下图的图标,上传到 iconfont 后,图标显示不全了。
我们选中该图标多个部分,进行“轮廓化”即可。
**Q:自定义 SVG 上传后,无法通过 color 属性设置颜色。
我们从 sketch 导出的 svg,一般都是自带颜色的,我们在上传时,选择去除颜色并提交即可。
经过上面的步骤,我们已经把需要的 Icon 上传到 iconfont 了,同时我们可以拿到字体的链接。
然后通过 antd 的 createFromIconfontCN 包装下即可使用。
const MyIcon = Icon.createFromIconfontCN({ scriptUrl: '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js', // 在 iconfont.cn 上生成 }); /* 使用起来还比较简单 */ <MyIcon type="xxx"/>
通过 svgr 我们可以将一个普通的 svg 图片,转成 React 组件。
// webpack.config.js // umijs 配置见 https://github.com/umijs/umi/issues/1078 { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: [ { loader: 'babel-loader', }, { loader: '@svgr/webpack', options: { babel: false, icon: true, }, }, ], }
import { Icon } from 'antd'; import MessageSvg from 'path/to/message.svg'; // path to your '*.svg' file. ReactDOM.render(<Icon component={MessageSvg} />, mountNode);
对于带颜色的图标,loader 并不知道 svg 上哪个颜色是需要自定义的,所以需要手动将 svg 中写死的 color 值改成 currentColor 。
currentColor
svgr 可以通过 cli,将 SVG 转换为组件,同时可以将 svg 中的颜色,设置成变量。
正常情况下,我们导出的 SVG 长这样:
<?xml version="1.0" encoding="UTF-8"?> <svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <!-- Generator: Sketch 58 (84663) - https://sketch.com --> <title>Group</title> <desc>Created with Sketch.</desc> <g id="组件" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="一级导航" transform="translate(-1197.000000, -18.000000)"> <g id="Group" transform="translate(1197.000000, 18.000000)"> <circle id="Oval" fill="#2F54EB" cx="10" cy="10" r="10"></circle> <g id="plus" transform="translate(3.000000, 3.000000)" fill-rule="nonzero"> <rect id="Rectangle-path" fill="#000000" opacity="0" x="0" y="0" width="14" height="14"></rect> <path d="M11.59375,6.48046875 L7.51953125,6.48046875 L7.51953125,2.078125 L6.48046875,2.078125 L6.48046875,6.48046875 L2.40625,6.48046875 C2.34609375,6.48046875 2.296875,6.5296875 2.296875,6.58984375 L2.296875,7.41015625 C2.296875,7.4703125 2.34609375,7.51953125 2.40625,7.51953125 L6.48046875,7.51953125 L6.48046875,11.921875 L7.51953125,11.921875 L7.51953125,7.51953125 L11.59375,7.51953125 C11.6539063,7.51953125 11.703125,7.4703125 11.703125,7.41015625 L11.703125,6.58984375 C11.703125,6.5296875 11.6539063,6.48046875 11.59375,6.48046875 Z" id="Shape" fill="#FFFFFF"></path> </g> </g> </g> </g> </svg>
通过 svgr 的命令行尝试转一下:
npx @svgr/cli --icon --replace-attr-values "#2F54EB=currentColor" message.svg
输出结果为:
import React from "react"; const MessageSvg = props => ( <svg width="1em" height="1em" viewBox="0 0 20 20" {...props}> <g fill="none" fillRule="evenodd"> <circle fill="currentColor" cx={10} cy={10} r={10} /> <path d="M14.594 9.48H10.52V5.078H9.48V9.48H5.406a.11.11 0 00-.11.11v.82c0 .06.05.11.11.11H9.48v4.402h1.04V10.52h4.074c.06 0 .11-.05.11-.11v-.82a.11.11 0 00-.11-.11z" fill="#FFF" fillRule="nonzero" /> </g> </svg> ); export default MessageSvg;
good job~ 现在我们获得了一个纯 React 组件,直接使用即可。
import { Icon } from 'antd'; import MessageSvg from './MessageSvg'; ReactDOM.render(<Icon component={MessageSvg} />, mountNode);
上面的几种方案我有在多个项目中尝试过,目前觉得 通过 webpack 将 SVG 转成组件 方案不错。
关注公众号「前端技术砖家」,拉你进交流群,大家一起共同交流和进步。
图标集成,也想用字体的方式,但是每次都追求速度,经常用的图片。作者的教程让我少了很多弯路,值得一看
怎么封装成一个独立的组件库呢
请问一下,用craco工具怎么配置呢?
虽然 antd 提供了大量的 Icon 图标,但是在平时的设计稿中,会出现各种设计师自定义的 Icon,对于这类图标,怎样处理更好呢?
多种方法
直接当做图片使用
svg 也是一种图片,可以作为
img
的src
使用。通过配置
url-loader
的配置,我们可以直接引用 svg 资源。优劣
color
,font-size
等。自定义 font 图标
在 antd v3.9.0 之后,提供了一个
createFromIconfontCN
方法,方便开发者调用在 iconfont.cn 上自行管理的图标。首先你需要在 iconfont 上创建自己的图标库,并上传自定义的 Icon,然后就可以通过自定义组件使用了。
iconfont 图标库
iconfont 上新建图标库比较简单,我就不赘述了。我讲一下在上传自定义 Icon 时的几个坑。
Q:自定义 SVG 上传后,显示为空白。
如果 SVG 图标不是封闭的,上传到 iconfont 之后,会显示为空白。那什么是封闭呢?大概就是图标有缺口~
比如下面的线条就是非封闭的,上传到 iconfont 就变成空白了。
我们只需要选中该图标,进行“轮廓化”处理即可。
Q:自定义 SVG 上传后,图标显示不全。
如果 SVG 图标由多个部分组成,但是没有进行“轮廓化”,那上传到 iconfont 之后,可能会显示不全。比如下图的图标,上传到 iconfont 后,图标显示不全了。
我们选中该图标多个部分,进行“轮廓化”即可。
**Q:自定义 SVG 上传后,无法通过
color
属性设置颜色。我们从 sketch 导出的 svg,一般都是自带颜色的,我们在上传时,选择去除颜色并提交即可。
自定义 MyIcon 组件
经过上面的步骤,我们已经把需要的 Icon 上传到 iconfont 了,同时我们可以拿到字体的链接。
然后通过 antd 的
createFromIconfontCN
包装下即可使用。优劣
自定义 SVG 图标
通过 svgr 我们可以将一个普通的 svg 图片,转成 React 组件。
参见官方文档
对于带颜色的图标,loader 并不知道 svg 上哪个颜色是需要自定义的,所以需要手动将 svg 中写死的 color 值改成
currentColor
。优劣
通过 cli 将 SVG 转成组件
svgr 可以通过 cli,将 SVG 转换为组件,同时可以将 svg 中的颜色,设置成变量。
正常情况下,我们导出的 SVG 长这样:
通过 svgr 的命令行尝试转一下:
输出结果为:
good job~ 现在我们获得了一个纯 React 组件,直接使用即可。
优劣
总结
上面的几种方案我有在多个项目中尝试过,目前觉得 通过 webpack 将 SVG 转成组件 方案不错。
color
,font-size
等属性控制样式。❤️感谢大家
关注公众号「前端技术砖家」,拉你进交流群,大家一起共同交流和进步。