开发日记(01) - uni-app 使用等宽字体对齐数字宽度

开发的过程中遇到数字显示列表,发现同样的数字数宽度不一。android 不会有, web 浏览器和 ios 会出现。

uni-app 使用等宽字体对齐数字宽度

0️⃣ 问题 ❓

更新时间:2021-02-28 15:55:18

  • 2021-02-28 15:55:18
    • Nvue 中使用 cssfont-family 属性值不能使用引号。
    • Nvue 需要下载 ttf 格式的字体进行 base64 编码。

开发的过程中遇到数字显示列表,发现同样的数字数宽度不一。android 不会有, web 浏览器和 ios 会出现。

之前也有遇到过,也解决了,写过文章记录 在网站中使用谷歌“ROBOTO”字体(解决 ios 数字 1 和 0 大小不等宽问题),不过文章没有明确的代码,也比较潦草,这次加上代码。

本次解决方案不仅仅适用于 uni-app,包括 Nvue, 还有普通的 vue,react 项目都能用。知道原理了,移植解决方案很简单。

原因:默认或者使用了非等宽字体,安卓默认的字体 Roboto 就是等宽的,啥叫非等宽,就是字体的宽度不一样,比如 12 在显示的时候所占用的宽度不一样。(中文字体默认就是等宽的)

一般带了 mono 标识的都是等宽的字体。

解决后:

看起来舒服了很多 😁

1️⃣ 下载需要的字体

链接:https://www.fontsquirrel.com/fonts/roboto

  • 选择 Webfont Kit
  • Choose a Subset 默认就行
  • Choose Font Formats 默认的 WOFF就行**(Nvue 需要使用 ttf)**
  • 点击 Download @font-face Kit
  • 打开压缩包使用 roboto_regular_macroman/Roboto-Regular-webfont.woff

2️⃣ 在 uni-app 中使用

本次测试了 app,h5 端,其他端未测试,理论通用。

将下载的 Roboto-Regular-webfont.woff 放在 项目的 static/fonts/Roboto-Regular-webfont.woff

新建 ${app}/common/scss/font.scss

${app} 指代项目。

@font-face {
  font-family: 'robotoregular';
  src: url('/static/fonts/Roboto-Regular-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

新建 ${app}/common/sass/index.scss

@import 'font.scss';

${app}/App.vue 中导入

<style lang="scss">
  /* #ifndef APP-NVUE */
  page {
    font-family: robotoregular, PingFang SC, Hiragino Sans GB, Heiti SC, Microsoft YaHei,
      WenQuanYi Micro Hei, Helvetica, Arial, monospace, serif;
  }
  /* #endif */
</style>

ok,大功告成。非 nvue 的页面如果没自定义 font-family 的字体应该已经生效了。

3️⃣ 在 nvue 页面中使用

nvue 渲染逻辑不同于 webview 所以这种方式在 nvue 是不生效的。准确来说,你在 nvue 中这么用会报错 😅。

nvue 的字体加载文档:https://weex.apache.org/zh/docs/modules/dom.html#addrule

具体的细节不多说了,直接上逻辑和代码,在尝试了各种方式后,最终决定在需要使用等宽字体的 text 组件上封装组件。这样耦合小,维护啥的方便点。

转换字体文件到 base64

首先我们需要用这个 https://www.giftofspeed.com/base64-encoder/ 网址把我们的字体文件转换成 base64 编码,因为导入字体文件,路径啥的在 nvue 不是很好处理。

新建 ${app}/components-nvue/c-roboto-font/c-roboto-font.vue

最好不要动格式,否则你会发现会多出一些空格换行啥的 😏。

新建 nvue 专用的文件夹。以 c 开头方便使用 easycom, 当然你可以自定义。

<template><text class="roboto-font">{{ text }}</text></template>

<script>
  export default {
    props: {
      text: {
        type: String,
        required: true,
      },
    },
    beforeCreate() {
      const dom = uni.requireNativePlugin('dom')
      dom.addRule('fontFace', {
        fontFamily: 'Roboto',
        src:
          "url('data:font/truetype;charset=utf-8;base64,[这里填写你的字体文件转换出来的base64编码,别写错了]')",
      })
    },
  }
</script>

<style scoped>
  .roboto-font {
    font-family: Roboto;
  }
</style>

配置 easycom

${app}/pages.json

{
  "easycom": {
    "^c-(.*)": "@/components-nvue/c-$1/c-$1.vue"
  }
}

使用

<c-roboto-font :text="foo.count" />

📔 开发日记系列

只记录些平时开发觉得有用的东西,有问题请务必斧正,拜托了 🙏🙏🙏

  1. 开发日记(01) - uni-app 使用等宽字体对其数字显示
  2. 开发日记(02) - js 异步任务队列
  3. 开发日记(03) - uni-app 打包为 app

关于我

SunSeekerX,

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

喜欢探讨技术实现方案和细节,完美主义者,见不得 bug

Github:https://github.com/SunSeekerX

个人博客:https://yoouu.cn/

个人在线笔记:https://doc.yoouu.cn/