キャンバスに図形やテキストを描画する

JavaScript

キャンバスに図形やテキスト描画する

簡単な例

HTMLに canvasタグを定義し、描画する領域のサイズを指定する。canvasオブジェクトの getContextメソッドで描画コンテキスト取得し、指定した領域に Canvas APIを使って図形やテキストを描画する。
キャンバスのサイズは、canvasタグの中で widthプロパティ, heightプロパティにより指定しなければならない。
CSSファイルにサイズを定義すると正しく動作せず、描画した矩形のサイズが想定を超えた大きさになってしまう。ただし canvasタグと CSSファイル両方に指定すれば正しく動く。canvasタグの内部的な動作とCSSのスケーリングの違いが原因のようである。CSSでサイズを定義しないことはひとつの正しい解決策である。
[sample1.png]

矩形を描く

[sample10.png]
3つの矩形は全て同じサイズである。右側の矩形が大きいのは、枠線が太いからである。枠線は太さを二等分して、それぞれ境界線の外側と内側に広げている

円を描く

[sample11.png]
2つ目の円を描く前に beginPathメソッドを呼ぶ必要がある。そうしないと2つ目の円に指定した塗りつぶしの色で、1つ目の円が塗りつぶされてしまう。矩形の場合はそういうことはない。
なお、図形を枠線で囲み、かつ塗りつぶすことを一度の操作で行うことはできない。

直線を描く

[sample20.png]
直線を引くには moveToメソッドで始点を、lineToメソッドで終点を指定し strokeメソッドをぶ。lineToメソッドを連続すれば一本の折れ線を引くことができる。

1ピクセルの太さの直線を描く

普通に1ピクセルの太さで直線や矩形を描いてみると、1ピクセルにしては線がやや太くてぼやけてるように見える。
[sample21.png]
次の例は1ピクセルの線がシャープに描かれている。
[sample22.png]
書き換えたコードは以下の通り。直線の軸を縦線の場合は x方向に、縦線の場合は y方向に 0.5ピクセルずらしている。矩形の場合はそれを組み合わせる。このような挙動は Canvas APIの仕様とのこと。

多角形を描く

[sample12.png]
多角形は3本以上の複数の直線を結んで描く。直線を結んで形を作った後、枠線で囲まれた図形を描く strokeメソッドまたは、塗りつぶた図形を描く fillメソッドを呼ぶ。
closePathメソッドを使えば、現在の点から終点までを結ぶことができる。多角形の最後の辺を指定するときに使う。

テキストを表示する

[sample30.png]
テキストを出力するときに beginPathメソッドを呼ぶは必要ない。textAlignプロパティにより横方向の表示位置を指定することができる。
[sample31.png]
textBaselineプロパティにより縦方向の表示位置を指定することができる。

図形とテキストを重ねる

[sample40.png]
塗りつぶした矩形の上に、図形やテキストを表示するには、塗りつぶした矩形を描いた後にそれらを描画する。

テキストのサイズを求める

[sample41.png]
テキストは縦横のサイズを属性として持っている。上の図は、テキストのサイズを求め、同じ大きさの矩形を作成し、テキストに合わせて表示したものである。
テキストのサイズを求めるには measureTextメソッドを使用する。
テキストの幅①は ②と③を足したものである。
②は基準点から左の長さ、③は基準点から右の長さである。
textAlign = "left" では ②→ 0 ③→ 240
textAlign = "center" では ②→ 120 ③→ 120
textAlign = "right" では ②→ 240 ③→ 0
テキストの高さは ④と⑤を足したものである。
④は基準点から上の長さ、⑤は基準点から下の長さである。
textBaseline = "alphabetic" では ④→ 51 ⑤→ 5
textBaseline = "top" では ④→ 4 ⑤→ 60
textBaseline = "middle" では ④→ 31 ⑤→ 25
textBaseline = "bottom" では ④→ 65 ⑤→ −9
以下のコードは measureTextメソッドにより求めたテキストのサイズを元に矩形を描画し、その中にテキストを描く処理である。textAlignと textBaselineの値が何であろうとも、適切なテキストの描画の開始位置を求めることができる。

図形、文字列のクリア

[sample50.png]
clearRectメソッドは、指定した矩形領域に描かれている全ての図形、テキストを消去する。

二つのキャンバスを重ねる

簡単な例

HTML
CSS
二つのキャンバスは、一つの div要素の下に子要素として格納する。ポイントは、キャンバスのサイズの指定である。
canvasタグの widthプロパティ、heightプロパティに実サイズを指定する。CSSの定義で position属性を absoluteにし、widthプロパティ、heightプロパティに 100% を指定する。
親要素の divタグの widthプロパティ、heightプロパティに同じサイズを指定する。position属性を relativeにする。少しでも違うとうまくいかないようなので、とにかくこの通りに記述する必要がある。
実行結果
グレーの背景色のキャンバスの上に、同じサイズのキャンバスを重ね、そちらに赤い枠線の矩形を描いている。キャンバスの重なりの上下は CSSの z-indexプロパティで指定することができる。
[sample2.png]
キャンバスの描画とは、画像をグラフィックコンテキスト表示するものである。従って、画像の一部だけ書き換えるというようなことはできない。もし書き換えるには、現在表示している矩形領域をすべてクリアし、その上に変更後の画像を再描画する必要がある。
例えば、一つのキャンバスに複数の異なる図形を重ねて描画していたらどうだろう。具体的には、fillRectメソッドを複数実行し、複数の矩形を描画するなどである。 この場合、一つの矩形のみを消したり、変更したりはできない。そうしたければ、全ての図形を変更の有無にかかわらず一から再描画しなくてはならない。 かなり面倒なことである。
このようなケースでは、複数のキャンバスを重ね合わせる対応が有効である。異なったキャンバスに描画した図形は、それぞれ個別に操作できるので処理が大分簡単になる。

応用例

[sample65.png]
文字列にマウスカーソルを置くと下線が付く。離すと下線が消える。
キャンバスは二つ作成し、重ねる。下のキャンバスには文字列を表示し、上のキャンバスには下線を表示する。JavaScriptで mousemoveイベントを補足し、カーソルが文字列の表示領域に入ったときに下線を表示、抜けたときに下線を消去する。下線の消去はキャンバスの全領域をクリアすることで実現される。なお、マウスイベントを補足できるのは最上位のキャンバスだけである。
また、mousedownイベントを補足し、文字列をクリックしたとき、alertダイアログボックスを表示するようにしている。
HTML
CSS
JavaScript