HTMLのCanvasに一本の線を描く

HTMLのCanvasに一本の線を描く

こんにちは。HTML5 エバンジェリストの小川 洋です。

今回は、HTMLのCanvasに一本の線を、JavaScriptのプログラミングで描きます。

HTMLのCanvasに一本の線を描く : デモ

HTMLのCanvasに一本の線を描く : ZIPファイル(4kb)

線をプログラミングするには、いくつか方法があると思いますが、ここでは、直線の方程式を使って描きます。

直線の方程式は、以下の通りです。

直線の方程式

aは直線の傾きを表し、bはy軸上の切片を表します。aもbも任意の定数値とすると、xの値が決まれば、yの値も決まります。

この数式は、平面上の座標図を前提にしたものなので、HTMLのCanvas領域を、その座標図に見立てる必要があります。

座標図

座標図

その際、Canvasの座標は、左上角を(0, 0)とし、x値は右へ、y値は下に進んで行くに従い増えていきます。ちょうど、下のように、y軸を逆さまにしたような座標図になります。

Canvasの座標

HTML5のCanvasの座標

直線のサンプルは、下記のように座標図に表せます。

直線のサンプル図

しかし、これをHTMLのCanvasにそのまま適用すると、y軸の増減値が逆のため、以下のように逆さまに表示されます。そのため、直線の式にあるaの傾きとbの切片には、それぞれ、-1を掛ける必要があります。

直線のサンプル、逆さま

また、このままでは、Canvasの左上角のo(0, 0)を起点にしたグラフィック表示になってしまうため、Canvasの中心へ、図そのものを移動しなければなりません。JavaScriptでは、この一連の作業を行なうプログラムを作る必要があります。

canvasの中心に移動

そのため、Canvas領域の横幅の半分の値をcenterXに代入し, 縦幅の半分の値をcenterYに代入して、それぞれのx値, y値に足して、グラフィックを表示します。

図形の移動

1.HTML

<!doctype html> <!-- 標準モードでWebページをレンダリング -->
<html lang="ja"> <!-- 言語指定付きのhtml要素 -->
	<head> <!-- ヘッダーの指定 HTMLページの生成に必要な情報を記述 -->
		<meta charset="UTF-8"> <!-- Web上の文字エンコーディングの指定 -->
		<title>HTMLのCanvasに一本の線を引く</title> <!-- ブラウザの上部ウィンドウのバーに表示されるタイトル -->
        <link href="css/base.css" rel="stylesheet" type="text/css"> <!-- cssファイル(デザインの仕様)の読み込み -->
		<script src="js/base.js"></script> <!-- JavaScriptファイル(制御の仕様)の読み込み -->
	</head>

    <body> <!-- HTMLページのメインコンテンツを示す要素 -->
        <canvas id = "viewArea" width = "275" height = "275"></canvas> <!-- 描画領域 -->
    </body>
</html>

2.CSS

@charset "UTF-8";

body /* bodyのデザイン */
{
	margin:0; /* borderより外側の余白は0 */
	padding:0; /* borderより内側の余白は0 */
	background-color: #fff; /* 背景色は白 */ 
	-webkit-transform:translateZ(0px); /* GPUの機能を使う */
}

#viewArea /* id名「viewArea」が付いたCanvas要素(タグ)のデザイン */
{
	position: absolute; /* 配置方法は絶対値 */
	top: 10px; /* Webのページの上から10ピクセルの位置 */
	left: 10px; /* Webのページの左から10ピクセルの位置 */
	width: 275px; /* 幅は275ピクセル */
	height: 275px; /* 高さは275ピクセル */
	border: 1px solid #000; /* 線は1ピクセルの太さで、実線、色は黒。上下左右に引く */
}

3.JavaScript

window.addEventListener("load", init, false);

function init()
{
	//変数の定義
	var centerX = 0,
	centerY = 0,
	ctx = null,
	theCanvas = null,
	points = []; //線を描くためのx値とy値のための配列
	
	//MVCデザインパターンの宣言
	function View(){}; //外観の処理を行うオブジェクトのグループ
	//function Controller(){}; //インタラクティブな制御を行なうオブジェクトのグループ(今回は使いません)
	function Model(){}; //ロジックの処理を行うオブジェクトのグループ
	
	//視覚の処理を行うオブジェクトのグループ
	View =
	{
		//空のinit関数を作る
		init : function()
		{
				
		}
	}
	
	//Viewの中の関数(init)にプロトタイプの変数や関数を定義します
	//プロトタイプには、インスタンスで使う共有の関数や変数を設定します
	View.init.prototype.draw = function()
	{
		//グラフィックの描画関数
		ctx.strokeStyle = "#000000"; //線のカラー設定
		ctx.lineWidth = 1; //線の太さ
		ctx.beginPath(); //パスの描画を始める
		ctx.moveTo(points[0].x + centerX, points[0].y + centerY); //線の開始位置 (xの座標値 , yの座標値)

		var length = points.length; //配列の総数を変数に入れる
		for (var i = 1; i < length; i++) //配列がなくなるまで、線を引く処理を続ける
		{
			ctx.lineTo(points[i].x + centerX, points[i].y + centerY); //配列から順番にx値とy値を取り出し、線を結ぶ
		}
		
		ctx.stroke(); //線の終了
	}
	
	//ロジックの処理を行うオブジェクトのグループ
	Model = 
	{
		//空のinit関数を作る
		init: function()
		{

		}
	}
			
	//Modelの中の関数(init)にプロトタイプの変数や関数を定義します
	//プロトタイプには、インスタンスで使う共有の関数や変数を設定します
	Model.init.prototype.ready = function()
	{
		//Canvasのエレメント要素を変数に代入する
		theCanvas = document.getElementById("viewArea");
		
		//Canvasの中心座標を取得
		//centerX: Canvasタグの横幅の1/2を取得
		var offsetX = (theCanvas.currentStyle || document.defaultView.getComputedStyle(theCanvas,'')).width;
		offsetX = Number(offsetX.replace('px',''));
		centerX =  offsetX / 2;
		
		//centerY: Canvasタグの高さの1/2を取得
		var offsetY = (theCanvas.currentStyle || document.defaultView.getComputedStyle(theCanvas,'')).height;
		offsetY = Number(offsetY.replace('px',''));
		centerY =  offsetY / 2 - 5;
		
		//Canvasタグで2次元描画を行ないます
		ctx = theCanvas.getContext("2d");

		
		//直線の方程式:y = a * x + b
		//aは線の傾き
		//bはy軸の切片
		//直線の方程式を使って、-100から100までの値をとるx値から、y値を計算し、それぞれを配列に追加する
		var a = 1,
		b = 0,
		j = 0;

		a *= -1; //Canvasのy軸は、上ではなく、下に向かって増えるので、-1を掛ける
		b *= -1; //Canvasのy軸は、上ではなく、下に向かって増えるので、-1を掛ける
		
		for (var i = -100; i <= 100; i++) //x値が-100から100までの整数値の場合のy値を計算して、配列に格納する
		{
			points[j] = {x:i, y:a * i + b};
			j++;
			
		}
	}
	
	//Modelの中のInit関数のインスタンスを生成
	var model = new Model.init();
	//Model関数のプロトタイプにあるready関数を呼び出します
	model.ready();
	
	//Viewの中のInit関数のインスタンスを生成
	var view = new View.init();
	//View関数のプロトタイプにあるdraw関数を呼び出します
	view.draw();
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です