Node.jsで画像に文字を書く

地味に進めていたこのサイトのリニューアルもほぼ完了しました。

新しいサイトはSNS対応(OGPってやつ)をきっちりしてみたかったのですが、このためには記事1つ1つにアイキャッチ画像の設定が必要でした。 ただまあ、テキストとソースコードがほとんどのこのブログで画像を毎回作るのも面倒くさくて…

というわけで、Node.jsでコンテンツと一緒に生成させるようにしてみました。

具体的には、以下のような画像を読み込んで、

Blanktarって文字とロゴだけが入った画像

以下のように記事のタイトルを入れるものを作りました。

「Node.jsで画像に文字を書く」って記事タイトルを重ねた画像

1. 必要なパッケージのインストール

今回はnode-canvasというライブラリを使用しました。 その名の通り、HTMLのCanvas APIをNode.js上で使えるようにしてくれるやつです。

$ npm install canvas

環境によっては依存関係を手動でインストールする必要があるので、問題があればGitHub上のREADMEを確認してください。

2. Canvasを用意する

まずはcreateCanvasという関数を使って、画像編集をするためのキャンバスの用意をします。 このキャンバスに色々書き込んでいく流れになります。

import { createCanvas } from 'canvas';


const canvas = createCanvas(640, 480);  // 640x480の空のキャンバスを作る
// const canvas = document.querySelector('#canvas');  // 上の一行はブラウザの場合のコレに相当します

const ctx = canvas.getContext('2d');  // ここからはブラウザと共通

3. 画像を読み込む

次に、書き込み先となる画像を読み込みます。 画像の読み込みにはImageクラスを使うか、そのヘルパ関数であるloadImageを使います。

loadImage関数を使う場合(簡単)

import { loadImage } from 'canvas';


const image = await loadImage('./path/to/image.jpg');  // ここはURLを渡しても平気

ctx.drawImage(image, 0, 0, 640, 480);  // さっき作ったCanvasの(0, 0)地点に640x480のサイズで描画

Imageクラスを使う場合(色々出来る?)

import { Image } from 'canvas';


const image = new Image();

image.src = './path/to/image.jpg';  // ここはURLでも良い(loadImageと一緒)

image.onerror = (err) => {
    console.error(err);
};

image.onload = () => {
    ctx.drawImage(image, 0, 0, 640, 480);  // さっき作ったCanvasの(0, 0)地点に640x480のサイズで描画
};

4. 文字を書き込む(英数字だけバージョン)

書き込み先の画像の準備が出来たら、いよいよ文字を書き込みます。 まずはフォントを気にしなくて良い英数字だけの文字列から。

ctx.fillText('hello world', 10, 10);  // (10, 10)の位置に"hello world"を書き込む

これだけで書き込みが出来ます。

このあたりの挙動はブラウザのCanvas APIと全く一緒なので、MDNあたりのリファレンスが参考になると思います。

5. 文字を書き込む(日本語バージョン)

5-1. フォントの読み込み

日本語(というかASCII文字以外)を書き込みたい場合は、まず始めにフォントの読み込みをする必要があります。 これには、registerFontという関数を使います。

ちなみに、registerFontの呼び出しはcreateCanvasを呼び出す前にやらないとダメみたいです。

import { registerFont } from 'canvas';


registerFont('./path/to/font.ttf', { family: 'Hoge Fuga' });  // font.ttfを登録する。フォント名は適当

これで登録が出来ます。 ttfotfも読めるので、かなりつよい。

URLの指定は出来ないので、そこだけ注意。

5-2. 使うフォントを指定して文字を書き込む

フォントの登録が完了したら、以下のようにして使うフォントを指定して書き込みます。 この辺はブラウザと一緒。

ctx.font = '12px "Hoge Fuga"';  // フォントサイズとさっき指定したフォント名

ctx.fillText('日本語が使える!', 10, 10);