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/