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