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

相關文章
相關標籤/搜索