第9回(応用編-1)

図形・グラフを書く


 前回の、第8回までの内容で、JavaScript を使って計算などするプログラムを作るための、基礎的なことは大体済んだと思います。そこで今回からは、応用編ということにして、前回までの例には出てこなかった応用例を書いていこうと思います。

図形を書いてみる

 HTML のタグで記述しても、JavaScript を使っても、画像を表示することはできます。しかし、元の画像ファイルから大きさなどは変更できますが、自由な形の図形を書くことができるわけではありません。JavaScript で、計算式を使うと、元の画像ファイルとは違った形の図形もある程度は書くことができます。
 元になる図形は、幅・高さともに1ピクセルで、透明:img001.gif、白:img002.gif、赤:img003.gif、青:img004.gif の4ファイルを用意しました。

 ● 四角形
 単純な四角形は、元の図形の幅と高さを指定するだけですので、フォームで四角形の色と大きさを指定し、表示することにしました。ここをクリックしてください。
<HTML>
<HEAD>
<SCRIPT TYPE="text/javascript">
    function disp()
    {
        var datA,datB,datC;
        with(document.form01)
        {
            datA=eval(txt01.value);
            datB=eval(txt02.value);
            if(r01[0].checked)
                datC="<IMG SRC='img003.gif' WIDTH='";
            else
                datC="<IMG SRC='img004.gif' WIDTH='";
        }
        document.write(datC+datA+"' HEIGHT='"+datB+"'>");  
        document.close();
    }
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME="form01">
■四角形の色<BR>
<INPUT TYPE="radio" NAME="r01" CHECKED>赤 
<INPUT TYPE="radio" NAME="r01">青<P>
■四角形の大きさ<BR>
幅:<INPUT TYPE="text" NAME="txt01"> 
高さ:<INPUT TYPE="text" NAME="txt02"><P><HR>
<INPUT TYPE="button" VALUE="表示" onClick="disp()"><P>
</FORM>
</BODY>
</HTML>
 ● 円形
 円形の場合は、元の図形の形状(幅と高さが1ピクセルでも四角形)と違いますので、表示するのは少し面倒です。ここでは、高さ1ピクセルで一行ずつ書いていくことにしました。ここをクリックしてください。
<HTML>
<HEAD>
<SCRIPT TYPE="text/javascript">
    function disp()
    {
        var rad,datA,datB,datC,y;
        with(document.form01)
        {
            rad=eval(txt01.value);
            datA=Math.pow(rad,2);
            if(r01[0].checked)
                datC="<IMG SRC='img003.gif' WIDTH='";
            else
                datC="<IMG SRC='img004.gif' WIDTH='";
        }
        for(y=-rad;y<=rad;y++)
        {
            datB=Math.floor(Math.sqrt(datA-Math.pow(y,2)));
            document.write("<IMG SRC='img001.gif' WIDTH='"+(rad-datB)+"' HEIGHT='1'>");  
            document.write(datC+datB*2+"' HEIGHT='1'><BR>");
        }
        document.close();
    }
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME="form01">
■円形の色<BR>
<INPUT TYPE="radio" NAME="r01" CHECKED>赤 
<INPUT TYPE="radio" NAME="r01">青<P>
■円形の半径(ピクセル)<BR>
半径:<INPUT TYPE="text" NAME="txt01"><P><HR>
<INPUT TYPE="button" VALUE="表示" onClick="disp()"><P>
</FORM>
</BODY>
</HTML>
 円の半径を rad とすると、式は x2+y2 = rad2 です。rad2datA に代入しておいてから、y-rad から rad の間で、x 座標を計算しています。x=√datA-y2 です。これを datB として、まず、rad-datB の長さで高さ1ピクセルの透明な横線を書き、次に datB×2 の長さで高さ1ピクセルの、指定した色の横線を書いてから改行しています。
 ここでは、一行ずつ書いていますが、1ピクセルずつ、x2+y2 の値と半径の二乗を比較して、小さければ(円の内側なら)色付の点を書き、大きければ(円の外側なら)透明の点を書く方法も考えられますし、この方が計算は簡単です。ところが、実際にこの方法で書いてみると、時間がかかり、半径が大きいと、ブラウザから処理が遅くなるが継続するか? というメッセージが表示されたりします。計算自体に時間がかかるわけはないのですが、document.write での書き出しには時間がかかり、上の方法の二乗の回数 document.write を実行することで遅くなるようです。
 ● 三角形
 二等辺三角形なら、円形より簡単です。高さと頂角を指定できるようにしてみました。ここをクリックしてください。
<HTML>
<HEAD>
<SCRIPT TYPE="text/javascript">
    function disp()
    {
        var datA,datB,datC,datD,y;
        with(document.form01)
        {
            datA=eval(txt01.value);
            datB=Math.tan((eval(txt02.value)/360)*Math.PI);
            if(r01[0].checked)
                datC="<IMG SRC='img003.gif' WIDTH='";
            else
                datC="<IMG SRC='img004.gif' WIDTH='";
        }
        datE=Math.floor(datA*datB);
        for(y=-0;y<=datA;y++)
        {
            datD=Math.floor(y*datB);
            document.write("<IMG SRC='img001.gif' WIDTH='"+(datE-datD)+"' HEIGHT='1'>");  
            document.write(datC+datD*2+"' HEIGHT='1'><BR>");
        }
        document.close();
    }
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME="form01">
■二等辺三角形を書く<P>
色:<INPUT TYPE="radio" NAME="r01" CHECKED>赤 
<INPUT TYPE="radio" NAME="r01">青<P>
高さ(ピクセル):<INPUT TYPE="text" NAME="txt01"> 
頂角:<INPUT TYPE="text" NAME="txt02" VALUE="60">°<P><HR>
<INPUT TYPE="button" VALUE="表示" onClick="disp()"><P>
</FORM>
</BODY>
</HTML>

 高さは datA に代入します。頂角の半分の角度のタンジェントから、高さに対する底辺の半分の長さの割合を求め、datB に代入します。y=0 の位置では、datA×datB の小数点以下を切り捨てて整数にした datE の幅の透明な横線を書き、色付の線の長さは 0 です。y の増加により、透明な横線の長さは、datB ずつ減少、色付の線の長さは datB×2 ずつ増加することにより、二等辺三角形にしています。

 二等辺三角形は、縦線を使って書くこともできます。ここをクリックしてください。縦線で書いていることがわかるように、色付の線と白い線を交互に書きました。

<HTML>
<HEAD>
<SCRIPT TYPE="text/javascript">
    function disp()
    {
        var datA,datB,datC,datD,datE,x;
        with(document.form01)
        {
            datA=eval(txt01.value);
            datB=Math.tan((eval(txt02.value)/360)*Math.PI);
            if(r01[0].checked)
                datC="<IMG SRC='img003.gif' WIDTH=1 HEIGHT='";
            else
                datC="<IMG SRC='img004.gif' WIDTH=1 HEIGHT='";
        }
        datE=Math.floor(datA*datB);
        for(x=0;x<datE;x++)
        {
            datD=Math.floor(x/datB);
            if(x%2==0)
                document.write(datC+datD+"'>");
            else
                document.write("<IMG SRC='img002.gif' WIDTH='1' HEIGHT='"+datD+"'>");  
        }
        for(x=datE;x>=0;x--)
        {
            datD=Math.floor(x/datB);
            if(x%2==0)
                document.write(datC+datD+"'>");
            else
                document.write("<IMG SRC='img002.gif' WIDTH='1' HEIGHT='"+datD+"'>");
        }
        document.close();
    }
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME="form01">
■二等辺三角形を書く-2<P>
色:<INPUT TYPE="radio" NAME="r01" CHECKED>赤 
<INPUT TYPE="radio" NAME="r01">青<P>
高さ(ピクセル):<INPUT TYPE="text" NAME="txt01"> 
頂角:<INPUT TYPE="text" NAME="txt02" VALUE="60">°<P><HR>
<INPUT TYPE="button" VALUE="表示" onClick="disp()"><P>
</FORM>
</BODY>
</HTML>
 底辺の長さの半分の datE を計算するところまでは同じです。まず、x0 から datE まで増加させていき、次に 0 まで減少させ、x を 高さに対する底辺の半分の長さの割合である datB で除した長さの縦線を書いています。この方法だと、透明な線は書く必要がありません。

グラフを書く

 実際には、前項のように計算結果により単純な形状の図形を書く、ということが必要になる場合は、ほとんどないと思います。計算をして、同時に必要になる図形は、普通はグラフということになります。
 ● 縦棒グラフ
 普通の縦棒グラフです。A~E の5項目の正の数値を入力してから、[グラフ表示] ボタンをクリックします。ここをクリックしてください。
<HTML>
<HEAD>
<SCRIPT TYPE="text/javascript">
    function disp()
    {
        var i,datA=0,datB;
        var Dat=new Array();
        for(i=0;i<=4;i++)
        {
            Dat[i]=eval(document.form01.elements[i].value);
            datA=Math.max(datA,Dat[i]);
        }
        document.write("<TABLE cellspacing='5'><TR valign='bottom' align='center'>");
        for(i=0;i<=4;i++)
        {
            datB=Math.floor((Dat[i]/datA)*300);
            document.write("<TD>"+Dat[i]+"<BR><IMG src='img003.gif' WIDTH='30' HEIGHT='"+datB+"'></TD>");
        }
        document.write("</TR><TR align='center'><TD>A</TD><TD>B</TD><TD>C</TD><TD>D</TD><TD>E</TD></TR></TABLE>");  
        document.close();
    }
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME="form01">
■縦棒グラフを書く<P>
 A:<INPUT TYPE="text" NAME="txt01"><BR>
 B:<INPUT TYPE="text" NAME="txt02"><BR>
 C:<INPUT TYPE="text" NAME="txt03"><BR>
 D:<INPUT TYPE="text" NAME="txt04"><BR>
 E:<INPUT TYPE="text" NAME="txt05"><HR>
<INPUT TYPE="button" VALUE="グラフ表示" onClick="disp()"><P>
</FORM>
</BODY>
</HTML>
 A~E の、最大値の棒の高さを 300ピクセルとして、他は最大値に対する、比率の高さにしています。縦軸の目盛りはないので、値を棒の上に表示しました。項目名と値の表示を、棒とそろえるためにテーブルを使用しています。
 ● 横棒グラフ
 横棒グラフも同じように書くことができます。ここをクリックしてください。
<HTML>
<HEAD>
<SCRIPT TYPE="text/javascript">
    function disp()
    {
        var i,datA=0,datB;
        var Dat=new Array();
        var Lab=new Array("A","B","C","D","E");
        for(i=0;i<=4;i++)
        {
            Dat[i]=eval(document.form01.elements[i].value);
            datA=Math.max(datA,Dat[i]);
        }
        datA=Math.ceil(datA*0.1)*10;
        document.write("<TABLE cellspacing='5'>");
        for(i=0;i<=4;i++)
        {
            datB=Math.floor((Dat[i]/datA)*300);
            document.write("<TR><TD>"+Lab[i]+"</TD><TD><IMG src='img003.gif' WIDTH='"+datB+"' HEIGHT='30'></TD></TR>");  
        }
        document.write("<TR><TD></TD><TD><IMG src='img004.gif' WIDTH='2' HEIGHT='6'><IMG src='img004.gif'
          WIDTH='148' HEIGHT='2' align='top'><IMG src='img004.gif' WIDTH='2' HEIGHT='6'><IMG src='img004.gif'
          WIDTH='148' HEIGHT='2' align='top'><IMG src='img004.gif' WIDTH='2' HEIGHT='6'></TD></TR>");
        document.write("<TR><TD></TD><TD>0<IMG src='img001.gif' WIDTH='140' HEIGHT='1'>"+datA/2+"<IMG src='img001.gif'
          WIDTH='140' HEIGHT='1'>"+datA+"</TD></TR>");
        document.write("</TABLE>");
        document.close();
    }
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME="form01">
■横棒グラフを書く<P>
 A:<INPUT TYPE="text" NAME="txt01"><BR>
 B:<INPUT TYPE="text" NAME="txt02"><BR>
 C:<INPUT TYPE="text" NAME="txt03"><BR>
 D:<INPUT TYPE="text" NAME="txt04"><BR>
 E:<INPUT TYPE="text" NAME="txt05"><HR>
<INPUT TYPE="button" VALUE="グラフ表示" onClick="disp()"><P>
</FORM>
</BODY>
</HTML>
 この例では、値をグラフに表示しないで、目盛りを表示しました。そのために、A~E の最大値の下一桁を切り上げた値の棒の長さを 300ピクセルとして、この値と、その半分の値を下の目盛りに表示しています。
 今回は、簡単なグラフを書いたところまでにします。