プログラミングとイラストレーション » HTMLのCanvasに再帰的に正五角形と五芒星形を描く
プログラミングとイラストレーション > HTML5 > HTMLのCanvasに再帰的に正五角形と五芒星形を描く

HTMLのCanvasに再帰的に正五角形と五芒星形を描く

HTMLのCanvasに再帰的に正五角形と五芒星形を描く

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

今回は、HTMLのCanvasに、再帰的に正五角形と五芒星を描きます。このふたつの図形の一辺は、黄金比率を持っています。その性質を使うと再帰的に図形を描いていくことができます。

HTMLのCanvasに再帰的に正五角形と五芒星形を描く : デモ

HTMLのCanvasに再帰的に正五角形と五芒星形を描く : ZIPファイル(6kb)

HTMLのCanvasに再帰的に正五角形と五芒星形を描くための図

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"; /* 文字のエンコードをHTMLページと合わせます */

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); //HTMLページのロードが終わった時点で、init()関数を実行する

function init()
{
	//変数の定義
	var centerX = 0,
	centerY = 0,
	ctx = null,
	theCanvas = null,
	points = [], //線を描くためのx値とy値のための配列
	degs = [270, 342, 54, 126, 198], //図形の中心位置(o)からの各点の角度
	length = degs.length, //degs配列の総数を変数に入れる
	pentacles = [], //五芒星の配列1
	pentacles2 = [], //五芒星の配列2
	pentacles3 = [], //五芒星の配列3
	pentacles4 = []; //五芒星の配列4
	
	//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(pentacles[0].x + centerX, pentacles[0].y + centerY); //線の開始位置 (xの座標値 , yの座標値)
		
		for (var i = 1; i < pentacles.length; i++) //配列がなくなるまで、線を引く処理を続ける
		{
			ctx.lineTo(pentacles[i].x + centerX, pentacles[i].y + centerY); //配列から順番にx値とy値を取り出し、線を結ぶ
		}
		ctx.lineTo(pentacles[0].x + centerX, pentacles[0].y + centerY); //最初の座標値へ線を引く
		
		//Pentacle 1
		ctx.moveTo(centerX + pentacles[0].x, centerY + pentacles[0].y);
		ctx.lineTo(centerX + pentacles[2].x, centerY + pentacles[2].y);
		
		ctx.moveTo(centerX + pentacles[0].x, centerY + pentacles[0].y);
		ctx.lineTo(centerX + pentacles[3].x, centerY + pentacles[3].y);
		
		ctx.moveTo(centerX + pentacles[1].x, centerY + pentacles[1].y);
		ctx.lineTo(centerX + pentacles[4].x, centerY + pentacles[4].y);
		
		ctx.moveTo(centerX + pentacles[1].x, centerY + pentacles[1].y);
		ctx.lineTo(centerX + pentacles[3].x, centerY + pentacles[3].y);
		
		ctx.moveTo(centerX + pentacles[2].x, centerY + pentacles[2].y);
		ctx.lineTo(centerX + pentacles[4].x, centerY + pentacles[4].y);
		
		
		//Pentacle 2
		ctx.moveTo(centerX + pentacles2[0].x, centerY + pentacles2[0].y);
		ctx.lineTo(centerX + pentacles2[2].x, centerY + pentacles2[2].y);
		
		ctx.moveTo(centerX + pentacles2[0].x, centerY + pentacles2[0].y);
		ctx.lineTo(centerX + pentacles2[3].x, centerY + pentacles2[3].y);
		
		ctx.moveTo(centerX + pentacles2[1].x, centerY + pentacles2[1].y);
		ctx.lineTo(centerX + pentacles2[4].x, centerY + pentacles2[4].y);
		
		ctx.moveTo(centerX + pentacles2[1].x, centerY + pentacles2[1].y);
		ctx.lineTo(centerX + pentacles2[3].x, centerY + pentacles2[3].y);
		
		ctx.moveTo(centerX + pentacles2[2].x, centerY + pentacles2[2].y);
		ctx.lineTo(centerX + pentacles2[4].x, centerY + pentacles2[4].y);
		
		
		//Pentacle 3
		ctx.moveTo(centerX + pentacles3[0].x, centerY + pentacles3[0].y);
		ctx.lineTo(centerX + pentacles3[2].x, centerY + pentacles3[2].y);
		
		ctx.moveTo(centerX + pentacles3[0].x, centerY + pentacles3[0].y);
		ctx.lineTo(centerX + pentacles3[3].x, centerY + pentacles3[3].y);
		
		ctx.moveTo(centerX + pentacles3[1].x, centerY + pentacles3[1].y);
		ctx.lineTo(centerX + pentacles3[4].x, centerY + pentacles3[4].y);
		
		ctx.moveTo(centerX + pentacles3[1].x, centerY + pentacles3[1].y);
		ctx.lineTo(centerX + pentacles3[3].x, centerY + pentacles3[3].y);
		
		ctx.moveTo(centerX + pentacles3[2].x, centerY + pentacles3[2].y);
		ctx.lineTo(centerX + pentacles3[4].x, centerY + pentacles3[4].y);
		
		
		//Pentacle 4
		ctx.moveTo(centerX + pentacles4[0].x, centerY + pentacles4[0].y);
		ctx.lineTo(centerX + pentacles4[2].x, centerY + pentacles4[2].y);
		
		ctx.moveTo(centerX + pentacles4[0].x, centerY + pentacles4[0].y);
		ctx.lineTo(centerX + pentacles4[3].x, centerY + pentacles4[3].y);
		
		ctx.moveTo(centerX + pentacles4[1].x, centerY + pentacles4[1].y);
		ctx.lineTo(centerX + pentacles4[4].x, centerY + pentacles4[4].y);
		
		ctx.moveTo(centerX + pentacles4[1].x, centerY + pentacles4[1].y);
		ctx.lineTo(centerX + pentacles4[3].x, centerY + pentacles4[3].y);
		
		ctx.moveTo(centerX + pentacles4[2].x, centerY + pentacles4[2].y);
		ctx.lineTo(centerX + pentacles4[4].x, centerY + pentacles4[4].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;
		
		//Canvasタグで2次元描画を行ないます
		ctx = theCanvas.getContext("2d");

		var dist = 100; //原点(0, 0)からの各頂点までの長さ

		//各頂点のそれぞれのx値, y値を計算して、配列に格納します
		for (var i = 0; i < length; i++)
		{
			var deg = degs[i]; //角度を変数に代入する
			var x = Math.cos(deg * Math.PI/180) * dist; //距離(distance)と角度(deg)からxの位置を求める方程式
			var y = Math.sin(deg * Math.PI/180) * dist; //距離(distance)と角度(deg)からyの位置を求める方程式
			pentacles[i] = {x:x, y:y}; //求めたx,yを配列に格納する
		}
		
		var dx = pentacles[0].x - pentacles[1].x;
		var dy = pentacles[0].y - pentacles[1].y;
		var dis = Math.sqrt(dx * dx + dy * dy);
		var fai = ((1 + Math.sqrt(5)) / 2); //黄金比率1.618...を算出
		
		var x = Math.cos(144 * Math.PI / 180) * dis;
		var y = Math.sin(144 * Math.PI / 180) * dis;
		pentacles2[0] = { x:pentacles[1].x + x, y:pentacles[1].y + y };
		
		//正五角形と五芒星の一辺には黄金比率の性質がある
		//その性質を使って五芒星の一辺を分けると次の正五角形の各頂点の座標位置が現れる
		x = Math.cos(144 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(144 * Math.PI / 180) * dis * 1 / fai;
		pentacles2[1] = { x:pentacles[1].x + x, y:pentacles[1].y + y };

		x = Math.cos(180 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(180 * Math.PI / 180) * dis * 1 / fai;
		pentacles2[2] = { x:pentacles[1].x + x, y:pentacles[1].y + y };
		
		x = Math.cos(360 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(360 * Math.PI / 180) * dis * 1 / fai;
		pentacles2[3] = { x:pentacles[4].x + x, y:pentacles[4].y + y };
		
		x = Math.cos(36 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(36 * Math.PI / 180) * dis * 1 / fai;
		pentacles2[4] = { x:pentacles[4].x + x, y:pentacles[4].y + y };
		

		dx = pentacles2[0].x - pentacles2[1].x;
		dy = pentacles2[0].y - pentacles2[1].y;
		var dis = Math.sqrt(dx * dx + dy * dy);
		
		
		x = Math.cos(-216 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(-216 * Math.PI / 180) * dis * 1 / fai;
		pentacles3[0] = { x: pentacles2[2].x + x, y:pentacles2[2].y + y };
		
		
		x = Math.cos(108 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(108 * Math.PI / 180) * dis * 1 / fai;
		pentacles3[1] = { x: pentacles2[2].x + x, y:pentacles2[2].y + y };
		
		x = Math.cos(180 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(180 * Math.PI / 180) * dis * 1 / fai;
		pentacles3[2] = { x: pentacles2[1].x + x, y:pentacles2[1].y + y };
		
		x = Math.cos(360 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(360 * Math.PI / 180) * dis * 1 / fai;
		pentacles3[3] = { x: pentacles2[4].x + x, y:pentacles2[4].y + y };
		
		x = Math.cos(-36 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(-36 * Math.PI / 180) * dis * 1 / fai;
		pentacles3[4] = { x: pentacles2[4].x + x, y:pentacles2[4].y + y };
		
		
		dx = pentacles3[0].x - pentacles3[1].x;
		dy = pentacles3[0].y - pentacles3[1].y;
		var dis = Math.sqrt(dx * dx + dy * dy);
		
		x = Math.cos(72 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(72 * Math.PI / 180) * dis * 1 / fai;
		pentacles4[0] = { x:pentacles3[0].x + x, y:pentacles3[0].y + y };
		

		x = Math.cos(144 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(144 * Math.PI / 180) * dis * 1 / fai;
		pentacles4[1] = { x:pentacles3[1].x + x, y:pentacles3[1].y + y };
		
		
		x = Math.cos(-144 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(-144 * Math.PI / 180) * dis * 1 / fai;
		pentacles4[2] = { x:pentacles3[2].x + x, y:pentacles3[2].y + y };
		
		
		x = Math.cos(-72 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(-72 * Math.PI / 180) * dis * 1 / fai;
		pentacles4[3] = { x:pentacles3[3].x + x, y:pentacles3[3].y + y };
		
		
		x = Math.cos(360 * Math.PI / 180) * dis * 1 / fai;
		y = Math.sin(360 * Math.PI / 180) * dis * 1 / fai;
		pentacles4[4] = { x:pentacles3[4].x + x, y:pentacles3[4].y + y };
	}
	
	//Modelの中のInit関数のインスタンスを生成
	var model = new Model.init();
	//Model関数のプロトタイプにあるready関数を呼び出します
	model.ready();
	
	//Viewの中のInit関数のインスタンスを生成
	var view = new View.init();
	//View関数のプロトタイプにあるdraw関数を呼び出します
	view.draw();
}

コメントを残す

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

コメントフィード

トラックバック URL : http://www.htmlcode.jp/html%e3%81%aecanvas%e3%81%ab%e5%86%8d%e5%b8%b0%e7%9a%84%e3%81%ab%e6%ad%a3%e4%ba%94%e8%a7%92%e5%bd%a2%e3%81%a8%e4%ba%94%e8%8a%92%e6%98%9f%e5%bd%a2%e3%82%92%e6%8f%8f%e3%81%8f/trackback/