JavaScript カウントダウンタイマー

概要: このチュートリアルでは、再利用可能な JavaScript カウントダウンタイマーを開発する方法を学びます。

カウントダウンタイマーとは

カウントダウンタイマーは、ランディングページで実行される仮想時計です。特定の日付からカウントダウンして、イベントの開始(または終了)を示します。

eコマースWebサイトでは、カウントダウンタイマーを使用して、オファーの開始(または終了)を表示できます。カウントダウンタイマーの目的は、顧客に製品やサービスの購入などの行動を促すことです。

このチュートリアルでは、JavaScript でゼロからカウントダウンタイマーを作成する方法を学びます。そして、それを使用して新年のカウントダウンタイマーを作成する方法を学びます。

以下は、最終的な新年のカウントダウンランディングページです。

作成するカウントダウンタイマーは再利用可能であるため、どのランディングページでも使用できます。さらに、このカウントダウンを使用して、1つのページに複数のカウントダウンタイマーを作成できます。

プロジェクト構造の作成

まず、countdown-timer というプロジェクトフォルダを作成します。そのフォルダ内に、JavaScript、CSS、および画像ファイルを格納する3つのサブフォルダ:jscss、および img を作成します。

次に、css フォルダに style.cssjs フォルダに app.jscountdown.js ファイル、そして countdown-timer フォルダに index.html を作成します。

3番目に、この花火の画像をダウンロードして、img フォルダにコピーします。この画像は、新年のカウントダウンページの背景として使用します。

プロジェクト構造は次のようになります

HTMLページの作成

HTMLコードの大部分は JavaScript から生成されるため、HTMLページは非常にシンプルです。

以下は、完全なHTMLページです

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Countdown Timer - New Year Countdown</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <h1>New Year Countdown</h1>
    <div class="countdown-timer"></div>
    <div class="message"></div>
    <div class="year"></div>

    <script src="js/countdown.js"></script>
    <script src="js/app.js"></script>

</body>
</html>Code language: HTML, XML (xml)

index.html ファイルでは、<head> セクションに style.css ファイルへのリンクを、<body> セクションに countdown.jsapp.js ファイルを配置します。

app.jscountdown.js ファイル内のオブジェクトを使用するため、countdown.js ファイルは app.js ファイルの前に配置する必要があります。

<body> セクションには4つの要素があります

  • 見出し1(<h1>)。この要素は見出しを表示します。カウントダウンを説明するものなら何でもかまいません(例:新年のカウントダウン)。
  • クラス countdown-timer を持つ <div>。この要素はカウントダウンを表示します。
  • message クラスを持つ <div>。この要素は、カウントダウンが完了したときにメッセージを表示します。
  • そして、year クラスを持つ <div>。この要素は新年を表示します(例:2021)。

Dateオブジェクトの概要

タイマーを作成するには、すべてのWebブラウザで使用可能な Date オブジェクトを使用する必要があります。

Date オブジェクトは、ある時点を表します。 1970年1月1日UTCからのミリ秒数を表す数値が含まれています。

以下は、現在の日付と時刻を表す新しい Date オブジェクトを作成する方法を示しています

const now = new Date();Code language: JavaScript (javascript)

そして、この例は、Date オブジェクトの getTime() メソッドを呼び出して、1970年1月1日00:00:00 UTC からのミリ秒数を取得する方法を示しています

const time = now.getTime();
console.log(time);Code language: JavaScript (javascript)

指定された日付と時刻で新しい Date オブジェクトを作成するには、次のように日付文字列を Date() コンストラクタに渡すことができます

const d = new Date('February 02, 2020 01:02:03');
console.log(d.getTime()); // 1580580123000Code language: JavaScript (javascript)

2つの時刻間のミリ秒数を計算するには、getTime() メソッドを呼び出して、- 演算子を使用します。例えば

const d1 = new Date('September 17, 2020 00:00:00');
const d2 = new Date('September 19, 2020 01:00:00');

const time = d2.getTime() - d1.getTime();
console.log(time); // 176400000Code language: JavaScript (javascript)

残り時間を計算する

カウントダウンタイマーは、ミリ秒数から残りの日数、時間、分、秒を計算し、この情報をWebページに表示する必要があります。

以下は、値が150000ミリ秒のtime変数を宣言しています

const time = 150000; // msCode language: JavaScript (javascript)

ミリ秒を分に変換するには、ミリ秒を1000で割って秒を取得し、秒を60で割って分を取得します。例えば

console.log(time / 1000 / 60); Code language: JavaScript (javascript)

出力

2.5Code language: CSS (css)

残りの分(2)を取得するには、Math.floor() 関数を使用します

const minutes = Math.floor(time / 1000 / 60);
console.log(minutes); // 2Code language: JavaScript (javascript)

残りの秒(30)を取得するには、除算の剰余を返す剰余演算子( % )を使用します

const seconds = Math.floor(time / 1000) % 60;
console.log(seconds); // 30Code language: JavaScript (javascript)

CountDownクラスの開発

まず、countdown.js ファイルに新しい CountDown クラスを作成します

class CountDown {
}Code language: JavaScript (javascript)

CountDown クラスは、3つの引数で初期化される必要があります

  • 有効期限。
  • カウントダウンタイマーのレンダリングを担当するコールバック。
  • そして、カウントダウンが完了したときに呼び出される別のコールバック。

CountDown クラスのコンストラクタは次のようになります

class CountDown {
    constructor(expiredDate, onRender, onComplete) {
        this.onRender = onRender;
        this.onComplete = onComplete;
        // handle the expired Date
        ..
    }
}Code language: JavaScript (javascript)

expiredDate 引数に基づいて、残り時間をミリ秒単位で計算できます

const currentTime = new Date().getTime();
const timeRemaining = expiredDate.getTime() - currentTime;Code language: JavaScript (javascript)

クラスのメソッド全体で残り時間(timeRemaining)にアクセスする必要があるため、CountDown クラスのプロパティとして定義する必要があります。

setExpiredDate() メソッド

以下は、timeRemaining プロパティを初期化する setExpiredDate() という新しいメソッドを定義しています

 setExpiredDate(expiredDate) {
    // get the current time
    const currentTime = new Date().getTime();
    // calculate the remaining time 
    this.timeRemaining = expiredDate.getTime() - currentTime;
}Code language: JavaScript (javascript)

timeRemaining がゼロより大きい場合、setExpiredDate() メソッドは start() メソッドを実行してタイマーを開始します。そうでない場合は、complete() メソッドを実行します。

setExpiredDate() は次のようになります

setExpiredDate(expiredDate) {
    // get the current time
    const currentTime = new Date().getTime();

    // calculate the remaining time 
    this.timeRemaining = expiredDate.getTime() - currentTime;

    // should the countdown completes or start
    this.timeRemaining > 0 ?
        this.start() :
        this.complete();
}Code language: JavaScript (javascript)

this.timeRemaining プロパティの値に基づいて complete() または start() メソッドを実行するために、三項演算子 ?: を使用していることに注意してください。

complete() メソッド

complete() メソッドは、onComplete コールバックが渡されたかどうかを確認し、それを呼び出します。 onComplete が使用できない場合、complete() は何もしません。

complete() {
    if (typeof this.onComplete === 'function') {
        onComplete();
    }
}Code language: JavaScript (javascript)

start() メソッド

start() メソッドは、timeRemaining プロパティを毎秒(1000ミリ秒)減らします。

残り時間がゼロ未満の場合、start() メソッドは

  • まず、complete() メソッドを呼び出します。
  • 次に、clearInterval() 関数を使用してタイマーをクリアします。
start() {
    //  setup a timer
    const intervalId = setInterval(() => {
        // update the timer  
        this.timeRemaining -= 1000;

        if (this.timeRemaining < 0) {
            // call the callback
            complete();

            // clear the interval if expired
            clearInterval(intervalId);
        }

    }, 1000);
}Code language: JavaScript (javascript)

残り時間がゼロより大きい場合、start() メソッドは onRender コールバックを実行するメソッドを呼び出す必要があります。

getTime() メソッド

以下の getTime() メソッドは、timeRemaining プロパティに基づいて、残りの日数、時間、分、秒を含むオブジェクトを返します。

  getTime() {
    return {
        days: Math.floor(this.timeRemaining / 1000 / 60 / 60 / 24),
        hours: Math.floor(this.timeRemaining / 1000 / 60 / 60) % 24,
        minutes: Math.floor(this.timeRemaining / 1000 / 60) % 60,
        seconds: Math.floor(this.timeRemaining / 1000) % 60
    };
}Code language: JavaScript (javascript)

update() メソッド

以下は、getTime() メソッドによって返された現在の残り時間オブジェクトを使用して onRender() コールバックを呼び出す update() メソッドを定義しています

update() {
    if (typeof this.onRender === 'function') {
        this.onRender(this.getTime());
    }
}Code language: JavaScript (javascript)

start() メソッドは、最初に、そしてその後毎秒 update() メソッドを呼び出します

start() {
    // update the countdown
    this.update();

    //  setup a timer
    const intervalId = setInterval(() => {
        // update the timer  
        this.timeRemaining -= 1000;

        if (this.timeRemaining < 0) {
            // call the callback
            complete();

            // clear the interval if expired
            clearInterval(intervalId);
        } else {
            this.update();
        }

    }, 1000);
}Code language: JavaScript (javascript)

以下は、完全な CountDown クラスです

class CountDown {
    constructor(expiredDate, onRender, onComplete) {
        this.setExpiredDate(expiredDate);

        this.onRender = onRender;
        this.onComplete = onComplete;
    }

    setExpiredDate(expiredDate) {
        // get the current time
        const currentTime = new Date().getTime();

        // calculate the remaining time 
        this.timeRemaining = expiredDate.getTime() - currentTime;

        this.timeRemaining <= 0 ?
            this.complete() :
            this.start();
    }


    complete() {
        if (typeof this.onComplete === 'function') {
            onComplete();
        }
    }
    getTime() {
        return {
            days: Math.floor(this.timeRemaining / 1000 / 60 / 60 / 24),
            hours: Math.floor(this.timeRemaining / 1000 / 60 / 60) % 24,
            minutes: Math.floor(this.timeRemaining / 1000 / 60) % 60,
            seconds: Math.floor(this.timeRemaining / 1000) % 60
        };
    }

    update() {
        if (typeof this.onRender === 'function') {
            this.onRender(this.getTime());
        }
    }

    start() {
        // update the countdown
        this.update();

        //  setup a timer
        const intervalId = setInterval(() => {
            // update the timer  
            this.timeRemaining -= 1000;

            if (this.timeRemaining < 0) {
                // call the callback
                complete();

                // clear the interval if expired
                clearInterval(intervalId);
            } else {
                this.update();
            }

        }, 1000);
    }
}Code language: JavaScript (javascript)

新年のカウントダウンを作成する

まず、新年を返す getNewYear() メソッドという新しい関数を作成します

const getNewYear = () => {
    const currentYear = new Date().getFullYear();
    return new Date(`January 01 ${currentYear + 1} 00:00:00`);
};Code language: JavaScript (javascript)

次に、.year 要素を選択して更新します。新年の4桁の年番号(例:2021)が表示されます

// update the year element
const year = document.querySelector('.year');
year.innerHTML = getNewYear().getFullYear();Code language: JavaScript (javascript)

3番目に、.countdown-timer.message、および h1 要素を選択します

// select elements
const app = document.querySelector('.countdown-timer');
const message = document.querySelector('.message');
const heading = document.querySelector('h1');Code language: JavaScript (javascript)

4番目に、数値が10未満の場合に数値に '0' をパディングする format 関数を定義します。たとえば、5は 05 になります。しかし、10は変わりません。

const format = (t) => {
    return t < 10 ? '0' + t : t;
};Code language: JavaScript (javascript)

5番目に、時間オブジェクトからHTMLマークアップを作成し、.countdown-timer 要素に更新する render() メソッドを定義します。残りの日数、時間、分、秒が表示されます。


const render = (time) => {
    app.innerHTML = `
        <div class="count-down">
            <div class="timer">
                <h2 class="days">${format(time.days)}</h2>
                <small>Days</small>
            </div>
            <div class="timer">
                <h2 class="hours">${format(time.hours)}</h2>
                <small>Hours</small>
            </div>
            <div class="timer">
                <h2 class="minutes">${format(time.minutes)}</h2>
                <small>Minutes</small>
            </div>
            <div class="timer">
                <h2 class="seconds">${format(time.seconds)}</h2>
                <small>Seconds</small>
            </div>
        </div>
        `;
};
Code language: HTML, XML (xml)

5番目に、カウントダウンが完了すると、メッセージ(例:"新年あけましておめでとうございます")が表示されます。

以下の showMessage() 関数は、新年あけましておめでとうございます メッセージを表示します。さらに、.countdown-timer 要素の内容をクリアし、見出し要素を非表示にします

const showMessage = () => {
    message.innerHTML = `Happy New Year ${newYear}!`;
    app.innerHTML = '';
    heading.style.display = 'none';
};Code language: JavaScript (javascript)

6番目に、新年のカウントダウンは、一定期間「新年あけましておめでとうございます」の挨拶メッセージを表示し、その後、再び新年のカウントダウンを表示する必要があります。

以下は、挨拶メッセージを非表示にし、見出し要素を表示する関数を定義しています

const hideMessage = () => {
    message.innerHTML = '';
    heading.style.display = 'block';
}Code language: JavaScript (javascript)

7番目に、一定期間メッセージを表示してから非表示にする complete() 関数を定義します。さらに、expiredDate を新年

const complete = () => {
    showMessage();
    // restart the countdown after showing the 
    // greeting message for a day ()
    setTimeout(() => {
        hideMessage();
        countdownTimer.setExpiredDate(getNewYear());
    }, 1000 * 60 * 24);
};Code language: JavaScript (javascript)

最後に、新しい CountDown インスタンスを作成し、新年の日付、render 関数、および complete 関数をそのコンストラクタに渡します

const countdownTimer = new CountDown(
    getNewYear(),
    render,
    complete
);Code language: JavaScript (javascript)

以下は、完全な app.js ファイルです

// Get the new year 
const getNewYear = () => {
    const currentYear = new Date().getFullYear();
    return new Date(`January 01 ${currentYear + 1} 00:00:00`);
};

// update the year element
const year = document.querySelector('.year');
year.innerHTML = getNewYear().getFullYear();

// select elements
const app = document.querySelector('.countdown-timer');
const message = document.querySelector('.message');
const heading = document.querySelector('h1');


const format = (t) => {
    return t < 10 ? '0' + t : t;
};

const render = (time) => {
    app.innerHTML = `
        <div class="count-down">
            <div class="timer">
                <h2 class="days">${format(time.days)}</h2>
                <small>Days</small>
            </div>
            <div class="timer">
                <h2 class="hours">${format(time.hours)}</h2>
                <small>Hours</small>
            </div>
            <div class="timer">
                <h2 class="minutes">${format(time.minutes)}</h2>
                <small>Minutes</small>
            </div>
            <div class="timer">
                <h2 class="seconds">${format(time.seconds)}</h2>
                <small>Seconds</small>
            </div>
        </div>
        `;
};


const showMessage = () => {
    message.innerHTML = `Happy New Year ${newYear}!`;
    app.innerHTML = '';
    heading.style.display = 'none';
};

const hideMessage = () => {
    message.innerHTML = '';
    heading.style.display = 'block';
};

const complete = () => {
    showMessage();

    // restart the countdown after showing the 
    // greeting message for a day ()
    setTimeout(() => {
        hideMessage();
        countdownTimer.setExpiredDate(getNewYear());
    }, 1000 * 60 * 60 * 24);
};

const countdownTimer = new CountDown(
    getNewYear(),
    render,
    complete
);Code language: JavaScript (javascript)

index.html を開くと、新年のカウントダウンが実行されていることがわかります。

まとめ

このチュートリアルでは、次の方法を学びました

  • ES6クラスを使用して、再利用可能なカウントダウンタイマーコンポーネントを定義する。
  • Date オブジェクトを使用して時間を操作する。
  • setInterval()clearInterval() を使用して、時間指定された繰り返しのアクションを作成およびキャンセルする。
このチュートリアルは役に立ちましたか?