HTML5のcanvasで描画する文字の後ろに白地をつける方法


本題に入る前に一つ問題です。Canvasで文字を描画(fillTextメソッドを利用)する時、文字の縦基準位置を指定しない、つまりデフォルトの場合、文字は指定座標にたいしてどの位置に描画されるでしょう。次の3つの中からお選びください(点は指定座標の位置)

drawTxt1 drawTxt2 drawTxt3
文字より上の位置 文字の縦中央の位置 文字より下の位置

というわけで全て不正解です。正解は下記のような位置関係となります。
drawTxt4

文字の縦位置はtextBaselineというメソッドで指定できます。最初に問題にだした3つはそれぞれ”top”,”middle”,”bottom”を指定した時の位置となります。じゃあ、デフォルトは何かというと、”alphabetic”という値です。つまり、アルファベットの基準位置です(参考:textBaseline プロパティ – Canvasリファレンス – HTML5.JP)。いかにも英語圏の人が作った仕様ですね。最初、何でこんな変な位置で文字が描画されるんだと思っていました。

ここから本題。文字を描画する際に文字の後ろ側に白地も描画する方法です。ただし、textBaselineは”middle”ということを想定してします。白地をつける文字をcanvas上に書くために、下記のような関数を作りました。

引数にオプションを入れており、それによってデフォルトの動きとは異なる動きにできるようにしています。8行目で、jQueryのextendメソッドを使ってデフォルトオブジェクトに引数のオプション用のオブジェクトをマージしていますが、これぐらならわざわざextend使わなくても、下記のようにやれば同じ動作となるはずです。

10行目のtextAlignプロパティで指定の座標に対する文字描画の横位置を指定しています(参考:textAlign プロパティ – Canvasリファレンス – HTML5.JP)。15行目のmeasureTextメソッドで、描画する文字の幅を取得しています(参考:measureText() メソッド – Canvasリファレンス – HTML5.JP)。高さについては14行目で、フォントサイズと同じと考えています(そんな単純じゃなさそうなんですが、textBaselineがmiddleだとこれで大丈夫そうです)。

17~29行目で白地の上の座標を取得しています(一応、textBaselineがtopやbottomなことも考慮して、高さを1.5倍しています)。30~40行目で白地の左の座標を取得しています。後は、42~45行目で、白地の座標が取得できてかつ文字背景の色の指定がある場合(白だと”rgb(255,255,255)”や”#ffffff”)、白地用の長方形を描いています。そうして、52行目でテキストを描画しています。

というわけで、以下実行サンプル。
canvasを使ったお絵描き投稿システム
ラジオボタンから『テキスト』を選んだ後、canvas上をクリック(正確にはマウスダウンやタッチスタート)すると、テキストボックスが表示されるので、そこに文字を入力してエンターキーを押すと文字が描画されます。この時、一緒に表示されるラジオボタンで『不透明』を選択すると白地が描画されます。
本当は、白地の色や、フォントサイズの指定もできたらもっといいんでしょうが、それはそのうち・・・。
なお、呼び出し時のコードは下記のようになっています。

久々にcanvasページをいじりましたが、ものすごく読みづらいコードになってしまっていることに気づきました(今更ですが)。もうちょっとキレイなコードが書けるようになりたいものです。オブジェクト指向とか使って。

コメントを残す

メールアドレスが公開されることはありません。