canvasでGoogleFontsを使う

canvasでGoogleFontsを使いたかったので、対応をメモ。
GoogleFontsを読ませる部分の処理に関してはこちらの記事の方のコードをほぼまるっと使わせていただきました。ありがとうございます。

/**
 * フォントファミリーの読み込み
 */
export const setFonts = async (
  fontFamilyList: {
    name: string;
    weight: string;
  }[],
) => {
  for (let i = 0; i < fontFamilyList.length; i++) {
    // URLでは空白を+に置き換える
    const urlFamilyName = fontFamilyList[i].name.replace(/ /g, "+");

    // Google Fonts APIのURL
    const googleApiUrl = `https://fonts.googleapis.com/css2?family=${urlFamilyName}:wght@${fontFamilyList[i].weight}`;

    const response = await fetch(googleApiUrl);

    if (response.ok) {
      // url()の中身のURLだけ抽出
      const cssFontFace = await response.text();
      const matchUrls = cssFontFace.match(/url\(.+?\)/g);
      if (!matchUrls) throw new Error("フォントが見つかりませんでした");

      for (const url of matchUrls) {
        // FontFaceを追加
        const font = new FontFace(fontFamilyList[i].name, url);
        await font.load();
        const documentFonts = document.fonts as any;
        documentFonts.add(font);
      }
    } else {
      throw new Error(response.statusText);
    }
  }
  return "done";
};
import "./styles.css";
import { setFonts, canvasLoading, setText } from "./setCanvasOptions";

const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const context = canvas.getContext("2d");


// 中略

if (context !== null) {
  canvasLoading(canvas, "on");
  //フォントを使う場所で
  const asyncFunc = async () => {
    const fatchDone = await setFonts(fontFamilyList);

    // フォントが読まれた後に描画する
    if (fatchDone) {
      context.beginPath();
      context.fillStyle = "rgb( 52, 201, 182)";
      context.fillRect(0, 0, canvas.width, canvas.height);

      setText(textList, context);

      canvasLoading(canvas, "off");
    }
  };
  asyncFunc();
}

ちょっとつまずきポイント

canvasにテキストを描画する時に、 context.font でフォントを指定するのですが、指定する順番を font-weight font-size font-family の順にしないと正常に表示できないようです。(文字が小さく描画されたり、特にsafariだとfont-familyが効いていなかったり。)

参考サイト

JavaScriptでGoogle Fontsを動的に読み込む
https://zenn.dev/cococig/articles/1d494847985263

JavaScript | Canvasでテキストの縦横中央揃えと各ポジションの指定パターン | 1 NOTES
https://1-notes.com/javascript-canvas-draw-text-positions/

関連