乐趣区

关于前端:开发日记04-iconfont-挂了项目内的图标怎么办

📌 0x1 问题

iconfont 应该是挂了有 1-2 两个月了,不论是因为什么起因,必定会有一大堆的我的项目有一阵子图标出不来。

作为开发者以来就始终有个感觉,那就是在线服务都不牢靠。我的项目中第三方服务越多,更多不可控的因素就越多。如果都是在本人的服务器上,至多我能够管制服务启动,敞开。都是在同一时间,而不会呈现这种能用,然而又没有齐全能用的状态,这比服务挂了还恶心。

Node 创始人新搞的 deno 也反对引入在线的脚本,我看到这段代码第一工夫不是居然还能这样写,给我的第一感觉就是这代码某天可能就挂了,导致整个我的项目起不来。

import {VERSION} from 'https://deno.land/std/version.ts'
console.log(VERSION)

📌 0x2 须要达到的成果

因为是 uni-app 开发的我的项目,且须要兼容 app 和 nvue。因而图标只能应用单色字体图标的模式,无奈间接应用 svg 的模式。

  • 本地导入,不依赖任何的第三方
  • 反对 weex 的 nvue 界面
  • 兼容 h5 和 app 的显示
  • 组件模式应用
  • (web 也是差不多的思路,这里以 uni-app 为例)

📌 0x3 解决思路

既然在线服务不牢靠,那么必定是应用本地导入形式了。当初的 iconfont 是无奈应用,无奈上传和下载。看看还有什么方法将 svg 转换到字体图标了。github 上有不少将 svg 转换到 webfont 的库。

  • svg2ttf
  • svgtofont

我尝试下载了几个测试,发现都存在一个问题,就是我从 MasterGo 导出的 svg 图标应用这些工具进行转换的话,在我的项目内应用始终是一坨彩色的。猜想是 svg 须要进行一些解决。因为我从 iconfont 下载一个 svg 下来进行转换是 ok。这里不开展说,也不是本人善于的方向。如果你想理解 iconfont 做了什么能够看看这个

  • iconfont 字体生成原理及应用技巧

外面讲的比拟具体,字体图标解决其实有很大的学识,图标很小,做的事件可不少。

📌 0x4 icomoon svg 解决

这是一个相似于 iconfont 的平台,毛病就是只能本地保护,所有的数据都存在缓存,如果清理了浏览器缓存数据就被革除了。不过这个反对我从设计图间接导出的 svg 进行解决。这里以 MasterGo 进行演示实际上就是获取 svg 图标的过程。

4×1 文件改名

首先让 ui 整顿好我的项目内用到的图标,命名好。能够让我间接导出成为 svg。

4×2 上传到 icomoon

拿到导出的 svg 图标,上传到 icomoon。点击 icomoon app 进入 icomoon

导入 svg 图标

抉择从 MasterGo 导出的图标,上传

选中所有的图标点击生成字体

点击预设设置为 class 选择器,勾销反对 ie 8,点击 download 下载字体包

4×3 拿到导出的文件

看起来和 iconfont 导出的没啥区别。

📌 0x5 图标组件

c-icon-moon.vue

一般的 vue 组件,外面的 #ifdef 写法是 uni-app 的条件编译。为了兼容多个平台须要应用到条件编译。

<template>
  <!-- #ifdef APP-NVUE -->
  <text @click="onClick" class="icomoon" :style="iconStyle">{{icons[name] }}</text>
  <!-- #endif -->

  <!-- #ifndef APP-NVUE -->
  <text @click="onClick" class="icomoon" :class="name" :style="iconStyle" />
  <!-- #endif -->
</template>

<script>
// #ifdef APP-NVUE
import icons from './icons'
// #endif
import {addUnit} from '@/utils'

export default {
  name: 'CustomIconMoon',
  props: {
    size: {type: [Number, String],
      default: 'inherit',
    },
    width: {type: [Number, String],
      default: 'auto',
    },
    weight: {
      type: String,
      default: 'normal',
    },
    height: {type: [Number, String],
      default: 'auto',
    },
    color: {
      type: String,
      default: '#909399',
    },
    name: {
      type: String,
      required: true,
    },
    rpx: {
      type: Boolean,
      required: false,
      default: false,
    },
    bubble: {
      type: Boolean,
      required: false,
      default: true,
    },
  },
  computed: {iconStyle() {
      return {fontSize: this.size === 'inherit' ? 'inherit' : addUnit(this.size, this.rpx),
        width: addUnit(this.width, this.rpx),
        height: addUnit(this.height, this.rpx),
        color: this.color,
        'line-height': addUnit(this.height, this.rpx),
        'font-weight': this.weight,
      }
    },
  },
  methods: {onClick(e) {this.$emit('click')
      if (!this.bubble && e) {e.stopPropagation()
      }
    },
  },
  // #ifdef APP-NVUE
  data() {
    return {icons: icons,}
  },
  // #endif
}
</script>

<style scoped>
/* #ifndef APP-NVUE */
@import './style.css';

/* #endif */

.icomoon {font-family: icomoon;}
</style>

addUnit 办法

// 增加单位,如果有 rpx,%,px 等单位结尾或者值为 auto,间接返回,否则加上 rpx 单位结尾
export function addUnit(value = 'auto', rpx = false) {value = String(value)
  return isNumber(value) ? `${value}${rpx ? 'rpx' : 'px'}` : value
}

/**
 * 验证十进制数字
 */
export function isNumber(value) {return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value)
}

icomoon-ttf-base64

为了兼容 nvue 须要将 fonts/icomoon.ttf 文件转换为 base64 写入到该文件

转换网址:https://www.giftofspeed.com/base64-encoder/

export default 'AAEAAAALAIAAAwAw...`

icomoon.woff

icons.js

这里配置 nvue 须要显示的图标名字。

\ue912 相似的字符能够关上 style.css 找到你须要在 nvue 显示的图标名字复制。

/**
 * 这里配置须要在 nvue 显示的图标
 */
export default {
  // 指纹
  'icomoon-fingerprint': '\ue912',
}

nvue-helper

nvue 须要的初始化配置。

import icomoonTtfBase64 from './icomoon-ttf-base64'

/**
 * iconfont 须要用 ttf 转 base64
 * 转换网址:https://www.giftofspeed.com/base64-encoder/
 */
export function onInitNvueFontIcon() {const dom = uni.requireNativePlugin('dom')
  dom.addRule('fontFace', {
    fontFamily: 'icomoon',
    src: `url('data:font/truetype;charset=utf-8;base64,${icomoonTtfBase64}')`,
  })
}

style.css

删除不须要的格式化,只留下 src: url('icomoon.woff') format('woff'); 这一段就行。

@font-face {
  font-family: icomoon;
  font-style: normal;
  font-weight: normal;
  font-display: block;
  src: url('icomoon.woff') format('woff');
}

.icomoon {
  font-family: icomoon !important;

  /* Better Font Rendering =========== */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-style: normal;
  font-variant: normal;
  font-weight: normal;
  line-height: 1;
  text-transform: none;
}

.icomoon-add::before {content: '\e900';}

/* ... */

📌 0x6 应用

vue 界面

间接参考 组件应用示例 就能够。

Nvue 界面

nvue 界面应用须要导入字体文件,全局只须要导入一次就行了

App.vue

<script>
// #ifdef APP-NVUE
import {onInitNvueFontIcon} from '@/components/c-icon-moon/nvue-helper'
// #endif

export default {onLaunch() {
    // eslint-disable-next-line no-console
    console.log('App Launch')
    
    /**
     * Nvue 启动解决
     */
    // #ifdef APP-NVUE
    onInitNvueFontIcon()
    // #endif
  },
  onShow() {
    // eslint-disable-next-line no-console
    console.log('App Show')
  },
  onHide() {
    // eslint-disable-next-line no-console
    console.log('App Hide')
  },
}
</script>

组件应用示例

其实就是 vue 组件的应用了。这里贴一个示例。

<c-icon-moon size="60" name="icomoon-fingerprint" color="red" />

显示成果

📌 iconfont 正名

这里为 iconfont 正名一下,先看下网友的情绪 https://github.com/thx/iconfont-plus/issues

阿里是大,但不是什么部门都大,外部是有估算调配的,人家是企业,不是慈善机构。从应用 iconfont 这个平台以来始终都是白嫖,精确来说如同没有付费我的项目。

再来看看明天用到的 icomoon 平台订阅费用,当然是举个例子,有多少公司违心在 icon 上有这个估算的呢?

评论区留给大家。

📔 开发日记系列

只记录些平时开发感觉有用的货色,有问题请务必斧正,托付了 🙏🙏🙏

  1. 开发日记 (01) – uni-app 应用等宽字体对其数字显示
  2. 开发日记 (02) – js 异步工作队列
  3. 开发日记 (03) – uni-app 打包为 app
  4. 开发日记 (04) – iconfont 挂了,我的项目内的图标怎么办?

对于我

SunSeekerX,

全栈开发、区块链开发、挪动端开发、前后端开发、NodeJS 开发、小程序、uni-app 开发、等

喜爱探讨技术实现计划和细节,完满主义者,见不得 bug

Github:https://github.com/SunSeekerX

集体博客:https://yoouu.cn/

集体在线笔记:https://doc.yoouu.cn/

退出移动版