[Labyrinthe Noir]>[Top]>[こども工作教室]>

アナログ時計のソースと解説

テキストファイルの作成

テキストエディタで、アナログ時計用にテキストファイルを作成します。

書式はHTML5に、ファイル形式はUTF-8とします。
「名前を付けて保存」を開き、保存場所を選んだら、ファイル名は 「aclock.html」、ファイルの種類は「すべてのファイル」を選び、文字コードは「UTF-8」を選んで、保存します。

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>アナログ時計</title>
</head> 
<body>
<h3>アナログ時計</h3>
<hr>
</body>
</html>

時計用の画像を配置

まずは単純な配置を行います。
後でCSSを記述することで、配置に変化を与えます。

<div>タグを使って時計の配置場所にID名を付けます。これもCSSと対応させるためです。

<img>タグで5つの画像を並べます。これらには、ファイル名の他、幅や高さ、ID名とクラス名を与えます。ID名はそれぞれ別の名前を付けます。クラス名は1つのグループを表す名前ですから同じ名前です。
後でCSSを摘要すると上から順に重ねて表示します。

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>アナログ時計</title>
</head> 
<body>
<h3>アナログ時計</h3>
<hr>
<div id="clocks">
<img src="body.png" width="250" height="250" id="image_body" class="clock">
<img src="short.png" width="250" height="250" id="image_short" class="clock">
<img src="long.png" width="250" height="250" id="image_long" class="clock">
<img src="sec.png" width="250" height="250" id="image_sec" class="clock">
<img src="cover.png" width="250" height="250" id="image_cover" class="clock">
</div>
</body>
</html>

画像の説明

パーツ名 文字盤 短針 長針 秒針 カバー
画像
ファイル名 body.png short.png long.png sec.png cover.png
ID名 image_body image_short image_long image_sec image_cover

これらの画像はオリジナルで作って、個性的な時計を作りましょう。

上記のパーツを使う場合は、画像の上で右クリックをして「画像を保存」します。パーツの大きさは250×250で作ってあります。
オリジナルで作る場合は、保存形式をPNGにし、文字盤以外は背景を透明にします。もし、PNGで透過画像が作れない場合は、GIFでも透過画像ができます。
これら5つの画像を同じ大きさで作っておけば、針の部分は中心で回転し綺麗に重なります。

文字盤は一番下に置かれる画像です。透明部分はなくてもかまいません。時刻を示す位置を正確に並べないと時計が狂ってしまいます。
短針は時間を表す針で太く短く作ります。
長針は最も長く作りますが、文字盤の外枠に重ならないように作ります。
秒針は一番細く作ります。
カバーは針の中心のピン留めやガラスケースを表現します。

時刻のデジタル表示

確認用に時刻のデジタル表示を作っておきます。

<div>タグにID名clock_timeと名付けておきます。

この時刻表示は、時計が正しく動いていることを確認するためのものです。
完成後は外してもかまいません。

【この時点の aclock.html を別枠で表示】

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>アナログ時計</title>
</head> 
<body>
<h3>アナログ時計</h3>
<hr>
<div id="clocks">
<img src="body.png" width="250" height="250" id="image_body" class="clock">
<img src="short.png" width="250" height="250" id="image_short" class="clock">
<img src="long.png" width="250" height="250" id="image_long" class="clock">
<img src="sec.png" width="250" height="250" id="image_sec" class="clock">
<img src="cover.png" width="250" height="250" id="image_cover" class="clock">
</div>
<div id="clock_time">--:--:--</div>
</body>
</html>

CSSの記述

<head>タグの中に<style>タグを置いて、CSSを記述します。

#clocksはID名を表しています。<div>タグの中にID名clocksがありますので、これに対応します。
.clockはクラス名を表しています。<img>タグで共通して使われているクラス名clockと対応します。
CSSの記述パターンはHTMLともJavaScriptとも全く違っています。

#clocksでは、<div>を一つのブロック(箱型)にして、幅(width)と高さ(height)を画像と合わせています。

.clockでは、5つの画像に対して絶対位置の指定をしています。位置を指定するにはtopやleftというプロパティを与えますが、ここでは何もしていません。これで画像が重なっています。
これは<img>タグの外に<div>タグで囲っているため、この中で上と左に寄せられています。

【この時点の aclock.html を別枠で表示】

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>アナログ時計</title>
<style type="text/css">
#clocks {
	display: block;
	width: 250px;
	height: 250px;
}
.clock {
	position: absolute;
}
</style>
</head>

(省略)

時計の機能を考える

スクリプトを書く前に、時計として動かすにはどんなことが必要か考えてみましょう。

1.1秒ごとに秒針を動かす。長針(分針)は1分、短針(時針)は1時間ごとに動く。

2.針の動きは画像を回転させる。

大まかにはこの2つのことが重要な機能です。しかも、この2つは同時に実行されますので、1秒ごとに時刻を計算して画像を回転させます。

スクリプトの準備

<body>タグの中に<script>タグを準備しましょう。
コンテンツよりも下に配置します。

(省略)
<div id="clock_time">--:--:--</div> <script type="text/javascript"> </script> </body> </html>

タイマーを起動するスクリプト

タイマーを起動するためsetInterval()を使います。
しかし、その前に、画像を読み込んでから処理を開始したいので、全ファイルの読み込み完了してからスクリプトが実行されるようにします。

window.onloadを指定することで、その中身はロードが終わったら実行という意味になります。

setInterval()の内容は、moveTimer()を1000ミリ秒(1秒)ごとに実行しなさいという意味です。このとき、変数timerIDにはタイマーの起動番号が入ります。これはタイマーを停止させるときに使います。(今回は停止処置はありません)

(省略)
<script type="text/javascript"> window.onload = function() { //タイマー起動 timerID = setInterval("moveTimer()",1000); }; </script>

(省略)

時計を動かすスクリプト

まずは、準備段階としてユーザー関数moveTimerを定義します。

ローカル変数として7つの変数を宣言しておきます。

変数dateは日付を、変数Hou、Min、Secは時刻を、変数hDeg、mDeg、sDegは角度を表すために使います。

(省略)
<script type="text/javascript"> window.onload = function() { //タイマー起動 timerID = setInterval("moveTimer()",1000); }; //時計を動かす function moveTimer() { var date,Hou,Min,Sec,hDeg,mDeg,sDeg; } </script>

(省略)

日付の取得

変数dateに現在の日時を取得します。

その次に、変数Houには時間、変数Minには分、変数Secには秒の値を個別に取得します。

そして、最後にID名clock_timeで指定した<div>タグの中に、それらの変数を使って時刻を出力します。

この段階で時計としてデジタル表示が機能していることを確認し、そこまでのスクリプトが正常に動いていることの確認とします。

【この時点の aclock.html を別枠で表示】

(省略)
//時計を動かす function moveTimer() { var date,Hou,Min,Sec,hDeg,mDeg,sDeg; //日付 date = new Date(); //時間取得 Hou = date.getHours(); Min = date.getMinutes(); Sec = date.getSeconds(); //時刻表示 document.getElementById("clock_time").innerHTML = Hou + ":" + Min + ":" + Sec;
}

(省略)

デジタル表示の調整

デジタル表示を見ていると桁数が1桁のときと2桁のときがあるのが判ります。
そして、桁数が変わると数字の位置がずれて、桁が揃っていません。

そこで、桁数を2桁に揃える処理を出力の前に行います。
時刻を取得したそれぞれの変数に対し、if文で10より小さい場合に、「0」の文字を付け加えて桁を揃えます。

非常に細かいことですが、時計のアプリを作るときには必要なことです。

【この時点の aclock.html を別枠で表示】

(省略)
//時計を動かす function moveTimer() { var date,Hou,Min,Sec,hDeg,mDeg,sDeg; //日付 date = new Date(); //時間取得 Hou = date.getHours(); Min = date.getMinutes(); Sec = date.getSeconds(); //デジタル表示 if (Hou < 10) Hou = "0" + Hou; if (Min < 10) Min = "0" + Min; if (Sec < 10) Sec = "0" + Sec; //時刻表示 document.getElementById("clock_time").innerHTML = Hou + ":" + Min + ":" + Sec; }
(省略)

角度の計算

時間を角度に直す計算式を作ります。

分と秒はどちらも60刻みなので同じ計算式になります。
時計の一周が360度ですからこれを60で割ると1刻みですので、これと時間をかけ算します。

時間は12刻みですから360を12で割って1刻み。そこに時間を掛けるのですが、時間表示は24時間制なので調節が必要です。
0~11はそのまま、12~23は12を引いた数が必要です。そこで、時間を12で割った余り(Hou % 12)を求めます。「%」は余りを求める演算記号です。
そうすると次のような対応表ができます。数値の試算にはExcelなど利用すると分かりやすいです。

変数Hou 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Hou % 12 0 1 2 3 4 5 6 7 8 9 10 11 0 1 2 3 4 5 6 7 8 9 10 11

この表によって時間をそのまま掛けるのではなく、余りを求めて掛け算すれば良いことが判ります。

(省略)
//時計を動かす function moveTimer() { var date,Hou,Min,Sec,hDeg,mDeg,sDeg; //日付 date = new Date(); //時間取得 Hou = date.getHours(); Min = date.getMinutes(); Sec = date.getSeconds(); //針の角度取得 hDeg = (Hou % 12) * (360 / 12); mDeg = Min * (360 / 60); sDeg = Sec * (360 / 60); //デジタル表示 if (Hou < 10) Hou = "0" + Hou; if (Min < 10) Min = "0" + Min; if (Sec < 10) Sec = "0" + Sec; //時刻表示 document.getElementById("clock_time").innerHTML = Hou + ":" + Min + ":" + Sec; }
(省略)

針の回転

各針の角度が求められたので、それぞれ対応する画像に角度を付けます。

今回はHTML5の書式に従いますが、ブラウザによって正式な対応が済んでいません。そのため、ブラウザにあった識別子が必要になりますので、1つの画像に対して4つのプロパティを用意しています。
transformが基本のプロパティで、Moz~がFirefox用、Webkit~がSafari用、ms~がIE用になります。将来は基本の記述に統一されることになっています。

CSS3のプロパティrotate()で角度を指定します。数値の後に「deg」という単位も必要です。
これを各針ごとに画像のID名を指定して実行します。

【この時点の aclock.html を別枠で表示】

(省略)
//時計を動かす function moveTimer() { var date,Hou,Min,Sec,hDeg,mDeg,sDeg; //日付 date = new Date(); //時間取得 Hou = date.getHours(); Min = date.getMinutes(); Sec = date.getSeconds(); //針の角度取得 hDeg = (Hou % 12) * (360 / 12); mDeg = Min * (360 / 60); sDeg = Sec * (360 / 60); //デジタル表示 if (Hou < 10) Hou = "0" + Hou; if (Min < 10) Min = "0" + Min; if (Sec < 10) Sec = "0" + Sec; //時刻表示 document.getElementById("clock_time").innerHTML = Hou + ":" + Min + ":" + Sec; //短針の表示 document.getElementById("image_short").style.transform = "rotate(" + hDeg + "deg)"; document.getElementById("image_short").style.MozTransform = "rotate(" + hDeg + "deg)"; document.getElementById("image_short").style.WebkitTransform = "rotate(" + hDeg + "deg)"; document.getElementById("image_short").style.msTransform = "rotate(" + hDeg + "deg)"; //長針の表示 document.getElementById("image_long").style.transform = "rotate(" + mDeg + "deg)"; document.getElementById("image_long").style.MozTransform = "rotate(" + mDeg + "deg)"; document.getElementById("image_long").style.WebkitTransform = "rotate(" + mDeg + "deg)"; document.getElementById("image_long").style.msTransform = "rotate(" + mDeg + "deg)"; //秒針の表示 document.getElementById("image_sec").style.transform = "rotate(" + sDeg + "deg)"; document.getElementById("image_sec").style.MozTransform = "rotate(" + sDeg + "deg)"; document.getElementById("image_sec").style.WebkitTransform = "rotate(" + sDeg + "deg)"; document.getElementById("image_sec").style.msTransform = "rotate(" + sDeg + "deg)"; } (省略)

角度の調整

このままで時計を動かすと動きに違和感が残ります。長針は1時間ごとに、短針は1分ごとに動くからです。

当たり前のようですが、実はそうではありません。アナログ時計の場合、短針はずっと時間の位置に止まってはいません。例えば、1時30分の場合、短針は1と2の中間にあるはずです。
そのためこのままでは、59分から0分になった途端に短針が大きく動くことになってしまいます。
また、長針も同じことが起こります。ただし、1分ごとに動く時計もあるので、好みで選びましょう。

まず、短針ですが、分数の大きさ(変数Min)に応じて、1時間の間(360/12)を移動します。1時間の角度を60で割ってそのうちの分数(分数/60)進むことになります。
式では「+=」を使って、変数hDegにその調整分を加算しています。

次に長針です。こちらも考え方は同じです。1つの目盛りは360/60という角度なので、その内の秒数/60が調整分の角度となります。これを変数mDegに加算します。

(省略)
//時計を動かす function moveTimer() { var date,Hou,Min,Sec,hDeg,mDeg,sDeg; //日付 date = new Date(); //時間取得 Hou = date.getHours(); Min = date.getMinutes(); Sec = date.getSeconds(); //針の角度取得 hDeg = (Hou % 12) * (360 / 12); mDeg = Min * (360 / 60); sDeg = Sec * (360 / 60); //角度調整
hDeg += (Min / 60) * (360 / 12);
mDeg += (Sec / 60) * (360 / 60);

//デジタル表示 if (Hou < 10) Hou = "0" + Hou; if (Min < 10) Min = "0" + Min; if (Sec < 10) Sec = "0" + Sec; //時刻表示 document.getElementById("clock_time").innerHTML = Hou + ":" + Min + ":" + Sec;

(省略)

これでアナログ時計の完成となります。

【この時点の aclock.html を別枠で表示】


戻る