JavaScript を使った時計、というものがあります。グラフィック表示はめんどくさいですが、
テキスト表示であれば文字を置き換えていけばいいので簡単です。
おおざっぱに言えば
- ブラウザ(を動作させている環境)からDateクラス経由で時・分・秒を取得して表示する関数を作成する
- その関数の最後で、1秒後(1000ミリ秒後)にまたその関数自体を呼び出すようにする(setTimeout関数を使用する)。
ということをやればいいんです。
いいんです、というか、検索すればわかりますがほとんどのサイトではそのようなサンプルプログラムを紹介しています。
ところでその時計、あってますか?(ブラウザの動作環境のハードウェアの時計があっていることを前提に)
JavaScriptのDateクラスには、getMillisecondsという名前の関数があります。よそさまのサンプルプログラムに、この関数の出力結果も追加してみてください。あるいは単体で実行するだけでも分かります。
var d = new Date(); document.write( d.getMilliseconds() );
何回も実行すればわかりますが、「110」だとか「465」だとか「995」だとか、たいてい2~3桁の数値が表示されると思います。
この数値は何を表すのか?それは new Date(); の瞬間の、その環境の時計の、1秒未満の値にほかなりません。500 あればつまり0.5秒です。
この値を無視して時・分・秒を表示しているサンプルプログラムのいかに多いことか!嘆かわしい。ランダムで最大1秒程度ずれてしまうデジタル時計なんてかっこわるい!と思いませんか?思いませんか。そう言わずに続きを読んでください。
さて、よそさまのサンプルコードの最後の部分にはたいてい次のように書かれています。
function tokei() { // 時計を表示 setTimeout( "tokei()", 1000 ); // 1秒後にもう一回 }
ここを、次からぴったり、その環境の時計の1秒未満の端数がゼロになるように呼び出すよう、修正してみましょう。
function tokei() { var d = new Date(); // 時計を表示 setTimeout( "tokei()", 1000 - d.getMilliseconds() ); }
よし。こうすれば、例えばある時に getMilliseconds() の値が 500、0.5秒ずれているとわかったら、次の時計を表示するタイミングを、1000-500=0.5秒後になるように調整できるはずです。そして、ずれがなくなっているかどうかは、常にgetMiilisecondの値を表示すればわかるはずです。うまくいけばこれが常に ゼロ になるはずです。
と思ってサンプルコードを作ってみたわけです。→ jstimer (いろんなブラウザで開いてみてください)
試験環境
- CPU : Intel Core i7 950
- OS : Windows 7 Professional x64 with SP1
- メモリ : 12GB
- ブラウザ : Firefox 10.0.2, Internet Explorer 9, Google Chrome 17.0.963.78 m
無負荷の状態でこれ。Google Chrome ではたいてい 0 になりましたが、Firefox では 1、IE では常時数ミリ秒ずれています。つまるところ、そのへんでよく見かけるJavaScript時計は、IEで開くと、ときどき無様に1秒ワープして2秒先に進むわけです。Google Chromeの場合はそのようなことには滅多にならない、ということもわかります(起動時のずれは放置されますけどね)。
さらにシステムに負荷をかけるため、このままためしに Windows エクスペリエンス インデックスの再計算を実行してみます。すると…
やはりIEはいまいちな値を出していますね。今回の環境では、Google Chrome がいちばん精度が高く、Internet Explorer が精度が悪く、FirefoxはかなりいいがGoogle Chromeには及ばない、という結果が得られました。
タイミングが重要になるアクションゲームみたいなものをJavaScriptで作る人って、精度の問題どうしてるんでしょうね。大変ですね。
最後に、ソースを眺めたい人用に、今回使用したサンプルコードを貼っておきますので、煮てよし焼いてよし、好きにしてください。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>test1</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> </head> <body> <div> </div> <div> <form name="frmMain"> <input type="button" value="Start" onclick="doit()"><br> <input type="text" name="txtMain" size="100" value=""> </form> </div> <script type="text/javascript"> <!-- function doit() { var d = new Date(); var ms = d.getMilliseconds(); document.frmMain.txtMain.value = d.toString() + ", getMilliseconds: " + ms; var timeoutValue = 1000; if( ms >= 1 ) timeoutValue = 1000 - ms; if( timeoutValue <= 100 ) timeoutValue = 300; setTimeout( "doit()", timeoutValue ); document.frmMain.txtMain.value = d.toString() + ", getMilliseconds: " + ms + ", timeoutValue: " + timeoutValue; } // --> </script> </body> </html>
最近のコメント