Skip to content

起因是最近项目要用的这种选字体的需求,所以就调研了一下实现方法,然后就有了这篇笔记

1.Chrome实验性接口 queryLocalFonts

Chrome 从v103开始支持该接口,是异步接口,返回Promise对象

js
if ('queryLocalFonts' in window) {
    queryLocalFonts().then(fonts => console.log(fonts))
}

如果是第一次使用,会弹出提示,点同意后返回本地的字体数组

如果浏览器不支持该接口,或是弹窗点了拒绝,则queryLocalFontsundefined

2. document.fonts

document.fonts 接口是 CSS 字体加载 API 的一部分,用于管理和加载浏览器中的字体

目前除了IE,流行浏览器都支持,但是该接口只能检查某字体是否可用,而无法给出系统支持的字体清单

所以事先需要有一份检测的字体清单,来检查哪些字体可使用

js
if (document.fonts.check('12px 宋体')) {
    console.log('字体可用');
} else {
    console.log('字体不可用');
}

此外还有load方法

js
document.fonts.load('9px Arial').then(() => {
    console.log('font loaded')
}, () => {
    console.log('error')
})

注意传参是CSS语法,所以9px Arial需带上9px,当然9rem之类也是可以的

3. 利用Canvas

可以用待检测的字体在Canvas写字,再获取宽度,跟用系统默认字体渲染的对比,如果不一样,则是渲染字体成功,如果缺字体,会用默认字体替换,这样渲染出来的宽度就没变化,则可以判断为无该字体

js
function detectFont(font) {
  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')
  const text = 'abcdefghijklmnopqrstuvwxyz0123456789'

  context.font = '72px Segoe UI'
  let baseSize = context.measureText(text).width

  context.font = '72px ' + font + ', Segoe UI'
  let newSize = context.measureText(text).width

  return newSize !== baseSize
}

detectFont('宋体')
// true

detectFont('仿宋')
// true

detectFont('PingFang SC')
// false

值得一提的是这个办法并非100%准确,例如不同浏览器渲染的差异、浏览器对缺失字体的处理方式、以及不同字体的宽度有可能一致等诸多原因。

综上所述,不同的方法各有优劣,开发者应结合项目需求选择合适的方式进行字体检测。通过灵活运用 以上方法,能够在大多数场景下满足字体检测的需求。这篇笔记希望能为你在实际开发中提供帮助,也希望能够提升你项目的用户体验和设计一致性。

上次更新于: