antd-mobile-icons 不提供源码,想定制 icon 组件,怎么办?
自定义 icon 图标组件库
antd-mobile-icons 不满足业务需求,也没提供源码(相关 ISSUE 讨论),我们想定制自己的 icon 图标组件库,怎么办?
下面介绍一种方法,能快速实现自定义实现满足业务诉求的 icon 图标组件库
关于 ICON 图标
因为图片图标或 font 图标,都存在一些问题
- 图片图标
- 不支持变色
- 不是矢量图,易失真
对于 font 图标,svg 图标有以下优势:
- 完全离线化使用,不需要从 CDN 下载字体文件,图标不会因为网络问题呈现方块,也无需字体文件本地部署。
- SVG 是矢量的,在低端设备上 SVG 有更好的清晰度。
- 支持多色图标。
- 对于内建图标的更换可以提供更多 API,而不需要进行样式覆盖。
更多讨论可参考:#10353。
关于 iconfont
- 使用 iconfont.cn 平台做 icon 图标的管理,所有 icon 一目了然
- 图标绘制
- 存储为 svg 格式(建议使用存储为 svg,不要使用导出为 svg)
- 如何使用 iconfont.cn 的产物做图标
- 这里我们推荐使用 svg 图标
规范
为了方便管理及使用 svg 图标,做以下规范约定
- 使用 iconfont.cn 平台做 icon 图标的管理,所有 icon 一目了然,方便管理使用
- icon 制作要遵守 图标绘制 规范
- 附加约定
- 统一 svg 纯色图标(注意边线风格等一致)
- 画布统一正方形
- 如需单独使用 svg 格式,建议使用存储为 svg(不要使用导出为 svg)
- iconfont 图标库,统一前缀命名规范(需图标库修改设置)
- 设置
Font Family
为xxfont
格式,如admfont
- 设置
FontClass/Symbol 前缀
为${Font Family}-
格式,如admfont-
- 设置
- 代码使用,参见以下示例
- font-class 方式
- symbol 方式(我们使用该模式)
<!-- 拷贝项目下面生成的fontclass代码 -->
<!-- font-class 方式引用 -->
<i class="xxfont xxfont-select"></i>
<!-- symbol 方式引用,可结合 svg-sprite 使用 -->
<svg class="xxfont" aria-hidden="true">
<use xlink:href="#xxfont-select"></use>
</svg>
iconfont 最多支持一次下载 100 个图标,可通过工具对下载的内容 iconfont.svg 进行分割导出独立的 svg 图标。
下面有可用的 cli 工具
Icon 图标工作流
我们是如下使用的,这里有篇文章页做了总结,可参考
iconfont 管理平台主要面向设计师 UI 和 前端开发 FE,主要为下面的工作流以及职责:
- 设计师 UI 负责把 icon 上传到平台,通过不同的“大库”区分业务线,形成一个 icon 池;
- 制作标准 icon,遵守 图标绘制 规范
- 管理 icon 资源池(每个业务一个 Icon 素材池或共用一个池子)
- 前端开发 FE 则根据项目需要,从 icon 池中挑选 icon,添加到业务项目,导出外链
- 规范 icon 命名及使用
- 管理 icon 项目库(一般分两个)
- 公共库,跟随基础组件库迭代管理,标准化,更稳定
- 业务项目库,跟随业务项目迭代管理,更新快,更灵活
为避免 iconfont 站点服务异常影响使用,推荐下载引入到本地项目中使用。
更新 Icon 流程
使用 cli 脚本更方便,可以将 iconfont 上的 icon 自动转为业务库 svg 的 React组件。
npm 已经有相应的 cli 工具来处理了——react-iconfont-cli
pnpm i react-iconfont-cli -D
# 初始化
npx iconfont-init
# 生成配置文件 iconfont.json,示例如下
# 配置配置 symbol_url
# 开始生成React标准组件
npx iconfont-h5
./iconfont.json
配置示例:
{
"symbol_url": "//at.alicdn.com/t/c/font_2707658_9cqox8p2rj.js",
"use_typescript": true,
"save_dir": "./src/components/iconfont",
"trim_icon_prefix": "icon",
"unit": "px",
"default_icon_size": 16
}
注意:symbol_url
为 iconfont.cn 上的 js 地址(对应 Symbol 模式),请务必看清 symbol_url
配置是.js后缀而不是.css后缀。
每次更新 icon 图标后,重新生成 Symbol 链接,更新 symbol_url 配置后,执行脚本 npx iconfont-h5
更新项目的 iconfont 组件即可(每次都重新生成),无需项目工程配合。
如果是 vue 项目,也有对应的 cli,可自行探索下。
使用 icon
iconfont 组件,使用方式如下
import IconFont from '@/components/iconfont';
export default () => {
return (
<>
<IconFont name="testfont-packaging" color="red" className="svgicon human" />
</>
)
}
注意: 这个 react-iconfont-cli
工具生成的 React 图标组件有些缺陷,下面有列出问题及解决方案
等有空了,可以提个 PR 优化或 fork 修复。
- svg 图标不应该使用
block
内联样式,使用下面类名svgicon
进行覆盖 - 扩大点击区域,增加
human
类名 - 关于生成 React 组件,使用 size 属性控制 svg 的宽高
- 此处也使用
svgicon
类名覆写为1em
- 如要控制 icon 图标大小,可使用 style 熟悉设置
fontSize
来实现
- 此处也使用
已经处理,详细参见 react-iconfont-cli2
解决了以下问题
- svg 默认 width 和 height 改为
1em
- svg 默认 viewBox 不处理, iconfont 的 viewBox 为
0 0 1024 1024
- svg 默认 fill 属性值改为
#CACACA
- 修改配置 trim_icon_prefix 默认值改为
''
, 这样生成的组件名称由 iconfont 平台控制 - 新增配置 default_style, 默认配置
{verticalAlign: '-0.125em', fill: 'currentColor'}
- 新增配置 default_class_name, 用于配置 svg 的统一css 类名,默认值
'svgicon'
- svg 新增 className 属性, 格式为
${default_class_name} ${iconId}
,如svgicon icon-xxx
.svgicon {
display: inline-block !important;
width: 1em;
height: 1em;
fill: currentColor;
vertical-align: -0.125em;
font-size: 16px;
}
/* 优化点击区域 */
.human {
position: relative;
}
.human:before {
content: '';
position: absolute;
top: -8px;
right: -8px;
bottom: -8px;
left: -8px;
}
另一个方案,也比较推荐,但如果项目较老,可能出现构建报错,不如上面的方案独立性好。
参看:《icon 工程化支持》