iconify图标使用新姿势

2023-11-037 min 作品
cover image
AI摘要
这篇文章讲了对hexo-iconify插件的升级,引入了新的css图标方式。通过新增的icons helper,实现了以mask-image为基础的css图标引入方法,解决了内联引用导致资源浪费的问题。文章介绍了实现原理,并通过TypeScript代码展示了插件的升级过程。最终优点在于集中了显示效果与体积,资源复用相对于svg inline更好,而缺点主要在于mask的兼容性,但对于大多数情况足够满足需求。

之前我们在hexo-iconify插件让你能够使用所有iconify图标中通过iconify官网所提供的api实现了一个给hexo博客轻松引入iconify图标的插件,这个插件通过icon这一helper,将图标以svg内联的方式写入网页中,虽然是按需引入,对于单个页面来说没有其他额外负担,但是在实际使用中,我们的网站是多页面的,很多图标被重复使用,但是由于是内联引用的,没法复用,造成了一定程度上资源的浪费。突然感觉又回到了iconfont了

于是我又去翻了官方文档,找到了svg in css这一章节,发现了iconify也提供了类似于iconfont这种通过css来引入的方法,与iconfont使用字体不同,iconify使用的是mask-image来将图标显示出来,之所以使用mask-image而不是background,主要还是因为mask-image能够使用currentColor来进行图标颜色的更改

于是我对原本的插件进行升级,在原有基础上,新增了icons这一helper,让你能够轻松的引入css图标

主要原理

其实也不难去想怎么实现这一功能,svg生产datauri相对比较容易,不需要base64编码,我们在helper部分返回类名,在渲染时将使用到的图标及类名注入css文件中即可

TypeScript
hexo.extend.helper.register(
  'icons',
  function (iconName: string, fileName?: string) {
    return getIconClass(iconName, fileName)
  },
)

hexo.extend.filter.register('after_render:css', function (str, data) {
  let defaultFile = 'icons.css'

  if (hexo.config.iconify?.file) {
    defaultFile = hexo.config.iconify.file
  }

  saveIcons.forEach((value, key) => {
    const fileName = value.file || defaultFile
    if (data.path.includes(fileName)) {
      hexo.log.info(`iconify: 写入图标 ${key}${fileName}`)
      str += `.${key}{--svg:url("${value.data}");}`
    }
  })

  return str
})

当然我们需要事先设置好基类 icons 的样式,我们在css文件中添加以下内容

CSS
.icons {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -.15em;
    background-color: currentcolor;
    mask: no-repeat center / 100%;
    mask-image: var(--svg);
}

优缺点

好处是集中了显示效果与体积相对比iconfont好,资源复用比svg inline好,能够自定义插入到哪个css文件(我们可以把首屏显示的放到主要css中,将那些一开始用户不可见或者需要下滑可见的放到非核心css中,保证用户体验)

缺点,主要集中在mask的兼容性问题,对于我来说是足够的,因为他除了ie都兼容,更何况svg本身在ie上就存在兼容性问题

评论
正在加载评论组件...