《 12:00 PM 公開/更新》
〆切(期限)日時まであとどのくらいの日数・時間が残っているのかをJavaScriptでリアルタイムにカウントダウン表示し続ける機能を作ってみましょう。現在日時と指定日時の差を求めて、差から残り日数・時刻を計算し、setIntervalメソッドを使って1秒ごとに表示を更新するだけで作れます。
JavaScriptを使って、〆切(期限)日時まであとどのくらいの日数・時間があるのかをリアルタイムにカウントダウンし続ける機能を作ってみましょう。
指定の日時までにあと何ミリ秒あるのか?をJavaScriptで得る方法は、記事「指定日までの残り日数を計算して表示する」で解説しました。
また、一定間隔ごとに特定の処理を自動実行する方法は、記事「経過時間(秒数)をリアルタイムに表示する」で解説しました。
この2つを組み合わせれば、期限日時まで、ひたすらカウントダウンし続ける機能も簡単に作れます。
例えば、以下のように。サンプルとして日時が既に入っていますが、書き換えればその日時までをカウントダウンします。
年月日時分秒
※ここにカウントダウンが表示されます。
「上記の日時までカウントダウンする」ボタンをクリックすると、その瞬間に再計算されて表示します。……が、最初から1秒毎に自動更新しているので、ボタンを押さなくても最大1秒待つだけで再計算されてカウントダウン表示は更新されます。(^_^;)
上記でやっていることは、
という処理です。
他に、1桁の数字を2桁に調整する機能や、数字以外の文字が入力された場合には0として解釈する機能など、エラー対策も含んでいますが。
以下に、HTML+JavaScriptソースに関して簡単に解説してみます。(※解説をすっ飛ばして全体のソースを見たい場合は、本ページ末尾の項目「リアルタイムカウントダウン機能を作るHTML+JavaScriptソースのまとめ」へどうぞ。)
とりあえず、HTMLで以下の6個の入力欄を作っています。JavaScript側から参照するために、id属性を使って名前を付けています。
HTMLソース
<input type="text" id="userYear" >年 <input type="text" id="userMonth">月 <input type="text" id="userDate" >日 <input type="text" id="userHour" >時 <input type="text" id="userMin" >分 <input type="text" id="userSec" >秒
あと、実際にカウントダウンを表示するための領域を以下のように確保しています。
HTMLソース
<p id="RealtimeCountdownArea" >※ここにカウントダウンが表示されます。</p>
上記のid名「RealtimeCountdownArea」を使って、JavaScriptから表示を更新します。
指定日時までの残り時間をカウントダウンするためには、「指定日時」から「現在日時」を引き算する必要があります。
その辺の処理に関しては、記事「指定日までの残り日数を計算して表示する」で解説していますから、詳しくはそちらをご参照下さい。
ここでは、以下のようにJavaScriptソースを記述しています。
かなり冗長なソースですが、「何をやっているのか?」の分かりやすさを重視して、短くせずに記述しています。実際に活用する際は、もっと短く書いた方が良いと思います。^^;
……と言いつつ、エラー処理部分は省略しているのですが。そこを含めるとソースを解釈しにくくなりそうなので。^^;(末尾のソースまとめには記載しています。)
JavaScriptソース
var nowDate = new Date(); var dnumNow = nowDate.getTime();
上記で、「現在日時」を数値(1970-01-01 00:00:00からのミリ秒)に変換して、変数dnumNowに格納しています。
JavaScriptソース
var inputYear = document.getElementById("userYear").value; var inputMonth = document.getElementById("userMonth").value - 1; var inputDate = document.getElementById("userDate").value; var inputHour = document.getElementById("userHour").value; var inputMin = document.getElementById("userMin").value; var inputSec = document.getElementById("userSec").value; var targetDate = new Date( inputYear, inputMonth, inputDate, inputHour, inputMin, inputSec ); var dnumTarget = targetDate.getTime();
上記で、ユーザが入力した指定日時を、数値(1970-01-01 00:00:00からのミリ秒)に変換して、変数dnumTargetに格納しています。
Dateオブジェクトでは、月の指定は、「1月が0」・「2月が1」……「12月が11」になるので、1を引いています。
JavaScriptソース
var diff2Dates = dnumTarget - dnumNow; if( dnumTarget < dnumNow ) { // 期限が過ぎた場合は -1 を掛けて正の値に変換 diff2Dates *= -1; }
上記で、2つの変数を引き算して、日数(ミリ秒)の差を計算しています。
期限が過ぎている場合はマイナスの値になるので、その場合には -1 を掛けて正の値にしています。
JavaScriptソース
var dDays = diff2Dates / ( 1000 * 60 * 60 * 24 ); // 日数 diff2Dates = diff2Dates % ( 1000 * 60 * 60 * 24 ); var dHour = diff2Dates / ( 1000 * 60 * 60 ); // 時間 diff2Dates = diff2Dates % ( 1000 * 60 * 60 ); var dMin = diff2Dates / ( 1000 * 60 ); // 分 diff2Dates = diff2Dates % ( 1000 * 60 ); var dSec = diff2Dates / 1000; // 秒
上記で、「差のミリ秒」を、日数・時間・分・秒に分解しています。
「割った解」と「割った余り」を使っていくことで、日→時→分→秒の順に抜き出しています。
日数は変数dDaysに、時間は変数dHourに、分は変数dMinに、秒は変数dSecに入ります。
なんかもうちょっとスマートな方法があるような気がしますが(^_^;)、まあ上記でもちゃんと計算はできます。
次に、計算結果を画面に表示する必要があります。
冒頭のサンプルでは、ユーザが入力した日時も含めて表示しています。
それらのソースは以下の通りです。
JavaScriptソース
var dlYear = targetDate.getFullYear(); var dlMonth = targetDate.getMonth() + 1; var dlDate = targetDate.getDate(); var dlHour = targetDate.getHours(); var dlMin = targetDate.getMinutes(); var dlSec = targetDate.getSeconds(); var msg1 = "期限の" + dlYear + "/" + dlMonth + "/" + dlDate + " " + dlHour + ":" + dlMin + ":" + dlSec;
上記で、変数msg1に、ユーザが指定した日時が文字列として格納されます。
実際には、「1桁の数字を2桁固定にする」処理を含んでいますが、上記では見た目を簡単にするために省略しています。
先も述べましたが、月は「1月が0」・「2月が1」……「12月が11」になっているので、ここでは1を足しています。
ユーザが入力した文字列を直接は利用せずに、カウントダウン計算用のDateオブジェクトから日付を求めているのは、ユーザの入力内容をそのまま出力する危険を避けるためです。
JavaScriptソース
var msg2 = Math.floor(dDays) + "日" + Math.floor(dHour) + "時間" + Math.floor(dMin) + "分" + Math.floor(dSec) + "秒";
上記で、変数msg2に、残り日数・時間が文字列として格納されます。ここがカウントダウンのメインです。
なお、Math.floorは、小数点以下を取り去る関数です。これがないと、小数点以下がずらーっと並んでしまいます。
ソースを見やすくするために改行していますが、全部を1行で書いても問題ありません。
JavaScriptソース
var msg; if( dnumTarget > dnumNow ) { // まだ期限が来ていない場合 msg = msg1 + "までは、あと" + msg2 + "です。"; } else { // 期限が過ぎた場合 msg = msg1 + "は、既に" + msg2 + "前に過ぎました。"; }
上記で、画面表示用の文字列を作成し、変数msgに格納しています。
「期限が来ていない」場合と「期限が過ぎた場合」とで表現を変える必要があったので、if文で条件分岐させています。
JavaScriptソース
document.getElementById("RealtimeCountdownArea").innerHTML = msg;
最後に、上記のようにinnerHTMLメソッドを使って、作成した文字列を(id名「RealtimeCountdownArea」の領域に)表示しています。
上記の一連の処理を、「showCountdown」という名称で関数にしておけば完成です。(全体のソースは後述)
上記で作成したソースを、1秒毎に繰り返し自動実行することで、「リアルタイムのカウントダウン」が実現します。
一定間隔ごとに特定の処理を自動実行する方法は、記事「経過時間(秒数)をリアルタイムに表示する」で解説しましたから、詳しくはそちらをご参照下さい。
ここでは、以下のように1行を書いただけです。
setInterval('showCountdown()',1000);
これで、1000ミリ秒(=1秒)ごとにshowCountdown関数が実行されます。
基本的に今回のサンプルは、2つの記事で解説済みの内容を組み合わせただけです。
なので、説明はあまり詳しくは書きませんでした。
全体的に対して難しくないので、ソースを読んで頂ければ簡単に分かるとは思いますが。(^_^;)
以下に、すべてのソース(HTML+JavaScript)をまとめて掲載しておきます。上記では省略した、桁数調整や入力エラー対策の関数も含んでいます。
HTMLソース
<p> <input type="text" id="userYear" maxlength="4">年 <input type="text" id="userMonth" maxlength="2">月 <input type="text" id="userDate" maxlength="2">日 <input type="text" id="userHour" maxlength="2">時 <input type="text" id="userMin" maxlength="2">分 <input type="text" id="userSec" maxlength="2">秒<br> <input type="button" value="上記の日時までカウントダウンする" onclick="showCountdown();"> </p> <p id="RealtimeCountdownArea">※ここにカウントダウンが表示されます。</p>
JavaScriptソース
function set2fig(num) { // 数値が1桁だったら2桁の文字列にして返す var ret; if( num < 10 ) { ret = "0" + num; } else { ret = num; } return ret; } function isNumOrZero(num) { // 数値でなかったら0にして返す if( isNaN(num) ) { return 0; } return num; } function showCountdown() { // 現在日時を数値(1970-01-01 00:00:00からのミリ秒)に変換 var nowDate = new Date(); var dnumNow = nowDate.getTime(); // 指定日時を数値(1970-01-01 00:00:00からのミリ秒)に変換 var inputYear = document.getElementById("userYear").value; var inputMonth = document.getElementById("userMonth").value - 1; var inputDate = document.getElementById("userDate").value; var inputHour = document.getElementById("userHour").value; var inputMin = document.getElementById("userMin").value; var inputSec = document.getElementById("userSec").value; var targetDate = new Date( isNumOrZero(inputYear), isNumOrZero(inputMonth), isNumOrZero(inputDate), isNumOrZero(inputHour), isNumOrZero(inputMin), isNumOrZero(inputSec) ); var dnumTarget = targetDate.getTime(); // 表示を準備 var dlYear = targetDate.getFullYear(); var dlMonth = targetDate.getMonth() + 1; var dlDate = targetDate.getDate(); var dlHour = targetDate.getHours(); var dlMin = targetDate.getMinutes(); var dlSec = targetDate.getSeconds(); var msg1 = "期限の" + dlYear + "/" + dlMonth + "/" + dlDate + " " + set2fig(dlHour) + ":" + set2fig(dlMin) + ":" + set2fig(dlSec); // 引き算して日数(ミリ秒)の差を計算 var diff2Dates = dnumTarget - dnumNow; if( dnumTarget < dnumNow ) { // 期限が過ぎた場合は -1 を掛けて正の値に変換 diff2Dates *= -1; } // 差のミリ秒を、日数・時間・分・秒に分割 var dDays = diff2Dates / ( 1000 * 60 * 60 * 24 ); // 日数 diff2Dates = diff2Dates % ( 1000 * 60 * 60 * 24 ); var dHour = diff2Dates / ( 1000 * 60 * 60 ); // 時間 diff2Dates = diff2Dates % ( 1000 * 60 * 60 ); var dMin = diff2Dates / ( 1000 * 60 ); // 分 diff2Dates = diff2Dates % ( 1000 * 60 ); var dSec = diff2Dates / 1000; // 秒 var msg2 = Math.floor(dDays) + "日" + Math.floor(dHour) + "時間" + Math.floor(dMin) + "分" + Math.floor(dSec) + "秒"; // 表示文字列の作成 var msg; if( dnumTarget > dnumNow ) { // まだ期限が来ていない場合 msg = msg1 + "までは、あと" + msg2 + "です。"; } else { // 期限が過ぎた場合 msg = msg1 + "は、既に" + msg2 + "前に過ぎました。"; } // 作成した文字列を表示 document.getElementById("RealtimeCountdownArea").innerHTML = msg; } // 1秒ごとに実行 setInterval('showCountdown()',1000);
上記では、一定時間毎に処理を繰り返すsetIntervalメソッドをいきなり実行しているので、スクリプトの読み込みと同時に処理が開始されます。
それを避けたい場合は、setIntervalメソッドも何らかの関数の内側に記述して下さい。記事「経過時間(秒数)をリアルタイムに表示する」では、ボタンをクリックするまでsetIntervalメソッドを実行しない書き方をしています。
showCountdown関数を実行するためのボタンも用意していますが、押さなくても1秒ごとに自動実行されるので、まあ不要です。(^_^;)
ページの読込と同時にカウントダウンを実行させるのでないのなら、カウントダウンを開始するボタンが必要ですが。
なお、期限日時が来たとき、「残り0日0時間0分0秒です」→「0日0時間0分0秒前に過ぎました」で、合計2秒間あるように見えます。
なぜこうなるのかは、ミリ秒まで表示させてみるとよく分かります。(^_^;;;
上記のようになるので、「指定日時まで残り1秒を切った後」から「指定日時から1秒が経過する直前」までの2秒間は、「0秒」の表示になります。
若干、不思議な感じがするので、それを避けたければ、ミリ秒まで含めて表示するのも良いかも知れません。
変数msg2を作る行を以下のようにした上で、
JavaScriptソース
var dMiSec = diff2Dates % 1000; var msg2 = Math.floor(dDays) + "日" + Math.floor(dHour) + "時間" + Math.floor(dMin) + "分" + Math.floor(dSec) + "秒" + dMiSec;
以下のように、setIntervalメソッドを1秒よりももっと短い間隔で呼び出します。
setInterval('showCountdown()',200);
上記の場合は、200ミリ秒(=0.2秒)ごとに描画が更新されます。
ただ、あまり更新頻度を上げてしまうと、処理が重たくなってしまう可能性がありますから、あんまり頻度を上げすぎない(=数値を低くし過ぎない)方が良いとは思います。
……というわけで、なんだかほとんどソースだけを掲載したような感じですが。(^_^;)
まあ、解説は冒頭でリンクしている2本の記事に書いていますからね。^^; 重複分を除けば、ほとんど説明することなんてないので。(^_^;;;
ユーザの指定した日時までの残り日数・時間をリアルタイムにカウントダウンする機能の作り方でした。(期限が過ぎた場合は、カウントダウンではなくカウントアップですが。^^;)
ぜひ、何かに活用してみて下さい。(^_^;)
()
(前の記事) « 現在時刻をテキストでリアルタイムに表示し続ける時計を作る方法
前後のJavaScript TIPS
< 旧 / 新 >
(次の記事) チェックボックスに合わせてテキスト入力欄の有効・無効を切り替える方法 »
▼このページに関連しそうな記事が約8本くらい自動表示されています。(たぶん)