どうも!LSSです!!
で、即興でアナログ時計を作ってみました。
画面を構成する、CSS部分についての解説はしていましたが、今回は肝心の「JavaScript」部分についての解説記事となります。
コード(script部分のみ)
<script>
tokeitm=setInterval(function(){
tokein=((Date.now()-(new Date()).getTimezoneOffset()*60000)%86400000)/1000;
tokeih.style.transform='rotate('+(((tokein%43200)/43200)*360-90)+'deg)';
tokeim.style.transform='rotate('+(((tokein%3600)/3600)*360-90)+'deg)';
tokeis.style.transform='rotate('+(((tokein%60)/60)*360-90)+'deg)';
},1000);
</script>
※HTML部分に、3時方向を向いた3本の針(IDはそれぞれ「tokeih」「tokeim」「tokeis」)があり、その針の回転角度を制御するスクリプトとなります。
コード解説(JavaScript部分)
やたらと ( ) が多くて、ややこしそうなコードになっていますねw
順にひも解いていきます。
setInterval
<script>
tokeitm=setInterval(function(){
tokein=((Date.now()-(new Date()).getTimezoneOffset()*60000)%86400000)/1000;
tokeih.style.transform='rotate('+(((tokein%43200)/43200)*360-90)+'deg)';
tokeim.style.transform='rotate('+(((tokein%3600)/3600)*360-90)+'deg)';
tokeis.style.transform='rotate('+(((tokein%60)/60)*360-90)+'deg)';
},1000);
</script>
今回のスクリプトは、1つの「setInterval」が全文を囲んでいます。
setIntervalは「一定時間ごとに、指定した関数を実行する」もので、
タイマーオブジェクト=setInterval(呼び出される関数,呼び出す間隔);
という書式で記述します。
呼び出す間隔の部分はミリ秒(1/1000秒)で指定します。
例えば、
a=setInterval('test()',100);
と書くと、別途用意した「test()」という関数を100ミリ秒(つまり0.1秒)毎に呼び出す事になります。
今回の場合は、別途関数を用意する事はせず、関数名を入れるところに、
function(){中略}
と、中略部分が数行に渡るコードを入れました。
この書き方だと、関数は関数名を持たず、即席で実行される内容を書く事ができます。
(関数名を持たない、という事は、他から呼び出して利用する事ができない、という事でもあります。今回の例ではその必要がないため、この書き方を採用しました。)
そして最後に、呼び出す間隔を「1000」としているので「1000ミリ秒(つまり1秒)」ごとに、中身が実行される事になります^^
時刻を秒で取得
さて、その呼び出される関数の内容は4行で書いていますが、まずその1行目から。
tokein=((Date.now()-(new Date()).getTimezoneOffset()*60000)%86400000)/1000;
の部分ですね。
ここでは、変数「tokein」に「日付が今日になってからの経過秒数」を代入しようとしています。
例えば、0時を回った直後、「0時0分3秒」なら「3」が入るようにしたいわけです。
( ) がたくさんありますが、わかりやすいよう色分け・改行すると、次のようになります。
tokein=
(
(Date.now()-(new Date()).getTimezoneOffset()*60000)
%86400000
)/1000;
Date.now()
「Date.now()」は「1970年1月1日 0時0分0秒からの経過ミリ秒」を数値で取り出す事ができます。
例えば、
<script>
document.write(Date.now());
</script>
というコードを実行すると
…という、凄い桁数の数値になりますw(約50年前からのミリ秒なので、さもありなん)
時刻を数値として取り扱えるので、かなり使い勝手がいいですね^^
そして、1日をミリ秒で言うと「86400000」ミリ秒(60*60*24*1000)となるので、
Date.now()%86400000
(%は余りを算出する演算子)は「今日になってからの経過ミリ秒」となります。
ところが…ここに落とし穴。
Date.now()で取り出せる「1970年1月1日 0時0分0秒からの経過ミリ秒」というのは、実は「国際標準時」での計算結果となります。
「国際標準時」=グリニッジ天文台(inイギリス)での時刻、ですね。
そして、ご存知の通り、地球には「時差」というものがあります。
日本では兵庫県明石市の子午線において、太陽が真上に来る時刻を正午とする時刻が採用されていますが、これはグリニッジを中心とした国際標準時と「9時間の時間差」があります。
というわけで、日本、もしくは他の国で、それぞれ使用されている「時刻」にあわせるためには「時差」を考慮する必要が出てきます。
getTimezoneOffset()
JavaScriptで「時差」を取得するのは、
日付オブジェクト.getTimezoneOffset()
という関数によって「分」単位で取得できます。
「日付オブジェクト」を作成する必要がでてきますが、今回はカンタンに、
(new Date()).getTimezoneOffset()
と、即席で日付オブジェクトを利用する事にしました。
…で、単位が「分」なもので、Date.now()の単位「ミリ秒」にあわせるべく、「60000」を掛けてから引き算したものが、
Date.now()-(new Date()).getTimezoneOffset()*60000
という式になります^^
そして、先ほどと同様に、
(Date.now()-(new Date()).getTimezoneOffset()*60000)%86400000
とする事で「時差を考慮した、今日になってからの経過ミリ秒」にしたもの
tokein=((Date.now()-(new Date()).getTimezoneOffset()*60000)%86400000)/1000;
1000で割って「秒」としたものを、変数「tokein」に代入したんですね^^
注:ただし、この式では「5.457秒」のように小数点以下も含んだ秒数となります。
小数点以下を切り捨てるために、
tokein=Math.float(((Date.now()-(new Date()).getTimezoneOffset()*60000)%86400000)/1000);
と後から修正しました^^;;;
…一行目からだいぶ長くなっちゃいました^^;
3本の針の角度を決めるのに必要な「今日になってからの秒数」が取得できたので、あとはそれを元に針の角度をそれぞれ指定していく事になります。
時針の角度計算
tokeih.style.transform='rotate('+(((tokein%43200)/43200)*360-90)+'deg)';
↑この部分ですね。
JavaScriptで「tokeih.style.transform=〇〇」と書くのは、CSSで「#tokeih{transform:〇〇;}」と書くのと同じ事を意味します。
ここで「43200」という数値を使っていますが、これは「12時間を秒単位にしたもの(12*60*60)」です。
時計の時針は12時間で一周(360度)するので、まず12時間で割った余りを
tokein%43200
で算出しています。
…次にそれをまた「43200」で割るのが、
(tokein%43200)/43200
です。
こうする事で「12時間ごとに区切った場合の、現在の区切り範囲内における現在時刻の比率」が取得できる事になります。
(この数値は0以上1未満の範囲に必ず収まります。)
例えば、「日付が変わってから18時間経過(=18時)」だと、12で割った余り=6時間で、それを12で割ると「0.5」という比率って事になるわけです。
次にこれに、一周=360度なので360を掛けます。
((tokein%43200)/43200)*360
18時=0.5の例でいうと、0.5*360で180度、という事になります。
時計の真上(0時)から時計回りに180度回転した位置である、「6時」の位置に来るようにしたかったんですね^^
ただ、今回の「アナログ時計」では、最初の配置が「3時方向」となっているため、ここでもまた「90度」戻してあげないといけません。
((tokein%43200)/43200)*360-90
として90を引いた結果(18時だと90という数値になります)を、元の「3時方向」の角度から回転させてあげたいので、
tokeih.style.transform='rotate('+(((tokein%43200)/43200)*360-90)+'deg)';
としたところで完成です!
18時に この計算が実行されると、
tokeih.style.transform='rotate(90deg)';
と書くのと同じ事になり、これはCSSで「#tokeih{transform:90deg;}」と指定するのと同じ結果になるため、「3時方向から時計回りに90度回転した位置」でめでたく「6時」の角度に時針が向くことになるんですね^^
分針、秒針も同様に。
あとの2行、
tokeim.style.transform='rotate('+(((tokein%3600)/3600)*360-90)+'deg)';
tokeis.style.transform='rotate('+(((tokein%60)/60)*360-90)+'deg)';
も、まったく同様の理屈で、区切りの単位を
「tokeim(分針)は一周3600秒、tokeis(秒針)は一周60秒」
として、「比率を算出→360を掛ける→90を引く」事で、それぞれの針の角度をJavaScriptから指定しています。
って、かなり長くなってしまいましたが…
上記のような内容を「1秒ごとに毎回呼び出して実行する」事で、3本の針の角度が設定されて、アナログ時計の動作が実現しています^^
あとがき
わずか数行のコードの解説に、かなりの文量を使ってしまいました^^;
あれですよ。
これはJavaScriptが難しいからじゃなくて、自分の説明が下手だからであって、
「LSSの説明文を嫌いになっても、JavaScriptを嫌いにならないでください!」
って言いたくなるところですwww
ってなとこで、今回はこのへんで!
次回もまた、よろしくお願いします^^