MENU

【JavaScript】 カウントダウンタイマーをブラウザに設置してみる

更新日:2021/05/14

 

「後〇〇分で終了」なんて聞くと、自分も参加してくなります。
これをWebページやるときはカウントダウン表示すると、効果的ですね。

 

そこで今回は、ブラウザ上にカウントダウンタイマーを設置する方法を紹介します。

 

カウントダウンの主要となる関数を作成

 

カウントダウンのタイマー管理および残り時間と終了を通知する関数を作成します。
ブラウザへの表示はここではおこなわないことで、汎用性を確保しています。

 

なお経過時間の計測について次の記事で紹介しているので、確認してみてください。
【JavaScript】 経過時間や日数を取得し処理時間などを計測

 

カウントダウン主要コード

 


const coutdownTimer =  ( tickCallBack , endCallBack
    ,daysOrSeconds , hours = null , minutes  = null , seconds = null ) => {

        // 秒を日数・時間・分・秒に変換
    const calcTime = sec =>{
        const days = Math.floor(sec / 86400);
        const hours = Math.floor( (sec-=days*86400) / 3600);
        const minutes = Math.floor( (sec-=hours*3600) / 60);
        sec-=minutes*60;
        return [days,hours,minutes,sec];
    };

        // 引数を秒数に変換
    let sec = (hours===null) ? daysOrSeconds
        : seconds + minutes * 60 + hours * 3600 + daysOrSeconds * 86400;

        // スタートのタイムスタンプ取得
    const startTime = Date.now();
        // 初回の残り時間通知
    tickCallBack( calcTime(sec) );

        // タイマースタート(1秒間隔)
    const timer = setInterval(
        ()=>{
                // 残り時間を秒で計算
            let nowSec= sec - Math.floor( (Date.now() - startTime) / 1000 );
            if( nowSec <= 0 ) { // 残り時間なし
                clearInterval(timer); // タイマー停止
                endCallBack(); // 終了通知
            }else{
                tickCallBack( calcTime(nowSec) ); // 残り時間通知
            }
        },1000
    )

};

 

コードが長いですが、処理的には単純です。

 

先頭の二つの引数は残り時間と終了の通知を受け取るコールバック関数を指定します。

 

3つ目以降はカウントの開始時間を指定します。
このとき4つ目以降に引数がない場合は、3つ目の引数を秒として扱います。

 

4つ目以降に引数がある場合は、3つ目から順番に日数・時間数・分数・秒数が指定されたとします。

 

なお引数の妥当性はおこなっていません。
必要なら追加してください。

 

使用例

 

では実際に使用しています。
次のスタートボタンを押すとカウントダウンが始まり、残り時間がゼロになった時点で終了します。

 

デモ

 

----

 

 

デモで使用したHTMLコードがこれ。

 

HTML


<button id="timerstart">スタート</button>
<p id="timer"></p>

 

JavaScriptコードは次のようになっています。

 

JavaScript


window.addEventListener( "DOMContentLoaded" , ()=> {

    const button = document.getElementById("timerstart");
    const p = document.getElementById("timer");

       // 残り時間通知受け取り関数
    const tickFunc = ( time  )=>{
        p.textContent = `残り${ time[0] } 日 ${ time[1] }時間 ${ time[2] }分  ${ time[3] }秒`;
    };
       // 終了通知受け取り関数
    const endFunc = ()=>{
        p.textContent = "終了しました";
    };

    button.addEventListener("click",()=>{
        coutdownTimer( tickFunc , endFunc , 70 );
    });
});

 

Promiseに置き換える

 

この程度のスクリプトは使用する意味がないのですが、同期処理はPromiseを使用すべきという方が一部でいるので、Promiseに置き換えてみます。

 


const coutdownTimer =  ( tickCallBack , endCallBack
    ,daysOrSeconds , hours = null , minutes  = null , seconds = null ) => {

        // 省略

    return new Promise( resolve => {
        // タイマースタート(1秒間隔)
        const timer = setInterval(
            ()=>{
                    // 残り時間を秒で計算
                let nowSec= sec - Math.floor( (Date.now() - startTime) / 1000 );
                if( nowSec <= 0 ) { // 残り時間なし
                    clearInterval(timer); // タイマー停止
                    if( endCallBack ) endCallBack(); // 終了通知
                    resolve();
                }else{
                    tickCallBack( calcTime(nowSec) ); // 残り時間通知
                }
            },1000
        )
    });
};

 

タイマー処理までは全く同じコードのため、ここでは省略してあります。
また省略した都合上、終了コールバックとPromiseの両方に対応したコードになっています。

 

このコードに対応したcoutdownTimer呼び出しは、次のようになります。

 


coutdownTimer( tickFunc , null , 70 )
            .then( ()=>endFunc() );

 

Promiseオブジェクトを経由することで余計な内部処理が増えます。
thenが使えること以外、あまり利点がないですね。

数値画像でカウントダウンする

 

0から9までの画像を用意して、その画像でカウントダウンをしてみます。

 

 

デモ

 


------

残り 時間

 

HTMLは次のようになっています。

 

HTML


<button id="timerstart">スタート</button>
<p id="msg"></p>
<p id="timer">
    残り<img src="https://note.affi-sapo-sv.com/img/n0.png">
    <img src="https://note.affi-sapo-sv.com/img/n0.png">日
    <img src="https://note.affi-sapo-sv.com/img/n0.png">
    <img src="https://note.affi-sapo-sv.com/img/n0.png">時間
    <img src="https://note.affi-sapo-sv.com/img/n0.png">
    <img src="https://note.affi-sapo-sv.com/img/n0.png">分
    <img src="https://note.affi-sapo-sv.com/img/n0.png">
    <img src="https://note.affi-sapo-sv.com/img/n0.png">秒
</p>

 

スクリプトコードはこちら。

 

JavaScript

 


const button = document.getElementById("timerstart");
const pmsg = document.getElementById("msg");
const ptimer = document.getElementById("timer");
const imgs = ptimer.querySelectorAll("img");

const srcimg = [
        "https://note.affi-sapo-sv.com/img/n0.png",
        "https://note.affi-sapo-sv.com/img/n1.png",
        "https://note.affi-sapo-sv.com/img/n2.png",
        "https://note.affi-sapo-sv.com/img/n3.png",
        "https://note.affi-sapo-sv.com/img/n4.png",
        "https://note.affi-sapo-sv.com/img/n5.png",
        "https://note.affi-sapo-sv.com/img/n6.png",
        "https://note.affi-sapo-sv.com/img/n7.png",
        "https://note.affi-sapo-sv.com/img/n8.png",
        "https://note.affi-sapo-sv.com/img/n9.png",
        ];
const tickFunc = ( time  )=>{
        imgs[0].src = srcimg[Math.floor(time[0] / 10)];
        imgs[1].src = srcimg[time[0] % 10];

        imgs[2].src = srcimg[Math.floor(time[1] / 10)];
        imgs[3].src = srcimg[time[1] % 10];

        imgs[4].src = srcimg[Math.floor(time[2] / 10)];
        imgs[5].src = srcimg[time[2] % 10];

        imgs[6].src = srcimg[Math.floor(time[3] / 10)];
        imgs[7].src = srcimg[time[3] % 10];
    };
const endFunc = ()=>{
        pmsg.textContent = "終了しました";
    };

button.addEventListener("click",()=>{
        pmsg.textContent = "開催中です";
        coutdownTimer( tickFunc , endFunc , 70 );
    });

 

カウントダウンの主要関数coutdownTimerはそのまま使用して、ブラウザの表示部分を変更します。

 

今回はあらかじめimgタグを用意しておき、src属性を変更しています。

 

数値画像がキャッシュされていない場合srcを変更した時点で読み込みがおこなわれるので、通信状況によっては表示が乱れる可能性があります。

 

気になる場合は、次のコードでサーバーから先読みをしておくといいです。

 

数値画像の先読み

 


for( let i = 0 ; i < srcimg.length ; i ++ )
    document.createElement( "img" ).src = srcimg[i];

 

気持ちを焦らせるカウントダウンタイマー

 

ここまでは秒単位のカウントタイマーを紹介してきました。
でもなんだか、のんびりしてる印象を受けますね。

 

次のデモを実行してみてください。

 

デモ

 


------

残り 時間 ミリ秒

 

最後のミリ秒が目まぐるしく変化するの見ていると、なんだか今すぐ行動しないていけないような気分になって、気持ちが焦ってきますね。

 

スクリプトコードは、これまで秒だったものをミリ秒にするだけです。
ご自由に改良してみてください。

けーちゃんおススメJavaScript入門書

  • スラスラ読める JavaScript ふりがなプログラミング
  • プログラム未経験者がJavaScript始めるならコレ!
    コードを掲載して自分で理解しろという投げっぱなしな入門書とは異なり、コードに一つ一つどんなことをやっているかをふりがなという形式で解説しています。
    それでいてJavaScriptの基礎と応用を学べる良書です。
  • これからWebをはじめる人のHTML&CSS、JavaScriptのきほんのきほん
  • JavaScriptの機能を実践で活かすにはHTMLやCSSの知識が不可欠です。
    しかしそれらの知識があることが前提として書かれている書籍が多い中、この本は総合的な知識を身に着けることができます。
    HTMLやCSSの知識も不安な方には、ぴったりの一冊です
  •  

    入門書の役割は、自分のやりたいことをネットで調べることができるようになるための、基礎的な知識の獲得です。
    まずはこれらの本でしっかりと基礎知識を身につけましょう。
    そしてもっと高度なことや専門的なことはネットで調べ、情報が足りないと感じたら書籍を購入してください。


    期間限定情報:
    6/21と6/22は年に一度のプライム会員大感謝祭!
    欲しかったアレが安く手に入るチャンスです
    忘れずにチェックしてください!
    僕は以前のタイムセール祭りで4Kモニタが買ったけど、それより安かったらどうしよう・・・

    ちなみにプライム会員でなくても、無料体験で参加できるようです。
    欲しい商品があるか、確認だけでもしておきましょう。

    記事の内容について

     

    こんにちはけーちゃんです。
    説明するのって難しいですね。


    「なんか言ってることおかしくない?」
    たぶん、こんなご意見あると思います。

    裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

    そんなときは、ご意見もらえたら嬉しいです。

    ご意見はこちら。
    https://note.affi-sapo-sv.com/info.php

    【お願い】

    お願い

    ■このページのURL


    ■このページのタイトル


    ■リンクタグ


    ※リンクして頂いた方でご希望者には貴サイトの紹介記事を作成してリンクを設置します。
    サイト上部の問い合わせよりご連絡ください。
    ただしサイトのジャンルによっては、お断りさせていただくことがあります。