プログラミング初心者の勉強ブログ #102
ドットインストールの「HTML5 Canvas入門」でcanvasタグを学習。JSを使ってcanvasで図形を描画する流れのまとめ。自分の好きな図形を作成でき、イベントもアニメーションも設定できるので相当幅が広がる気がする。
目次
[toc]
canvasで出来ること
HTMLのcanvasタグは、
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Canvas</title> </head> <body> <canvas id="stage"></canvas> </body> </html>
html側でcanvasタグを書き込み、JS側でcanvas要素を「contextオブジェクト」として取得し操作していくことで、様々な図形を自分で描画できる。また、自分で描画した図形に対しアニメーションやイベントアクションを加えることも可能。
- 図形の描画
- グリッドの描画
- テキストの表示
- 画像の表示
- アニメーション化
- イベントオブジェクトの設定
使いこなしたらブラウザ上に表示されるほとんどの表現を、canvasで作れるのではないかと思う。
ちなみにドットインストールではcanvas入門として、
このようなアニメーションをcanvasで作成する。車はクリックで動き出し、もう一度クリックすると止まるようになっている。
以下ではcanvasを操作するために用いるcontextオブジェクトを、JSで取得し設定するために必要なメソッド類をまとめていく。
初期化関係
html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Canvas</title> </head> <body> // canvasタグのマークアップ <canvas id="stage"></canvas> </body> </html>
js
(function() { // canvasタグに設定したidで要素を取得 let stage = document.getElementById('stage'); // contextオブジェクト用変数宣言 let ctx; // idから要素を取得できなかったとき用 if (typeof stage.getContext === 'undefined') { return; } // stageからcontextオブジェクトを生成(2dや3dを引数にとる) ctx = stage.getContext('2d'); })();
基本的に操作は全てJSで行う。イベントオブジェクトと同様、コンテキストオブジェクトをまず生成しなければならない。canvasは非対応ブラウザも存在するため、undefinedの分岐を加えておく必要がある。
矩形の描画
strokeRect
// 枠線のみの矩形の描画 // 下の場合ブラウザ右端から右へ100、左へ50移動した地点に // width:100, height:60の四角形が表示される ctx.strokeRect(100, 50, 100, 60);
strokeRectは枠線のみの図形の描画を行う。
fillRect
// 塗りつぶした矩形の描画 ctx.fillRect(120, 70, 100, 60);
fillRectは塗りつぶした矩形の描画を行う。使い方はstrokeRectと同じ。
clearRect
// 指定した矩形の形で透明にくりぬける ctx.fillRect(140, 90, 100, 60);
fillRect指定した矩形の形で透明にくりぬけ、画面を一旦クリアにするときなどに利用できる。使い方は上2つと同じ。
矩形以外の図形をpathで描画
座標を指定した図形
let x = 100; let y = 100; // pathの開始宣言 ctx.beginPath(); // 開始座標に移動 ctx.moveTo(x, y); // 2つめの座標を指定 ctx.lineTo(x + 100, y + 100); // 3つめの座標を指定 ctx.lineTo(x + 200, y); // pathの終了宣言 ctx.closePath(); //3点で囲まれた部分を塗りつぶす ctx.fill(); //3点からなる図形の線の描画 ctx.stroke();
自分で座標を指定し、その座標からなる図形の描画する。beginPathで開始宣言、closePathで終了宣言となる。指定した図形はfullで塗りつぶしができ、strokeで線の描画ができる。
円弧
ctx.beginPath(); // 開始座標に移動 ctx.moveTo(50, 40); // 下の場合、座標(50, 40)の地点を円の中心とした半径20の円 // の4分の1の扇型になる ctx.arc(50, 40, 20, 0, 90 * Math.PI / 180, false); //円弧の線の描画 ctx.stroke(); //円弧の塗りつぶし ctx.fill();
円弧の場合もpathを使う。arcは弧度法(ラジアン)で円弧の形を指定する。リファレンスをみてて動かさないと動きは掴めない。
参考:CanvasRenderingContext2D.arc() – MDN
スタイルの設定
//// 必ず描画の前に書き込む // 線のスタイル変更 ctx.strokeStyle = 'red'; ctx.lineWidth = 3; // 塗りつぶしのスタイル変更 ctx.fillStyle = 'skyblue'; // 影の作成 ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'; ctx.shadowOffsetX = 5; ctx.shadowOffsetY = 5; ctx.shadowBlur = 5; ctx.fillStyle = 'black'; // 円形グラデーション let g = ctx.createRadialGradient(100, 100, 0, 100, 100, 20); # 半径0から20までの円の範囲でグラデーション変数を代入 g.addColorStop(0.0, 'red'); # 開始はレッド (0%) g.addColorStop(0.5, 'orange'); # 中間はオレンジ(50%) g.addColorStop(1.0, 'yellow'); # 最後はイエロー(100%) ctx.fillStyle = g; # グラデーション変数を反映 ctx.beginPath(); ctx.arc(100, 100, 20, 0, 360 * Math.PI / 180, false); # 半径20の円を描画 ctx.fill(); # 塗りつぶしで表示 // 線形グラデーション let g = ctx.createLinearGradient(100, 80, 100, 120); # 座標(100, 80)から座標(100, 120)の方向へグラデーション変数を代入 g.addColorStop(0.0, 'orange'); # 開始はオレンジ(0%) g.addColorStop(1.0, 'yellow'); # 最後はイエロー(100%) ctx.fillStyle = g; # グラデーション変数を反映 ctx.beginPath(); ctx.arc(100, 100, 20, 0, 360 * Math.PI / 180, false); # 半径20の円を描画 ctx.fill(); # 塗りつぶしで表示
描画の前にスタイルを指定する。線や塗りつぶしだけでなく、影やグラデーションもそれぞれメソッドが存在する。
テキストの表示
//フォントの設定 ctx.font = '14px Arial'; // ベースラインの設定 ctx.textBaseline = 'middle'; // テキストアラインの設定 ctx.textAlign = 'center'; // 座標(100, 100)にテキストの表示 ctx.fillText('hogehoge', 100, 100);
fillTextの第一引数に表示したいテキストを入れる。
画像の表示
//画像オブジェクトの初期化 let img = new Image(); //画像パスの指定 img.src = 'img/hoge.png'; // 画像の表示① // 座標(100, 100)に表示 ctx.drawImage(img, 100, 100); // 画像の表示② // 引数に画像のwidthとheightを指定できる ctx.drawImage(img, 100, 100, 300, 200); // 画像の表示③ // styleでrepeatも可能 ctx.fillStyle = ctx.createPattern(img, 'repeat'); ctx.fillRect(100, 100, 300, 200);
canvasでも画像を操作できる。
まとめ
今回やったドットインストールの「HTML5 Canvas入門」は、最後の方にリファクタリングを教えてくれる。なんかもう感動するくらいサラサラとメソッドが整理され、ごちゃごちゃしていたコードがあっという間にオブジェクト指向設計されていく。現状ドットインストールのレッスンを400くらい受けているが、いよいよまじで尊敬してしまいそう。とりあえず真似して自分でも違うレッスンでやったJSのコードをリファクタリングしてみるものの、変数にするべきなのかプロパティ化するべきなのか判断基準がイマイチわからない。変数のスコープを意識して、できる限り狭める感覚はなんとなくだがわかってきたかもしれない。これからJS書くときは、何回も使う変数は宣言と代入を分けて書こうと思う。自力である程度設計できるようになりたい。RailsよりJSの方がオブジェクト設計の勉強になっている。
以上ありがとうございました。