【Javascript】Canvasに多角形で「花」を描いてみる

花弁って幾何学的ですよね

ある日、植物園で見たお花が、四角形を組み合わせたような形だったんですよ。

エクメア ファスキアタ

この写真の中心の部分、なんだか四角形とか、五角形とか…の組合せで描画できそうじゃないか…!
ということで、JavascriptでCanvasに多角形を組み合わせたお花風の何かを書くようなコード書いてみました。

Canvasの使い方を学んでたけど…なんかいい練習問題無いかな、って探している人にも丁度いいかなと思います。

デモページ

デモページはこちら

4, 5, 6角形が一番お花っぽく見えます。

ソースコード

コードは下記の通りです。

<html>
<head>
	<title></title>
	<meta charset="UTF-8">
</head>
<body>
	<script>
	class BloomPolygon{
		constructor(default_ctx, default_num, default_size, default_depth_limit, default_rate){
			this.ctx = default_ctx || {};
			this.num = default_num || 3;
			this.size = default_size || 128;
			this.depth_limit = default_depth_limit || 32;
			this.scale_rate = default_rate || 0.92;

			this.fib_a = 1;
			this.fib_b = 1;
		}
		// calc fibonacci
		_fib(){
			var res = this.fib_a + this.fib_b;
			this.fib_a = this.fib_b;
			this.fib_b = res;
			return res;
		}
		// draw polygon
		_drawPolygon(ctx, num, x, y, size){
			ctx.beginPath();
			ctx.moveTo(x + size * Math.cos(0), y + size * Math.sin(0));

			for (var side = 0; side <= num; side++)
			  ctx.lineTo(x + size * Math.cos(side * 2 * Math.PI / num), y + size * Math.sin(side * 2 * Math.PI / num));

			ctx.stroke();
			ctx.closePath();
		}
		// recursively drawing polygons
		_recursiveDraw(ctx, num, size, depth){
			if(depth < 0) return;

			ctx.rotate(this._fib() * Math.PI / 180.0);
			//ctx.rotate(this._pri() * Math.PI / 180.0);
			this._drawPolygon(ctx, num, 0, 0, size);
			
			this._recursiveDraw(ctx, num, size * this.scale_rate, --depth);
		}
		// MAIN function!!
		//   can change context and figure type
		bloom(ctx, num, size, depth_limit, scale_rate) {
			// update if value set
			this.ctx = ctx || this.ctx;
			this.num = num || this.num;
			this.depth_limit = depth_limit || this.depth_limit;
			this.scale_rate = scale_rate || this.scale_rate;

			// draw exec
			this.ctx.strokeStyle = "#eeaadd"
			this.ctx.beginPath();
			this.ctx.translate(128, 128);
			this._recursiveDraw(this.ctx, this.num, size || this.default_size, this.depth_limit);
			this.ctx.closePath();
		}
	}

	var bloomer = new BloomPolygon();

	// draw flower with triangle ~ octagon
	[3, 4, 5, 6, 7, 8]
		.forEach((v)=>{
			document.body.appendChild((function(v){
				var el = document.createElement("canvas");
				el.id = "canvas-" + v;
				el.setAttribute("width", 256);
				el.setAttribute("height", 256);
				bloomer.bloom(el.getContext("2d"), v, 96, 32, 0.92);
				return el;
			})(v));
		});
	</script>
</body>
</html>

大ざっぱな解説としては、お花描画用のクラスが大きく1つ。
最後のほうにそのクラスをインスタンス化して、3角形~8角形まで描画メソッドをコールしている感じです。

描画の中身は、再帰してx角形をフィボナッチ数列の度数だけ回転させて描画しているだけです。

フィボナッチ数を選んだのは、花弁の枚数とか結構フィボナッチ数を踏むらしかったのと、回転角が固定されるより変化した方がいいかなと思ったからです。
素数を回転角にして試してもみたんですが、いまいち綺麗に描けなかったのでやめました。

 

 

 

 

コメントを残す

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