|| home software nature technology koneta

maHTML/Canvas要素で遊んでみる (2) 化学構造式の描画

ホーム / 技術っぽいもの / HTML/Canvas要素で遊んでみる (1)

[< HTML/Canvas要素で遊んでみる (1)へ] [HTML/Canvas要素で遊んでみる (3)へ >]

2006/03/26

はじめに

一つ前の項目にてcanvas 要素とJavascriptを用いて動的にアニメーション画像を作成する練習をしました。
というわけで今度は折角なのでより専門に近いものとして、選択した化合物の構造をリアルタイムで描画するものを作ってみました。

六員環をひとつだけ含むいくつかの簡単な化合物にしか対応していませんが、それなりに遊べるのではないかと思いますです。

構造式の表記法にはあんまりやる気の無い汎用性を持たせていて、例えばシアヌル酸 (2,4,6-トリヒドロキシ-1,3,5-トリアジン)ならば
「aNbCcNdCeNfC hOjOlO abcbeb hbjblb」という感じの指定になっています(これだけ書いても意味不明ですが。。。)

どうせならSMILEとかに対応させたかった気もしますが、Javascriptにはちょっと荷が重いかも。
ちなみに灰色が炭素、青色が窒素、赤色が酸素、緑色が塩素です。

Chemical structure

お使いのウェブブラウザはcanvasに対応していない模様です。残念。
<canvas>-supported web-browser required.

ソース

View Sourceしたものと同じ内容です。

<script type="text/javascript">
<!--

function Initialize()
{
	canvas = document.getElementById("canvas0201");
	if(canvas.getContext)
	{
		context = canvas.getContext("2d");
		
		// 枠を書く
		context.fillStyle = "#006699";
		context.fillRect(0, 0, 500, 500);
	}
}

// シクロヘキサンを描く
function DrawCyclohexane(x, y)
{
	if(canvas.getContext)
	{
		context = canvas.getContext("2d");
		context.strokeStyle = "#FFFFFF";
		context.beginPath();
		context.moveTo(x, y);
		context.lineTo(x+60, y+30);
		context.lineTo(x+60, y+90);
		context.lineTo(x, y+120);
		context.lineTo(x-60, y+90);
		context.lineTo(x-60, y+30);
		context.lineTo(x, y);
		context.stroke();
	}
}

// 結合を描く
function DrawBond(x, y, p)
{
	if(canvas.getContext)
	{
		context = canvas.getContext("2d");
		context.strokeStyle = "#FFFFFF";
		context.beginPath();
		var xi = -1, yi = -1, xf = -1, yf = -1;
		switch(p)
		{
			case 'a':
				xi = x; yi = y+6; xf = x+54; yf = y+33;
				break;
			case 'b':
				xi = x+54; yi = y+33; xf = x+54; yf = y+87;
				break;
			case 'c':
				xi = x ;yi = y+114; xf = x+54; yf = y+87;
				break;
			case 'd':
				xi = x; yi = y+114; xf = x-54; yf = y+87;
				break;
			case 'e':
				xi = x-54; yi = y+33; xf = x-54; yf = y+87;
				break;
			case 'f':
				xi = x-54; yi = y+33; xf = x; yf = y+6;
				break;
			case 'g':
				xi = x; yi = y; xf = x; yf = y-60;
				break;
			case 'h':
				xi = x+60; yi = y+30; xf = x+114; yf = y-3;
				break;
			case 'i':
				xi = x+60; yi = y+90; xf = x+114; yf = y+117;
				break;
			case 'j':
				xi = x; yi = y+120; xf = x; yf = y+180;
				break;
			case 'k':
				xi = x-60; yi = y+90; xf = x-114; yf = y+117;
				break;
			case 'l':
				xi = x-60; yi = y+30; xf = x-114; yf = y+3;
				break;
			default:
				break;
		}
		if(xi != -1)
		{
			context.moveTo(xi, yi);
			context.lineTo(xf, yf);
			context.stroke();
		}
	}
}
// 原子を描く
function DrawAtom(x, y, p, s)
{
	if(canvas.getContext)
	{
		context = canvas.getContext("2d");
		if(s == 'C')
		{
			context.strokeStyle = "#666666";
			context.fillStyle = "#999999";
		}
		else if(s == 'N')
		{
			context.strokeStyle = "#000099";
			context.fillStyle = "#0000AA";
		}
		else if(s == 'O')
		{
			context.strokeStyle = "#990000";
			context.fillStyle = "#AA0000";
		}
		else if(s == 'X')
		{
			context.strokeStyle = "#009900";
			context.fillStyle = "#00AA00";
		}
		var xp = -1, yp = -1;
		context.beginPath();
		switch(p)
		{
			case 'a':
				xp = x; yp = y;
				break;
			case 'b':
				xp = x+60; yp = y+30;
				break;
			case 'c':
				xp = x+60; yp = y+90;
				break;
			case 'd':
				xp=x;yp=y+120;
				break;
			case 'e':
				xp = x-60; yp = y+90;
				break;
			case 'f':
				xp = x-60; yp = y+30;
				break;
			case 'g':
				xp = x; yp = y-60;
				break;
			case 'h':
				xp = x+114; yp = y-3;
				break;
			case 'i':
				xp = x+114; yp = y+117;
				break;
			case 'j':
				xp = x; yp = y+180;
				break;
			case 'k':
				xp = x-114; yp = y+117;
				break;
			case 'l':
				xp = x-114; yp = y+3;
				break;
			default:
				break;
		}
		if(xp != -1)
		{
			context.arc(xp, yp, 10, 0, 2*Math.PI, 1);
			context.fill();
			context.stroke();
		}
	}
}

// 描く対象により呼ぶ関数を振り分ける
function DrawObject(x, y, p, s)
{
	if(s == 'b')
	{
		DrawBond(x, y, p);
	}
	else
	{
		DrawAtom(x, y, p, s);
	}
}

// 2バイトで1命令となるコマンド解析部
//  1バイト目が位置 (a-fが環の1-6位, g-lが環についた置換基)
//  2バイト目が内容 (CONが原子, bは結合)
function DrawCompound(command)
{
	var p = 0;
	Initialize();
	while(p < command.length)
	{
		if(command[p] == ' ')
		{
			p++;
		}
		else
		{
			DrawObject(250, 190, command[p], command[p+1]);
			p += 2;
		}
	}
	DrawCyclohexane(250, 190);
}

//-->
</script>


Copyright © MASUDA Yoshihiro (contact@masudayoshihiro.jp).