1. ホーム
  2. Web制作
  3. html5

ディテールキャンバスの描画Webフォントいくつかのメソッド

2022-01-29 08:23:27

最近、canvasで描画するときに頭痛に遭遇しました。canvasはネットワークフォントを効果なく描画します。そこで、いくつかの解決策を探してテストし始めましたが、途中で多くのピットに遭遇しました。そこで、この記事を書いてまとめました。もし、canvasを使っていて同じ問題に遭遇したら、それが何らかの助けになることを願います。

サーバーサイドの変換

サーバーサイド変換とはどういう意味ですか?コンテンツと必要なフォントは直接サーバーに渡され、サーバーはフォントを画像に変換するテキストから画像へのインターフェースを提供し、その画像を直接キャンバスに描画します。これにより、ウェブフォントの描画は問題なく、互換性の問題もありませんが、そうすると、サーバーの作業も増え、またテキストコンテンツがユーザーによって編集可能である場合にも、その作業は必要になります。そうすると、ユーザーは操作のたびに一度だけインターフェースを要求して、もう一度画像を描画することになり、ネットワークのオーバーヘッドが増加します。サーバー側の介入が不要な場合は、次の解決策を見てください。

webfontloader

webfontloaderはGoogleとTypekitが開発したコンポーネントライブラリで、フォントの読み込みをリッスンするための標準イベントのセットを提供しています。長い間更新されていませんが、フォントの読み込みには有効です。ここではその具体例を紹介します。

var WebFont = require('webfontloader')
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
var link = document.createElement('link')
link.rel = 'stylesheet'
link.type = 'text/css'
link.href = 'http://fonts.googleapis.com/css?family=Vast+Shadow'
document.getElementsByTagName('head')[0].appendChild(link)
WebFont.load({
  custom: {
    families: ['Vast Shadow']
  },
  active: function () {
    ctx.font = '50px "Vast Shadow"'
    ctx.textBaseline = 'top'
    ctx.fillText('123', 20, 10)
  }
})

まず、require で webfontloader を導入し、google フォントを読み込むための script タグを動的に挿入します。次に webfontloader の load メソッドを呼び出してリスナーを設定し、フォントが読み込まれるとアクティブフックをトリガーして対応するフォントのコンテンツを描き始めます。webfontloader には開発者が呼び出し可能なイベントシステムのフックがあります。

ウェブフォントを描画するためにjsライブラリを持ち込む必要があると感じている方、大丈夫です、ライブラリなしで行う方法をご紹介します

document.fonts.load

GoogleでCanvas Loading Web Fontsを検索すると、必ず以下の解決策が出てきます。

var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
var link = document.createElement('link')
link.rel = 'stylesheet'
link.type = 'text/css'
link.href = 'http://fonts.googleapis.com/css?family=Vast+Shadow'
document.getElementsByTagName('head')[0].appendChild(link)
var image = document.createElement('img')
image.src = link.href
image.onerror = () => {
  ctx.font = '50px "Vast Shadow"'
  ctx.textBaseline = 'top'
  ctx.fillText('123', 20, 10)
}

この解決策には少し問題があり、画像の onerror イベントが発生したとき、フォントが読み込まれた保証はなく、css ファイルが読み込まれただけなので、最初の訪問時には有効になりません:。

しかし、このフォントはブラウザを再び更新した後に有効になります。


この理由は何でしょうか?ブラウザをリフレッシュさせるネットワークリクエストを見てみましょう。

後ろのフォントはキャッシュされているので描画できていることがわかりますが、クロームデバッグでキャッシュを無効にするをチェックしてキャッシュを無効にすると、どうリフレッシュしてもフォントが描画されなくなります。

解決策はあるのでしょうか?答えはイエスです。読み込みにFont Load APIを使用し、以下のコードを参照してください。

var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
var link = document.createElement('link')
link.rel = 'stylesheet'
link.type = 'text/css'
link.href = 'http://fonts.googleapis.com/css?family=Vast+Shadow'
document.getElementsByTagName('head')[0].appendChild(link)
var image = document.createElement('img')
image.src = link.href
image.onerror = () => {
  document.fonts.load('50px Vast Shadow', '123').then(() => {
    ctx.font = '50px "Vast Shadow"'
    ctx.textBaseline = 'top'
    ctx.fillText('123', 20, 10)
  })
}

まずimageのonerrorイベントのトリックcssファイルの読み込みを使い、次にdocument.fonts.loadを呼んでフォントが読み込まれたかどうかを確認するので、正確に読み込まれたフォントを聞くことができます。しかしこのapiには互換性の問題があるので、具体的にはテーブルを参照してください。

このapiについてもっと知りたい方は、mdnにアクセスして

コントラスト描画

コントラスト描画とはどういう意味ですか?持っていないフォントを設定し、比較のために必要なフォントを設定するということです。

var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
var link = document.createElement('link')
link.rel = 'stylesheet'
link.type = 'text/css'
link.href = 'http://fonts.googleapis.com/css?family=Vast+Shadow'
document.getElementsByTagName('head')[0].appendChild(link)
ctx.font = '50px UNKNOW'
ctx.textBaseline = 'top'
ctx.fillText('123', 20, 10)
var dataDefault = ctx.getImageData(20, 10, 50, 50).data
ctx.clearRect(20, 10, 100, 100)
var detect = () => {
  ctx.font = '50px "Vast Shadow"'
  ctx.textBaseline = 'top'
  ctx.fillText('123', 20, 10)
  var dataNow = ctx.getImageData(20, 10, 50, 50).data
  if ([].slice.call(dataNow).join('') === [].slice.call(dataDefault).join('')) {
    ctx.clearRect(20, 10, 100, 100)
    requestAnimationFrame(detect)
  }
}
detect()

まず、存在しないフォントを設定し、描画し、対応する領域のレンダリングデータを取得し、次にレンダリング領域をクリアし、次に必要なフォントを設定し、対応する領域のレンダリングデータを取得して、リアルタイムで比較し、レンダリングデータが同じ場合は、システムのデフォルトフォントで描画されていることを意味し、必要なフォントは描画されていない、次にrequestAnimationFrameを実行して検出メソッドを、描画データが異なる場合は必要なフォントはレンダーされていたことになる。

要約

この記事では、canvasにWebフォントを描画するための一般的な方法をいくつか紹介しましたが、それぞれメリットとデメリットがありますので、参考にして適宜利用していただければと思います。

この記事がお役に立てれば幸いです。そして、スクリプトハウスを応援していただければ幸いです。