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()
でパスの始点を変更することができます。
それを使って、様々な図形を描くことが可能です。
- canvas に図形を描く - 開発者ガイド | MDN
https://developer.mozilla.org/ja/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes
画像の描画
画像の描画は context.drawImage()
で行います。
ですが、画像はまず画像を読み込み終えていることが前提ですので、画像が読み込み終わっているかのチェックが必要になります。
See the Pen 画像の描画 by ryokio (@ryokio) on CodePen.
context.drawImage()
は画像以外にも色々指定することができます。
- CanvasRenderingContext2D.drawImage() - Web API | MDN
https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/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を触れようとしている方の一助になれば幸いです。
ありがとうございました。