canvas使用自定义字体

图片描述

[TL;DR] 有人在群里发了张图片问最后一个是什么字。根据生活经验和一些图片上的信息搜索并无匹配到对应的字。而后找了个提供字体识别服务的网站,得到图中所用字体后,把经常使用汉字输入预览,肉眼一一对比后确认了这个字,也是运气加眼神好。后来写了个简单的页面用程序来作对比:先把图片二值化再简化获得一个数组,而后把汉字渲染到canvas上后用相同的方法获得一个数组,对比两个数组计算类似度。细节就不说了,不是本文的重点,接下来讲说怎么使用特殊字体在canvas上绘制文本。canvas

@font-face

搜“canvas使用自定义字体”,搜索的结果基本是使用CSS的@font-face来指定字体。数组

@font-face {
  font-family: "myFont";
  src: url("./custom.ttf"); /* 省略其余格式 */
}

而后canvas中使用这个字体浏览器

const cvs = document.querySelector('canvas')
const ctx = cvs.getContext('2d')

context.font = '30px myFont'
ctx.fillText('测试', 50, 50)

结果发现没效果,查看网络面板,发现字体已经下载了。应该是文本在字体还未加载完就绘制了,因此要保证绘制前资源已经准备好。网络

window.onload = function () {
  // canvas fillText
}

加上后,仍是没效果,难道font不像img同样在加载完后触发window.onload?因而我尝试把绘制文本放到一个较长延时的setTimeout函数里。函数

setTimeout(() => {
  // canvas fillText
}, 5000)

仍是没效果,可是经过网络面板发现,字体是在差很少5s后才请求下载的。这里咱们应该有了个猜想,随后查到资料证明了:原来对于大部分浏览器,字体是懒加载的,在@font-face中声明了并不会下载此字体,只有在使用了这个字体,浏览器才会下载。测试

对于DOM+CSS来讲没有问题,由于页面能够先显示默认的字体,当自定义字体加载完成后,页面自动呈现新字体。可是对canvas来讲就不行了,由于在绘制的时候自定义字体还未加载完,那么绘制到画布会使用的默认字体,等自定义字体加载完,画布是不会自动更换像素的。字体

因此要保证绘制前字体已经加载完,咱们能够先对对DOM元素使用该字体触发字体下载。网站

<style>
@font-face {
  font-family: "myFont";
  src: url('./custom.ttf'); 
}
canvas {
  font-family: "";
  font-size: 0;
}
<style>

<!-- DOM元素中间必须有字符,可使用&nbsp; -->
<canvas>.</canvas>

<script>
window.onload = function () {
  const cvs = document.querySelector('canvas')
  const ctx = cvs.getContext('2d')

  context.font = '30px myFont'
  ctx.fillText('测试', 50, 50)
}
</script>

FontFace

能够看到前面的方法比较麻烦,但在摸索过程当中经过搜索“JS怎么监听字体加载完成”,搜到了一个新的APIdocument.fonts.ready,而且这个接口返回的是Promise,可见应该是挺新的接口。顺藤摸瓜,在MDN上找到了FontFace这个接口,它的做用和CSS中的@font-face相似。使用很简单,直接看代码。url

<canvas></canvas>

<script>
const myFont = new FontFace('myFont', 'url(./custom.ttf)')

myFont.load().then(font => {
  document.fonts.add(font)
}).then(() => {
  const cvs = document.querySelector('canvas')
  const ctx = cvs.getContext('2d')

  ctx.font = '30px myFont'
  ctx.fillText('测试', 50, 50)
})
</scipt>

上面只是最简单的使用,如想了解更多的能够去看看相关文档:https://developer.mozilla.org...spa

相关文章
相关标签/搜索