谈谈Web项目中图标的方式

谈谈Web项目中图标的方式

单个图标

我们可以选择单独引用图标文件如png、svg等等,这种方式缺点显而易见,图标多了之后不方便维护

字体文件

通过font-face,我们可以指定一个用于显示文本的自定义字体,字体文件内部类似一个svg我们可以在字体文件里面随便定义这些字符的形状,

font

通过对应字体文件的字体编码我们就可以使用这些图标了,如下面是一个close图标

<i class="iconfont">&#xe64f;</i>

这样有个明显的缺点就是图标不直观,我们很难根据&#x33;知道它是什么图标,我们可以通过提前定义好对应图标css的::before的content,将其改造成自定义class引用的方式

.icon-close:before{
	content: "\e64f"
}

然后我们在页面中可以这样使用

<span class="iconfont icon-close"></span>

因为是字体格式所以这种方式使用图标有以下特点

  • 兼容性最好,支持ie6+,及所有现代浏览器。
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • 不支持多色。

symbol 引用

symbol 元素用来定义一个图形模板对象,它可以用一个use元素实例化。一个symbol元素本身是不呈现的。只有symbol元素的实例(亦即,一个引用了symboluse元素)才能呈现,如

  <svg>
    <!-- symbol definition  NEVER draw -->
    <symbol id="sym01" viewBox="0 0 150 110">
      <circle cx="50" cy="50" r="40" stroke-width="8" stroke="red" fill="red" />
      <circle cx="90" cy="60" r="40" stroke-width="8" stroke="green" fill="white" />
    </symbol>

    <!-- actual drawing by "use" element -->
    <use xlink:href="#sym01" x="0" y="0" width="100" height="50" />
    <use xlink:href="#sym01" x="0" y="50" width="75" height="38" />
    <use xlink:href="#sym01" x="0" y="100" width="50" height="25" />
  </svg>

symbol的作用域是全局的我们也可以在svg中单独使用如

  <svg>
    <!-- symbol definition  NEVER draw -->
    <symbol id="sym01" viewBox="0 0 150 110">
      <circle cx="50" cy="50" r="40" stroke-width="8" stroke="red" fill="red" />
      <circle cx="90" cy="60" r="40" stroke-width="8" stroke="green" fill="white" />
    </symbol>
  </svg>
  <svg>
    <use xlink:href="#sym01" x="0" y="0" width="100" height="50" />
  </svg>

我们还通过一些css技巧,支持svg像字体那样,通过font-size,color来调整样式。

.icon {
  /* em让宽高等于字体大小 */
  width: 1em;
  height: 1em;
  /* 继承父级的 color 属性 */
  fill: currentColor;
}
<svg class="icon">
  <use xlink:href="#icon-close"></use>
</svg>

常用的图标库对比

常用的图标库有阿里的iconfont,字节的IconPark

iconfont特点

  • 支持上传自己自己的图标,并将图标按照项目进行管理

  • 只支持字体、symbol引用的方式,并且可以单独下载图标为svg或者png格式

  • 支持通过文件的方式导入可与任何框架配合使用

iconpark特点

与iconfont不同的是它并没有使用symbol引用的方式,而是通过现代框架代码将其编译成了组件,我们可以更方便的对框架图标进行更细粒度的定制,

  • 只包含官方提供的svg图标,好处是图标风格样式更统一

  • 可对图标大小、颜色、线框粗细、端点等属性进行等更定制化的转换

  • 可以跨平台导出多种图标组件代码,包括React、Vue2、Vue3格式

虽然没有使用symbol引用,但多次引用同一图标并不会导致打包后代码增加,在vue中字体组件会被编译成下面这张形式。

var dj, pj, hj, mj = (pj = !1, hj = function(e) {
  return Ao("svg", {
    width: e.size,
    height: e.size,
    viewBox: "0 0 48 48",
    fill: "none"
  }, [Ao("path", {
    d: "M9 18V42H39V18L24 6L9 18Z",
    fill: e.colors[1]
  }, null), Ao("path", {
    d: "M9 42V18L4 22L24 6L44 22L39 18V42H9Z",
    stroke: e.colors[0],
    "stroke-width": e.strokeWidth,
    "stroke-linecap": e.strokeLinecap,
    "stroke-linejoin": e.strokeLinejoin
  }, null), Ao("path", {
    d: "M19 29V42H29V29H19Z",
    fill: e.colors[3],
    stroke: e.colors[2],
    "stroke-width": e.strokeWidth,
    "stroke-linejoin": e.strokeLinejoin
  }, null), Ao("path", {
    d: "M9 42H39",
    stroke: e.colors[0],
    "stroke-width": e.strokeWidth,
    "stroke-linecap": e.strokeLinecap
  }, null)])
}, {
  name: "icon-" + (dj = "home"),
  props: ["size", "strokeWidth", "strokeLinecap", "strokeLinejoin", "theme", "fill", "spin"],
  setup: function(e) {
    // 。。。
  }
});

在我们的组件使用的地方如

<home theme="filled"/>

被编译成了类似下面这种形式的函数调用

P(u, {
    theme: "filled"
  })

如何选择

对于如何选择这两个方式我们可以考虑以下情况

选择iconfont

  • ui或者产品想使用自己的图标

  • 需要对图标进行管理

  • 前端项目非React、Vue2、Vue3框架

  • 想使用起来更简单更灵活一点

选择iconpark

  • 需要方便对图标进行更定制化设置
  • 项目中需要对图标风格进行响应式的更改