- 公開日: 2018年03月26日
JavaScriptでお絵描きできるcanvas要素
最近のWebブラウザには、JavaScriptで「お絵描き」が楽しめる「キャンバス(canvas要素)」を置くことができます。実際にどんな感じで絵を描くことができるのか、試してみることにしましょう。
Webブラウザに「お絵描き」できるcanvas要素
canvas要素は、Webブラウザの画面内に動的(表示時にプログラムで操作可能)な描画領域を作る仕組みです。Webブラウザ上にcanvas要素を配置すると、その部分は画像(img要素)に近い感覚で扱える描画領域になります。
描画機能のAPIには、長方形、パス(経路)を指定した多角形、円、文字列などを描くための基本的な機能が用意され、JavaScriptに読み込んだ画像を描画することも可能です。さらに、canvas要素の各ピクセルの色を直接読み書きするフレームバッファ機能も用意されています。
通常の「グラフィックプログラミング」に必要なものは、一通り用意されていると言えるでしょう。各ピクセルの色を直接設定できるので、標準機能に不足があってもやろうと思えば(自力計算で)「何でもあり」です(現実的かどうかはともかく)。
canvas要素に描かれた画像は、通常の画像と同じくユーザーが画像ファイルに保存したりJavaScriptからpngやjpegのデータを取得することも可能です。つまり、Web上でちょっとした画像処理を行って処理結果を表示、さらに画像ファイルとして保存する「画像処理アプリケーション」を開発することもできます。
では実際にcanvas要素を配置したhtmlファイルを作成し、JavaScriptで何か描いてみましょう。
html内にcanvas要素を配置するには、以下のようなcanvasタグを記述します。
<canvas id="test_canvas" width=256 height=256></canvas>
JavaScriptから扱いやすいように、idと大きさも指定してみました。
JavaScriptからcanvas要素を扱うには、「context」が必要になります。contextは、以下のようにcanvas要素のgetContext()メソッドで取得します。
var test_context = document.getElementById('test_canvas').getContext('2d');
今回は、getContext()の引数に基本的な描画機能を利用するための「2d」を指定しました。getContext()の引数によっては、WebGL(Webブラウザ向けOpenGL ES)を通して高度な演算・描画処理を行うWebGL用contextを取得することもできます。
実際に描画を行う際は、このcontextのプロパティやメソッドを通してcanvas要素にアクセスするわけです。
以上の流れを一つのhtmlファイルにまとめたのが、以下になります。
<!DOCTYPE html>
<html>
<body>
<canvas id="test_canvas" width=256 height=256 style="border: 1px solid;"></canvas>
<script>
var test_context = document.getElementById('test_canvas').getContext('2d');
</script>
</body>
</html>
このhtmlを適当なファイル名で保存したら、Webブラウザで表示してください。枠で囲われたcanvas要素が表示されるはずです。
canvas要素に長方形を描く
これでtest_contextを通してcanvas要素に描画できる状態になったので、Webブラウザのアドレス欄に以下のようなJavaScriptのコードを入れて改行キーを押してみましょう。
javascript:test_context.fillRect(64,64,128,128)
枠で囲われたcanvas要素内に、黒い正方形が描かれたと思います。contextのfillRect()は、「左上のx/y座標と幅/高さ」を指定して塗りつぶし長方形を描く関数です。事前に色を設定していないので、デフォルトの黒で描かれました。
塗りつぶしの色は、fillStyleプロパティで設定できます。たとえば、以下のようにするとcontextの塗りつぶし色は、青(0000ff)に設定されます。
test_context.fillStyle = '#0000ff';
先ほどのhtmlを以下のように書き換えて、リロードしてみましょう。
<!DOCTYPE html>
<html>
<body>
<canvas id="test_canvas" width=256 height=256 style="border: 1px solid;"></canvas>
<script>
var test_context = document.getElementById('test_canvas').getContext('2d');
test_context.fillStyle = '#0000ff';
test_context.fillRect(64,64,128,128)
</script>
</body>
</html>
fillStyleの設定が反映されて、青い正方形が表示されました。
今度は、塗りつぶさない輪郭だけの長方形を描いてみましょう。fillRect()の代わりにstrokeRect()という関数を使ってみます。
輪郭を描くときも、色などの設定が可能です。輪郭(contextで描く線)の色は、strokeStyleプロパティで設定します。たとえば、輪郭を赤線にしたいなら以下のようにします。
test_context.strokeStyle = '#ff0000';
さらに、線の太さもlineWidthプロパティで設定できます。少し太めに描いてみましょうか。
test_context.lineWidth = 8;
線の設定を行ったら、実際に描いてみます。
<!DOCTYPE html>
<html>
<body>
<canvas id="test_canvas" width=256 height=256 style="border: 1px solid;"></canvas>
<script>
var test_context = document.getElementById('test_canvas').getContext('2d');
test_context.strokeStyle = '#ff0000';
test_context.lineWidth = 8;
test_context.strokeRect(32, 32, 64, 64);
</script>
</body>
</html>
Webブラウザ上に図形が描かれているのを確認したら、通常の画像と同じく「保存」してみてください。たとえばWindows版のChromeなら、canvas要素の上で右クリックすると出てくるコンテキストメニューから名前を付けて保存できます。
canvas要素に文字列を描く
次に、文字列を描いてみましょう。
文字列も、中を塗りつぶすfillText()と輪郭だけを描くstrokeText()が用意されていて、いずれも引数に「文字列, x座標, y座標」を指定します(オプションで最大幅を追加指定することもできます)。
輪郭正方形を描くhtmlのstrokeRect()を、以下のようにstrokeTextに差し替えて再度読み込んでみてください。
test_context.strokeText("abc", 64, 64);
なにやらごちゃごちゃした「赤い塊」が描かれましたね……
デフォルトのフォントが小さめなので、太い線で描くと線に埋もれてしまうようです。fontプロパティで大き目のフォントに変更してみましょう。
fontプロパティには、cssのfontと同じ形式でフォント設定を行えるので、以下の文をstrokeText()の前に入れてみてください。
test_context.font = '72px serif';
今度は、大きな文字が太線で描かれました。
先の例では文字列が指定x座標に対して「左寄せ」で描かれましたが、中央寄せにしたい場合もあるでしょう。その場合は、textAlignプロパティに「center」を指定すると、文字列描画関数に渡すx座標が中央に来るように文字列を描くことができます。
今回作成したcanvas要素は、width(横幅)を256に設定していたので
test_context.textAlign = 'center';
test_context.strokeText("abc", 128, 64);
とすると、ちょうど中央に描かれます。
canvas要素に画像を描く
以上、長方形や文字列を描く方法を見てきましたが、続いてcanvas上に画像を描いてみることにします。
canvas要素に画像を描くためには、まずJavaScriptで画像を読み込む必要があります。
画像はhtml内のimg要素でも良いのですが、今回はImageオブジェクトを使用してみました。Imageオブジェクトは、画像を保持するオブジェクトです。srcプロパティに画像の場所を指定すると画像を読み込み、JavaScriptから利用できるようになります。
ただ、実際の描画は画像の読み込みが終わってから行う必要があるので、「onload」プロパティで「画像の読み込みが終わったら実行する関数」を設定しておきます。
以下のようにすると、同じディレクトリにあるtest.jpgをImageオブジェクトimgに読み込んで、読み込みが終わったらdraw()関数を実行することができます。
var img = new Image();
img.onload = draw;
img.src = 'test.jpg';
src(Imageオブジェクトに読み込む画像)は、onloadイベント設定の後に指定している点に注意してください。この順序を逆にするとonloadが設定される前に読み込みが終わってしまい、draw()関数が呼ばれなくなる可能性があります。
画像を読み込んだら、実際にcontextを通して描画を行います。画像の描画に使用する関数は、drawImage()関数です。
drawImage()には、いくつもの呼び出し(引数)の形がありますが、まずは一番簡単な「描画する画像, x座標, y座標」の形で試してみましょう。
以下のhtmlファイルを作成し、適当な画像test.jpgと同じディレクトリに置いた上でWebブラウザで表示してみてください。
<!DOCTYPE html>
<html>
<body>
<canvas id="test_canvas" width=256 height=256 style="border: 1px solid;"></canvas>
<script>
function draw() {
test_context.drawImage(img, 0, 0);
}
var test_context = document.getElementById('test_canvas').getContext('2d');
var img = new Image();
img.onload = draw;
img.src = 'test.jpg';
</script>
</body>
</html>
canvas要素の左上に画像が表示されたと思います。
drawImage()では、画像の一部を描くことも可能です。画像の一部を描く場合は
drawImage(転送元x座標, 転送元y座標, 転送する横幅, 転送する高さ, 描画先x座標, 描画先y座標, 描画する横幅, 描画する高さ)
という形で呼び出します。「転送元」は、画像の、「描画先」はcanvas要素の画像で指定します。
試しに、先ほどのhtmlファイルのdrawImage()を以下のように書き換え再読み込みしてみてください。
test_context.drawImage(img, 0, 0, 64, 64, 96, 96, 64, 64);
今度は、画像の左上の部分(0, 0)-(63,63)が、canvas要素の中央(96, 96, 159, 159)に描かれました。
先の例では描画する大きさを画像に合わせましたが、画像の転送(切り出し)サイズと描画サイズを異なる値にすると「拡大縮小」を実現できます。たとえば、
test_context.drawImage(img, 0, 0, 64, 64, 64, 64, 128, 128);
とすれば、画像の左上64×64の部分をcanvas要素の中央128×128の範囲に拡大描画できるわけです。
\Webサイト担当者としてのスキルが身に付く/
Webブラウザで手軽なお絵描きプログラミング
以上、駆け足で図形や文字列・画像の描画、さらに画像ファイルに保存といったcanvas要素の基本的な使い方を試してみました。図形や画像を描くプログラムがごく短いコードで実現できるのは、「画面に表示されているWebブラウザ」を対象にプログラミングを行うJavaScriptならではですね。
Webブラウザ上にJavaScriptで絵を描いて画像ファイルに保存できる、ということは、テキストエディタだけで「絵を描くプログラム」を作成し、描いた絵を保存できることを意味します。
ちょっとした図形や文字列を組み合わせたイラストが欲しい、というときは手軽で便利な方法にもなり得ますので、機会があればWebブラウザを「お絵描きツール」としても活用してみてください。
- この記事を書いた人
- 宍戸輝光