第 13 回 HTMLのプログラミング

本日の内容


このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。

13-1. HTMLのプログラミング

bekijo.js

暗号などで使用する、 xy (modn) (xy乗 を nで割った余り) を計算するべき乗電卓を紹介します。

bekijo.html


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>power caluculator</title>
<script type="text/javascript" src="calc.js"></script>
<style>
input { width:5em;}
</style>
</head>
<body>
<h1>べき乗電卓</h1>
<form name="calcform">
<p>
<input type="number" name="a" value="0"><sup>
<input type="number" name="b" value="1"></sup>
 mod
<input type="number" name="n" value="1">
<input type="button" value="&equiv;(計算)" onClick="calc();">
<!--<span id="result">0</span>-->
<input type="number" name="result" value="0">
</p>
<p>
<input type="reset" >
</p>
</form>
</body>
</html>

calc.js


function power(a,b,n){
    if(b==0) return 1;
    var result = power(a,parseInt(b/2),n);
    return (result*result*(b%2==0?1:a) )% n;
}
function calc(){
    var a = parseInt(document.calcform.a.value);
    var b = parseInt(document.calcform.b.value);
    var n= parseInt(document.calcform.n.value);
    document.calcform.result.value = power(a,b,n);
}

使い方

出力欄以外に数値を入れて、計算ボタンを押すと計算結果が出ます。

例えばRSA鍵 x7 (mod143) , z103 (mod143) , に対して、適当な x(11,13 とは互いに素)な数に対して、 7 乗 したあと、 103 乗して、元の x に戻ることを確認する。

説明

バイナリー法というアルゴリズムを用いて、高速で桁溢れを起こさないアル ゴリズムを使っています。 xy z (modn) であるとき、 x 2 y z 2 (modn) x 2 y + 1 z 2 x (modn) が成り立ちます。 そこで、帰納的にべき乗を定義すると、y の二進展開に対応した処理が行われます。

DOM のアクセスは、 document のあとに、 form の名前、input の名前をそ れぞれピリオドでつなぐとアクセスできます。 そこで、結果を表示するところも名前付きの input にしておけば、表示が 楽になります。

  1. form , input のname 属性
  2. onClick 属性

kamishibai.js

Webテキストで、ボタンで画像ファイルを切り替えて出力する Kamishibai.js を紹介します。 前準備として、画像ファイル群を「共通名+通し番号+拡張子」というファイル 名で用意します。(samp1.jpg, samp2.jpg など)

kamishibai.js


function genArray(name,suf,fromnum,tonum){
    var result =[];
    for( var i = fromnum; i<=tonum; i++){
	result.push(name+i+suf);
    }
    return result;
}
var Kamishibai = function(id,files){
    this.name=id;
    this.elem=null;
    this.src="src";
    this.index=0;
    this.files = files;
    this.setSrc = function(){
	this.init();
	var prev = this.elem.getAttribute(this.src);
	if(prev != this.files[this.index]){
	    this.elem.setAttribute(this.src,this.files[this.index]);
	}
	return false;
    };
    this.resetpage = function(){
	this.index=0;
	return this.setSrc();
    };
    this.init = function(){
	if(this.elem==null){
	    this.elem=document.getElementById(this.name);
	    this.src = this.elem.localName=="object"?"data":"src";
	}
    };
    this.forward = function(){
	this.index=this.index+1<this.files.length ? this.index+1:this.files.length-1;
	return this.setSrc();
    };
    this.backword = function(){
	this.index=this.index>0? this.index-1:0;
	return this.setSrc();
    };
    this.toend = function(){
	this.index=this.files.length-1;
	return this.setSrc();
    }
    this.redraw = function(){
	this.init();
	var svg = this.elem.contentDocument;
	svg.forceRedraw();
    }
};

使い方

上記の kamishibaji.js は head 内の script で読み込んでおきます。 そして、HTML 内で図を表示したい場所に、定形の HTML を置きます。

一つの HTML で複数のこのkamishibai の機能を使うため、一つ一つオブジェ クトを生成します。 予め定めておく名前として次を用意します()。

機能名前例
オブジェクト名objname1
img タグのidobjid1
画像ファイル名の接頭語gazou
画像ファイル名の拡張子.png
画像ファイル名の連番の開始番号0
画像ファイル名の連番の終了番号9
画像ファイルの高さ100

<script>
var objname1 = new Kamishibai("objid1",genArray("gazou",".png",0,9));
</script>
<div>
<table>
<tr><td>
<img src="gazou0.png" height="100" id="objid1">
</td>
</tr>
<tr>
<td>
<button onclick="objname1.resetpage()">|&lt;</button>
<button onclick="objname1.backword()">&lt;</button>
<button onclick="objname1.forward()">&gt;</button>
<button onclick="objname1.toend()">&gt;|</button>
</td>
</tr>
</table>
</div>

例13-1

平衡木

平衡木

説明

何年も前に作ったものなので、現在の技術だと template などを使えば、もっ とシンプルにできるかも知れません。 ただ、表示させるところはなるべくプログラム生成させず、可読性とカスタ マイズを優先しました。

オブジェクトを作ることで、各ボタンを押したときに、特定の画像ファイルのみを差し替えることができる。

template


<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>template テスト</title>
<style>
    th,td {border: 1px solid black;}
</style>
</head>
<body>
<h1>テンプレートテスト</h1>
<table>
    <thead>
        <tr><th>商品番号</th><th>商品名</th><th>単価</th></tr>
    </thead>
    <tbody>
        <template id="shohin">
            <tr><td></td><td></td><td></td></tr>
        </template>
    </tbody>
</table>
<script>
    var data =[
        {"商品番号": 999001, "商品名": "リンゴ", "単価": 200},
        {"商品番号": 999002, "商品名": "みかん", "単価": 100},
        {"商品番号": 999003, "商品名": "もも", "単価": 500}
];
</script>
<script>
    var temp = document.querySelector("#shohin");
    for(var i=0; i< data.length; i++){
        var d = data[i];
        var c = temp.content.cloneNode(true);
        var t=c.querySelectorAll("td");
        t[0].textContent = d.商品番号;
        t[1].textContent = d.商品名;
        t[2].textContent = d.単価;
        temp.parentNode.appendChild(c);
    }
</script>
</body>
</html>

Interval


<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>時計</title>
</head>
<body>
<p id="tokei"></p>
<script>
setInterval(function(){
    var p=document.getElementById("tokei");
p.textContent = new Date();
},500);
</script>
</body>
</html>

Canvas


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>cambus test</title>
</head>
<body>
    <p>aaa</p>
    <canvas id="imgcanvas" width="600" height="500">
        <p>ccc</p>
    </canvas>
    <p>bbb</p>
    <script>
        var imgcanvas=document.getElementById("imgcanvas");
        if(imgcanvas.getContext) {
            var ctx=imgcanvas.getContext('2d');
            ctx.fillStyle="rgba(255,0,0,1)";
            ctx.strokeStyle="#000000";
            ctx.fillRect(0, 0, 100, 100);
            ctx.strokeRect(0, 0, 100, 100);
            ctx.fillRect(50, 50, 100, 200);
            ctx.strokeRect(80, 130, 200, 100);

            ctx.beginPath();
            ctx.moveTo(0,100);
            ctx.lineTo(200,200);
            ctx.stroke();

            ctx.font = "16pt 'Arial'";
            ctx.fillText("abc",250,50);
            ctx.strokeText("xyz",250,150);
        }
    </script>
</body>
</html>

13-2. 演習

演習13-2

与えたデータの配列に関して、折れ線グラフを書くプログラムを作れ


<script>
    var data=[3,4,2,6,10,3];
</script>

演習13-3

アナログの針を表示する時計を作成せよ

13-3. 演習の解答

演習13-2

与えたデータの配列に関して、折れ線グラフを書くプログラムを作れ


<script>
    var data=[3,4,2,6,10,3];
</script>

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>折れ線グラフ</title>
</head>
<body>
    <canvas id="grahu" width="600" height="400"></canvas>
    <script>
        var data = [3, 4, 2, 6, 10, 3];
    </script>
    <script>
        var grahu = document.getElementById("grahu");
        if (grahu.getContext) {
            var ctx = grahu.getContext('2d');
            ctx.fillStyle = "rgba(255,0,0,1)";
            ctx.strokeStyle = "#000000";
            ctx.beginPath();
            ctx.moveTo(0, 100);
            for (var i = 0; i < data.length; i++) {
                ctx.lineTo(i * 100+100, 200 - data[i] * 10);
            }
            ctx.stroke();
        }
    </script>
</body>
</html>

演習13-3

アナログの針を表示する時計を作成せよ


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>時計</title>
</head>
<body>
    <p id="debug"></p>
    <canvas id="tokei" width="600" height="400"></canvas>
    <script>
        function plothari(ctx, deg, radius) {
            deg -= Math.PI / 2;
            ctx.fillStyle = "rgba(255,0,0,1)";
            ctx.strokeStyle = "#000000";
            ctx.beginPath();
            ctx.moveTo(300, 200);
            ctx.lineTo(Math.cos(deg) * radius + 300,
                Math.sin(deg) * radius + 200);
            ctx.stroke();
        }
        var tokei = document.getElementById("tokei");
        var debug = document.getElementById("debug");
        debug.textContent = "aaa" + tokei.getContext;
        if (tokei.getContext) {
            var ctx = tokei.getContext('2d');
            function tick() {
                var date = new Date();
                debug.textContent = "" + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
                ctx.clearRect(0, 0, 600, 400);
                plothari(ctx, (date.getHours() % 12) * Math.PI / 6, 100);
                plothari(ctx, date.getMinutes() * Math.PI / 30, 150);
                plothari(ctx, date.getSeconds() * Math.PI / 30, 200);
            }
            setInterval(tick, 500);
        }
    </script>
</body>
</html>

13-4. 参考文献

  1. Shelley Powers (著), 株式会社クイープ (翻訳)「JavaScriptクックブック」 オライリージャパン (2011/4/23)
  2. 加藤善規 (著), できるシリーズ編集部 (著)「できるポケット Web制作必携 HTML&CSS全事典 改訂版 HTML Living Standard & CSS3/4対応」インプレス; 改訂版 (2020/2/14)

坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科