HTML+JavaScriptだけでブラウザに図形描画 - Canvas API -
Canvas APIは、HTML+JavaScriptだけで図形を描画するための機能です。従来、ブラウザ上で動的に図形を描画するには、Flashのようなプラグインを利用しなければなりませんでした。しかし、Canvas APIを利用することで、ブラウザ標準の機能だけで同じようなことが実現できます。
今回は、そのCanvas APIを使って、Webページ上に図形を描画するサンプルを解説していきます。サンプル一式は、会員限定特典としてダウンロードできます。記事末尾をご確認ください。
- TIPS 007:キャンバスを準備する
- TIPS 008:キャンバスに四角形を描画する
- TIPS 009:キャンバスに直線を描画する
- TIPS 010:折れ線を描画する
- TIPS 011:多角形を描画する
- TIPS 012:ベジェ曲線を描画する
- TIPS 013:円/円弧を描画する
- TIPS 014:直線から連なる円弧を描画する
- TIPS 015:線のスタイルを設定する
- TIPS 016:角の形状を設定する
- TIPS 017:図形を塗りつぶす
もちろん、Canvas APIは新しい機能なので、まだまだ老舗のFlashには機能面でも生産性でも及ばない点はあまたあります。本格的な開発では、ライブラリなどが充実してくるのを待つべき分野もあるでしょう。また、そもそも対応ブラウザも限定されていますので、無制限にすべてのサイトで利用できるわけではありません。
それでも、Canvas APIはHTML5の中でももっとも注目されている機能のひとつです。今後、ゲームやアニメーションの分野で利用される機会は確実に広がっていくものと予想されます。
表1:Canvas APIの対応バージョン
ブラウザ | 対応バージョン |
---|---|
Internet Explorer | 9以降 |
Firefox | 1.5以降 |
Google Chrome | 1.0以降 |
Safari | 1.3以降 |
Opera | 9以降 |
TIPS 007:キャンバスを準備する
Canvas APIを利用するには、まず図形の描画先(=キャンバス)を準備しておく必要があります。
[リスト1]キャンバスを準備するコード(canvas.html)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>HTML5 TIPS</title> <!--キャンバスの背景色/枠線を指定(3)--> <style> #cv { background-color: #FFF; border: 1px solid black; } </style> <script> ...中略... </script> </head> <body> <!--キャンバスの準備(1)--> <canvas id="cv" width="400" height="300"> <!--Canvas機能に対応していないブラウザへの備え(2)--> Canvas機能に対応したブラウザでアクセスしてください。 </canvas> </body> </html>
キャンバスは、
キャンバスのサイズを指定するには、必ずwidth属性(幅)、height属性(高さ)を利用してください(デフォルト値は300×150ピクセル)。
スタイルシートのwidth/heightプロパティを使うと、
(*)いくらサイズを変更しても、Canvas内部ではwidth/height属性の値に基づいて座標計算されるということです。
(3)は、スタイルシートでキャンバスの枠線や背景色を指定しています。必須ではありませんが、キャンバスにはデフォルトで枠線が付きませんし、背景色は透明です。一般的には、明示的に適切なスタイルを設定しておくのが望ましいでしょう。
TIPS 008:キャンバスに四角形を描画する
[リスト2]キャンバスに四角形を描画するコード(canvas.html)
<script> window.addEventListener('DOMContentLoaded', function() { // Canvas APIが利用できるかを判定(1) if (HTMLCanvasElement) { // コンテキストオブジェクトを取得(2) var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); // 塗りつぶしの四角、枠線だけの四角を描画(3) c.fillRect(20, 20, 150, 200); c.strokeRect(10, 10, 200, 150); } } ); </script>
図1:キャンバス上に四角形が描画された(クリックで拡大) |
Canvas APIは新しい命令なので、利用する前にまず、ブラウザが対応しているかをチェックしなければなりません(*)。これを行っているのが(1)です。
HTMLCanvasElementは、
(*)
Canvas APIを利用できることが確認できたら、続いてコンテキストオブジェクト(以降、コンテキスト)を取得します((2)の部分)。コンテキストは「文脈」という意味で、キャンバス描画のための座標やスタイル情報を管理すると共に、キャンバスへの描画を担当します。Canvas APIのコアとなるオブジェクトと言っても良いでしょう。
コンテキストを取得するには、
コンテキストを取得できたら、いよいよ図形を描画します。サンプルではCanvas APIの中でももっとも基本的なfillRect/storokeRectメソッドを利用しています((3)の部分)。fillRectメソッドは塗りつぶした四角を、srokeRectメソッドは枠線のみの四角を、それぞれ描画します。
[構文]fillRect/storokeRectメソッド
- fillRect(左上のX座標, 左上のY座標, 幅, 高さ)
- strokeRect(左上のX座標, 左上のY座標, 幅, 高さ)
座標は、キャンバスの左上の基点(0, 0)とし、それぞれ水平方向がX座標、垂直方向がY座標となります。右、下に行くにつれて、座標は大きくなります。
TIPS 009:キャンバスに直線を描画する
キャンバスに直線を描画するには、パスを定義したあと、strokeメソッドを呼び出します。
[リスト2]キャンバスに直線を描画するコード(line.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); // パスの開始(1) c.beginPath(); // 始点/終点を設定(2) c.moveTo(15, 15); c.lineTo(350, 250); // パスに沿って直線を描画(3) c.stroke(); } } );
図2:キャンバスに直線が描画された(クリックで拡大) |
Canvas APIを利用する上で、パス(Path)の理解は欠かせません。
パスとは、コンテキストで管理される座標の集合です。Canvas APIでは、今後、パスで表された座標の集合に従って、直線や曲線を描画したり、囲まれた領域を塗りつぶしたりすることになります。
パスは、beginPathメソッドで開始します((1)の部分)。パスを初期化するためのメソッドと言い換えても良いでしょう。既に座標(群)が設定されていた場合には、beginPathメソッドでクリアされます。
続いて、moveToメソッドでパスの始点を、lineToメソッドで終点を、それぞれ設定します((2)の部分)。
ただし、ここまでの操作では、まだ座標を定義しただけです(この時点では、まだキャンバスに図形は描画されません)。パスに沿って直線を描画するには、最後にstrokeメソッドを呼び出してください((3)の部分)。
TIPS 010:折れ線を描画する
折れ線を描画するには、lineToメソッドを繰り返し呼び出します。
[リスト3]折れ線を描画するコード(line2.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); c.beginPath(); c.moveTo(15, 15); c.lineTo(30, 250); c.lineTo(250, 200); c.lineTo(280, 130); c.lineTo(250, 80); c.stroke(); } } );
図3:キャンバスに折れ線が描画された(クリックで拡大) |
lineToメソッドで指定した直線の終点は、そのまま次の直線の始点となります。よって、折れ線を描画したいのであれば、lineToメソッドを繰り返し呼び出します。結果として、上のサンプルであれば、(15, 15)→(30, 250)→(250, 200)→(280, 130)→(250, 80)に、順番に線が引かれていることになります。
TIPS 09と同じく、最後にstrokeメソッドを呼び出すのを忘れないようにしてください。
TIPS 011:多角形を描画する
多角形を描画するには、パス定義の最後でclosePathメソッドを呼び出します。
[リスト4]多角形を描画するコード(polygon.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); c.beginPath(); c.moveTo(15, 15); c.lineTo(30, 250); c.lineTo(250, 200); c.lineTo(280, 130); c.lineTo(250, 80); c.closePath(); c.stroke(); } } );
図4:キャンバスに多角形が描画された(クリックで拡大) |
上のコードは、TIPS 10のコードからわずかにアミカケの部分を付け加えただけです。
closePathメソッドは、最後の座標と最初の座標とを結ぶためのメソッドです。lineToメソッドで、いちいち最初の座標を指定する必要はない点に注目です。
このように、始点と終点とが結ばれたパスのことを「クローズパス」と言います。一方、closePathメソッドが呼び出されなかった(=始点と終点とが結ばれていない)、TIPS 10のようなパスのことをオープンパスと言います。
TIPS 012:ベジェ曲線を描画する
ベジェ曲線とは、以下のような曲線のことを言います。
図5:ベジェ曲線とは?(クリックで拡大) |
制御点が1つのものを二次ベジェ曲線、2つあるものを三次ベジェ曲線と言います。これらのベジェ曲線をCanvas APIで描画するには、quadraticCurveTo(二次ベジェ曲線)、bezierCurveTo(三次ベジェ曲線)メソッドを利用します。
[リスト5]ベジェ曲線を描画するコード(curveTo.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); // 二次ベジェ曲線を描画(左) c.beginPath(); c.moveTo(10, 10); c.quadraticCurveTo(350, 100, 50, 100); c.stroke(); // 三次ベジェ曲線を描画(右) c.beginPath(); // 新たなパスの始まり(1) c.moveTo(100, 150); c.bezierCurveTo(450, 150, 0, 200, 400, 300); c.stroke(); } } );
quadraticCurveTo/bezierCurveToメソッドの構文は、以下のとおりです。
[構文]quadraticCurveTo/bezierCurveToメソッド
- quadraticCurveTo(x1, y1, x2, y2)
- bezierCurveTo(x1, y1, x2, y2, x3, y3)
引数x1、y1...は、冒頭の図の座標に対応しています。また、x0、y0はquadraticCurveTo/bezierCurveToメソッドを呼び出す前の最後の座標を表すものとします(サンプルであればmoveToメソッドで指定された座標です)。
なお、上のサンプルでは独立した2つの図形を描画しています。その場合は、新たな図形(パス)の始まりで、beginPathメソッドを呼び出さなければならない点に注意してください((1))。
TIPS 013:円/円弧を描画する
円や円弧を描画するには、arcメソッドを使います。
[リスト6]円/円弧を描画するためのコード(arc.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); // 中心(100, 150)、半径50の円を描画(1) c.beginPath(); c.arc(100, 150, 50, 0, 2 * Math.PI, false); c.stroke(); // 中心(300, 150)、半径50、45°~180°の円弧を描画(2) c.beginPath(); c.arc(300, 150, 50, 0.25 * Math.PI, Math.PI, false); c.stroke(); } } );
6:円、円弧が描画された(クリックで拡大) |
arcメソッドの構文は、以下のとおりです。
[構文]arcメソッド
- arc(中心のX座標, 中心のY座標, 半径, 開始角度, 終了角度, 反時計回りか)
開始角度は右水平方向(3時の方向)を基点に、時計回りで指定します。角度はラジアンという単位で指定します。ラジアンは「度数÷180×円周率」で求められます。
よって、(1)の「2 * Math.PI」は「360÷180×円周率」で360°(完全な円)を意味します。
もしも「終了角度 - 開始角度」が360°未満である場合には、円弧を描画します。例えば、(2)では45°~180°の範囲で円弧を描画します。円弧はデフォルトで時計回りに描画されますが、arcメソッドの最後の引数をtrueにした場合、円弧は反時計回りに描画されます。
以下は、12行目の最後の引数をtrueに切り替えた場合の結果です。
図7:円弧は反時計回りに描画される(クリックで拡大) |
TIPS 014:直線から連なる円弧を描画する
arcToメソッドを使うことで、直線から連なる円弧を描画できます。
[リスト7]直線から連なる円弧を描画するコード(arcTo.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); c.beginPath(); // 直線から連なる円弧を描画 c.moveTo(100, 250); c.arcTo(200, 10, 380, 280, 50); c.stroke(); } } );
図8:直接から連なる円弧を描画する(クリックで拡大) |
arcToメソッドの構文は、以下のとおりです。それぞれの引数の意味は、図の座標に対応しています。また、x0、y0はarcToメソッドを呼び出す前の最後の座標を表すものとします(サンプルではmoveToメソッドで指定された座標です)。
[構文]arcToメソッド
- arcTo(x1, y1, x2, y2, r)
実際に描画されるのは、図の黒い線の部分です。座標(x2, y2)が終点となるわけではない点に注意してください。
TIPS 015:線のスタイルを設定する
Canvas APIでは、線の色、太さ、先端の形状などを指定できます。
[リスト8]線のスタイルを指定するコード(lineStyle.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); c.strokeStyle = 'Blue'; // 線の色 c.lineWidth = 10; // 線の太さ // 標準の先端(左端) c.beginPath(); c.lineCap = 'butt'; c.moveTo(30, 30); c.lineTo(30, 280); c.stroke(); // 丸めた先端(中央) c.beginPath(); c.lineCap = 'round'; c.moveTo(150, 30); c.lineTo(150, 280); c.stroke(); // 四角の先端(右端) c.beginPath(); c.lineCap = 'square'; c.moveTo(270, 30); c.lineTo(270, 280); c.stroke(); } } );
図9:先端の異なる3本の直線が描画された(クリックで拡大) |
線スタイルに関わるプロパティには、以下のようなものがあります。
表2:線スタイルに関わるプロパティ
プロパティ | 概要 | |
---|---|---|
strokeStyle | 線の色 | |
lineWidth | 線の幅 | |
lineCap | 先端のスタイル(設定値は以下) | |
設定値 | 概要 | |
butt | 既定のスタイル | |
round | 先端を丸める | |
square | 先端を四角くする |
lineCapプロパティのbuttとsquareはよく似ていますが、squareの方が角を加工している分、やや長めになります。
TIPS 016:角の形状を設定する
折れ線を描画する場合、その角のスタイルを指定することもできます。
[リスト9]角の形状を変更したコード(miter.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); c.lineWidth = 10; // 鋭角を設定(左端) c.beginPath(); c.lineJoin = 'miter'; c.miterLimit = 4; c.moveTo(60, 85); c.lineTo(100, 220); c.lineTo(140, 85); c.stroke(); // 平たい角を設定(中央) c.beginPath(); c.lineJoin = 'bevel'; c.moveTo(160, 85); c.lineTo(210, 220); c.lineTo(240, 85); c.stroke(); // 丸めた角を設定(右端) c.beginPath(); c.lineJoin = 'round'; c.moveTo(260, 85); c.lineTo(300, 220); c.lineTo(340, 85); c.stroke(); } } );
図10:先端の異なる折れ線を表示(クリックで拡大) |
角の形状に関わるプロパティには、以下のようなものがあります。
表3:角の形状に関わるプロパティ
プロパティ | 概要 | |
---|---|---|
lineJoin | 先端のスタイル | |
設定値 | 概要 | |
miter | 鋭角(デフォルト) | |
bevel | 角を平たく | |
round | 角を丸める | |
miterLimit | 鋭角の度合い |
miterLimitプロパティは、lineJoinプロパティがmiterの場合のみ有効です。数値が大きい程、鋭くなります。
TIPS 017:図形を塗りつぶす
fillメソッドを利用することで、パスで囲まれた領域を塗りつぶすこともできます。
[リスト10]多角形を塗りつぶすためのコード(fill.html)
window.addEventListener('DOMContentLoaded', function() { if (HTMLCanvasElement) { var cv = document.querySelector('#cv'); var c = cv.getContext('2d'); c.beginPath(); c.moveTo(15, 15); c.lineTo(30, 250); c.lineTo(250, 200); c.lineTo(280, 130); c.lineTo(250, 80); c.closePath(); // 塗りつぶしスタイルを設定 c.fillStyle = 'Red'; c.globalAlpha = 0.5; // パスに沿って塗りつぶし c.fill(); // c.stroke(); } } );
図11:多角形が赤く塗りつぶされた(クリックで拡大) |
塗りつぶしスタイルは、以下のプロパティで指定できます((1)の部分)。
表4:塗りつぶしに関わるプロパティ
プロパティ | 概要 |
---|---|
fillStyle | 塗りつぶし色 |
globalAlpha | 不透明度(0~1。0:透明、1:不透明) |
スタイルを設定できたら、あとはfillメソッドで塗りつぶすだけです。サンプルでは赤、半透明(0.5)で多角形を塗りつぶしています。
もしも図形に枠線を付けたいならば、fillメソッドと合わせて、strokeメソッドを呼び出すこともできます(*)。以下は、18行目のコードをコメントインした場合の結果です。
図12:塗りつぶされた図形に枠線が付いた(クリックで拡大) |
(*)もちろん、TIPS 015、TIPS 016で紹介したような線スタイルを合わせて指定しても構いません。
Canvas APIを使った複数のHTMLサンプル
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- HTML+JavaScriptだけでブラウザに図形描画(2)- Canvas API-
- 動画・音声のブラウザ対応状況、canvasによる描画
- HTML+JavaScriptだけでブラウザに図形描画(3)- Canvas API-
- 簡単な図を描いてみよう!
- HTML 5+JavaScriptでCanvasアプリを作る
- JavaScriptを使って描画するCanvasとは?
- 「TAURI」で「丸アートお絵描き」アプリを作ろう
- 「Krita」と「Python」で「ベジェ曲線」を描いてみよう
- デスクトップアプリライクな操作性を実現するドラッグ&ドロップAPI
- JavaScriptでローカルファイルを自在に操る- File API