[HTML5] Canvasに描写 – アトラクタっぽいの

Filed under 3D, HTML5, JavaScript



HTMLのCanvasを利用してアトラクタっぽいやつの描写。

こんな感じになりました。

Canvas部分をクリックすることで再描写されます。

以下、ソースです。

また、jsdo.itにも同じものを投稿しました(こちら)。

HTMLのソース(index.html)

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
    <head>
        <title>Canvas sample 02 Attractor.</title>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <meta http-equiv="Content-Style-Type" content="text/css">
        <meta http-equiv="Content-Script-Type" content="text/javascript">
        <link rel="stylesheet" type="text/css" href="style.css"/>
        <script type="text/javascript" src="script.js"></script>
    </head>
    <body>
        <div id="wrapper">
        	<p>Click to reset.</p>
        	<p>Source code is <a href = "src.zip">Here.</a></p>
        	<p>AS3 version:  <a href="http://wonderfl.net/c/p9i6">PV3Dその10  3Dでアトラクタっぽいの - wonderfl build flash online</a></p>
        	<canvas id="myCanvas" width="600" height="400" onclick="reset()"></canvas>
        </div>
    </body>
</html>

JavaScriptのソース(script.js)

var RADIAN = Math.PI / 180;
var FOCUS = 280;
var CENTER_X = ((600 / 2) | 0);
var CENTER_Y  = ((400 / 2) | 0);
var NUM_1 = 600;
var NUM_2 = 15;
var width;
var height;
var context;
var bmpd;
var bmpdArray;
var points;
var atts;
var count;
var theta;
var func;
var a, b, c, d, i, j, p, dd, xx, yy, zz, scale;

window.onload = function()
{
	var canvas = document.getElementById('myCanvas');
	if (! canvas || ! canvas.getContext ) {return false;}
	else
	{
		width = canvas.width;
		height = canvas.height;
		context = canvas.getContext('2d');

		reset();
	}
}

function onFrame()
{
	context.fillStyle = "#000000";
	context.fillRect(0,0,width, height);
	bmpd = context.getImageData(0, 0, width, height);
	bmpdArray = bmpd.data;

	for(i=0; i < count; i++)
	{
		p = points[i];
		xx = Math.cos(theta * RADIAN) * p.x - Math.sin(theta * RADIAN) * p.z;
		zz = Math.sin(theta * RADIAN) * p.x + Math.cos(theta * RADIAN) * p.z;

		scale = FOCUS * 1.5 / (FOCUS - zz);
		xx = ((xx * scale)|0) + CENTER_X;
		yy = ((p.y * scale)|0) * (-1) + CENTER_Y;

		// 範囲内なら点を打つ
		if (xx >= 0 && yy >= 0 && xx < width && yy < height)
		{
			j = (yy * width + xx)*4;
			bmpdArray[j] = p.cR;
			bmpdArray[j + 1] = 255;
			bmpdArray[j + 2] = p.cB;
			bmpdArray[j + 3] = 255;
		}
	}
	context.putImageData(bmpd,0,0);
	theta ++;
}

function reset()
{
	points = [];
	atts = [];
	theta = 0;

	if(func){ clearInterval(func);}

	// 変数の初期化
	a=(Math.random() - 0.5) * 4;
	if (Math.abs(a) < 1) {a*=2;}
	b=(Math.random() - 0.5) * 4;
	if (Math.abs(b) < 1){ b*=2;}
	c=(Math.random() - 0.5) * 4;
	if (Math.abs(c) < 1){ c*=2;}
	d=(Math.random() - 0.5) * 4;
	if (Math.abs(d) < 1){ d*=2;}

	for(i=0; i < NUM_1; i++){atts[i] = new AttrPoint();}

	count = 0;
	for(j=0 ; j<NUM_2 ; j++)
	{
		for(i=0; i < NUM_1; i++)
		{
			dd = atts[i];
			dd.x1=Math.sin(a * dd.y0) - dd.z0 * Math.cos(b * dd.x0);
			dd.y1=dd.z0 * Math.sin(c * dd.x0) - Math.cos(d * dd.y0);
			dd.z1=Math.sin(dd.x0);

			points[count] =new Point3D(dd.x1 * 70, dd.y1 * 70 + 20, dd.z1 * 70);
			dd.x0=dd.x1;
			dd.y0=dd.y1;
			dd.z0=dd.z1;
			count ++;
		}
	}

	// レンダリング開始
	func = setInterval("onFrame()", 30);
}

function AttrPoint()
{
	this.x0 = Math.random() * 2.0 - 1.0;
	this.y0 = Math.random() * 2.0 - 1.0;
	this.z0 = Math.random() * 2.0 - 1.0;
	this.x1=0;
	this.x2=0;
	this.x3=0;
}

function Point3D(x,y,z)
{
	this.x = x;
	this.y = y;
	this.z = z;

	this.cR = 255*Math.random();
	this.cB = 255*Math.random();
}

CSSのソース(style.css)

*{
	margin:0;
	padding:0;
	border: none;
	text-decoration:none;
	list-style:none;
	font-size:100%;
	font-style:normal;
	font-weight:normal;
}
a:link
{
	text-decoration:underline;
	color: #289000;
}
a:visited
{
	text-decoration:underline;
	color: #599000;
}
a:hover
{
	text-decoration:underline;
	color: #982000;
}
a:active
{
	text-decoration:underline;
	color: #599000;
}
body {
	text-align:left;
	background-color:#ffffff;
}

#wrapper {
	font-size:14px;
	color: #555555;
	width: 600px;
	height:500px;
	margin-top:100px;
	margin-left : auto;
	margin-right : auto ;
}

#myCanvas {
	margin-top:5px;
	background-color: #DDDDDD;
	border: 1px solid #777777;
}

Post a Comment

Your email is never published nor shared.