Canvas2Dについてさっくり復習してみた


Canvas2Dについてさっくり復習してみた

概要

ryokio0129です。

JavaScript Advent Calendar 2020 6日目になります。
初参加です。よろしくお願いいたします。

canvasへの描画に関して、昨今色々なフレームワークやライブラリがあり、そちらを使うことが多いと思います。
かくいう私も、仕事では Phaser というHTML5ゲームフレームワークを使っていることが多いです。

そんな中、たまたま素のCanavs2Dを触らないといけない状況が発生したので、さっくり復習していきます!

Canvas2Dをさっくり復習するどん

Canvas2Dのコンテキスト取得

WebGLにしてもCanvas2Dにしても、HTMLCanvasElementからコンテキストを取得しないと描画できないです。
Canvas2Dに関してはCanvasRenderingContext2Dを取得します。

See the Pen Canvas2Dのコンテキストを取得 by ryokio (@ryokio) on CodePen.

矩形・テキストの描画

矩形の描画は context.fillRect(x, y, width, height)
テキストの描画は context.fillText(text, x, y)

さくっと描画できますが、現状だとどちらも黒で何がなんだかわからないですね……。

See the Pen 矩形・テキストの描画 by ryokio (@ryokio) on CodePen.

色を指定する

色……特に塗りつぶすための色を指定するのは context.fillStyle を使います。
context.fillStyle はCSSの指定そのまま使えるので、例えば context.fillStyle = rgba(255, 0, 0, 0.1) のようにすると、不透明度も反映することが可能です。

色は変わりましたが、これだとどちらも同じ色になってしまいます。
これだと困りますね……。

See the Pen 色を指定する by ryokio (@ryokio) on CodePen.

描画状況の保存・復元

context.save() で今の描画状況を保存します。
context.restore() で保存した状況を復元します。

これで矩形のみがrgba(255, 0, 0, 0.1)になりました。
また、

context.save();

  // この時点での描画を保存
  context.save();
  context.fillStyle = '#00FF00';
  context.restore();

context.restore();

のように入れ子も出来ますが、context.save()context.restore() が抜けると大変なことになりますので、ご注意を。
(今までで context.restore() の記載が抜けてることの方が多かったです)

See the Pen 描画状況の保存・復元 by ryokio (@ryokio) on CodePen.

様々な図形

円弧を描く場合は context.arc() を使えば描けます。
context.beginPath() でパスを使いたい宣言をします。その後に、context.arc() を使って描画します。

See the Pen 円弧を描く by ryokio (@ryokio) on CodePen.

また context.moveTo() でパスの始点を変更することができます。
それを使って、様々な図形を描くことが可能です。

画像の描画

画像の描画は context.drawImage() で行います。
ですが、画像はまず画像を読み込み終えていることが前提ですので、画像が読み込み終わっているかのチェックが必要になります。

See the Pen 画像の描画 by ryokio (@ryokio) on CodePen.

context.drawImage() は画像以外にも色々指定することができます。

変形

図形や画像などは変形することが可能です。

拡縮に関しては context.scale()
移動に関しては context.translate()
回転に関しては context.rotate()

複雑な変形を行う場合は context.transform() もしくは context.setTransform() で可能です。
context.transform() は現状のマトリクスからの変形。
context.setTransform() は現状のマトリクスを破棄して変形(上書き)です。
どちらにしても2Dの行列計算が必要です。調べれば出てくるとはいえ、私は苦手です……。

See the Pen 変形 by ryokio (@ryokio) on CodePen.

合成

直前の描画との合成をする際は、context.globalCompositeOperation を設定します。
私は黒の矩形を画像で抜いて、シルエット画像にする。ということが多いでしょうか。
(これによって、わざわざシルエット画像を用意してもらう必要がなくなる)

See the Pen 合成 by ryokio (@ryokio) on CodePen.

オフスクリーンレンダリング

合成 の際に少しやっていますが、新しいcanvas要素を作り、そこにひとまず描画を行い、
その結果を、実際のcanvasに描画して反映させています。
いわゆるオフスクリーンレンダリングです。

専用の OffscreeCanvas というものもあるようですが、当面はこの手法でやるしかないのかなと思っています。

OffscreenCanvas - Web APIs | MDN
https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas

終わりに

アドベントカレンダー初参加だ!
と思いつつも、仕事が忙しい(言い訳)ために、今急いで書いた次第であります。
だが、参加することに意義がある! ……と信じつつ。

根っこのCanvas2Dを触れようとしている方の一助になれば幸いです。
ありがとうございました。