antd-mobile-icons 不提供源码,想定制 icon 组件,怎么办?

1,142 阅读2分钟

antd-mobile-icons 不提供源码,想定制 icon 组件,怎么办?

自定义 icon 图标组件库

antd-mobile-icons 不满足业务需求,也没提供源码(相关 ISSUE 讨论),我们想定制自己的 icon 图标组件库,怎么办?

下面介绍一种方法,能快速实现自定义实现满足业务诉求的 icon 图标组件库

关于 ICON 图标

因为图片图标或 font 图标,都存在一些问题

  • 图片图标
    • 不支持变色
    • 不是矢量图,易失真

对于 font 图标,svg 图标有以下优势:

  • 完全离线化使用,不需要从 CDN 下载字体文件,图标不会因为网络问题呈现方块,也无需字体文件本地部署。
  • SVG 是矢量的,在低端设备上 SVG 有更好的清晰度。
  • 支持多色图标。
  • 对于内建图标的更换可以提供更多 API,而不需要进行样式覆盖。

更多讨论可参考:#10353

关于 iconfont

  1. 使用 iconfont.cn 平台做 icon 图标的管理,所有 icon 一目了然
    1. 图标绘制
    2. 存储为 svg 格式(建议使用存储为 svg,不要使用导出为 svg)
  2. 如何使用 iconfont.cn 的产物做图标
    1. 代码使用
  3. 这里我们推荐使用 svg 图标

规范

为了方便管理及使用 svg 图标,做以下规范约定

  1. 使用 iconfont.cn 平台做 icon 图标的管理,所有 icon 一目了然,方便管理使用
    1. icon 制作要遵守 图标绘制 规范
    2. 附加约定
      1. 统一 svg 纯色图标(注意边线风格等一致)
      2. 画布统一正方形
      3. 如需单独使用 svg 格式,建议使用存储为 svg(不要使用导出为 svg)
  2. iconfont 图标库,统一前缀命名规范(需图标库修改设置)
    1. 设置 Font Familyxxfont 格式,如 admfont
    2. 设置 FontClass/Symbol 前缀${Font Family}- 格式,如 admfont-
  3. 代码使用,参见以下示例
    1. font-class 方式
    2. 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后缀。

iconfont-symbol_url.png

每次更新 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 修复。

  1. svg 图标不应该使用 block 内联样式,使用下面类名 svgicon 进行覆盖
  2. 扩大点击区域,增加 human 类名
  3. 关于生成 React 组件,使用 size 属性控制 svg 的宽高
    1. 此处也使用 svgicon 类名覆写为 1em
    2. 如要控制 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 工程化支持》