В этом руководстве вы узнаете, как разработать и создать многоразовый таймер обратного отсчета в JavaScript с нуля.
Что такое таймер обратного отсчета
Таймер обратного отсчета — это виртуальные часы, работающие на целевой странице. И он ведет обратный отсчет от определенной даты, чтобы указать начало (или конец) события.
На веб-сайтах электронной коммерции вы можете использовать таймер обратного отсчета, чтобы отобразить начало (или конец) предложения. Цель таймера — побудить клиентов совершить такие действия, как покупка товаров или услуг.
В этом руководстве вы узнаете, как создать и использовать таймер обратного отсчета в JavaScript с нуля.
Обратите внимание, что таймер обратного отсчета, который вы собираетесь создать, можно использовать повторно, поэтому вы можете использовать его на любой целевой странице. Кроме того, вы можете использовать для создания нескольких таймеров на одной странице.
Создание структуры проекта
Сначала создайте папку проекта с именем countdown-timer
. Внутри этой папки создайте три подпапки: js
, css
и img
, в которых будут храниться файлы JavaScript, CSS и изображения.
Во-вторых, создайте style.css
в папке css
, app.js
и countdown.js
в папке js
и index.html
в папке countdown-timer
:
В-третьих, скачайте эту картинку фейерверка и скопируйте ее в папку img
. Вы будете использовать это изображение в качестве фона страницы обратного отсчета до Нового года.
Структура проекта будет выглядеть так:
Создание HTML-страницы
HTML-страница довольно проста, потому что вы будете генерировать большую часть HTML-кода из JavaScript.
Ниже показана полная 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>
В файле index.html
вы размещаете ссылку на файл style.css
в разделе <head>
и файлы countdown.js
и app.js
в разделе <body>
.
Обратите внимание, что файл countdown.js
должен располагаться перед файлом app.js
, потому что app.js
будет использовать объекты из файла countdown.js
.
Раздел <body>
состоит из четырех элементов:
- Заголовок 1(
<h1>
). Этот элемент покажет заголовок. Это может быть все, что описывает обратный отсчет, например, обратный отсчет до Нового года. <div>
сcountdown-timer
класса. Этот элемент будет отображать обратный отсчет.<div>
с классомmessage
. Этот элемент будет отображать сообщение, когда обратный отсчет завершится.- И
<div>
с классомyear
. Этот элемент покажет Новый год, например, 2021.
Краткий обзор объекта Date
Чтобы создать таймер, вам нужно будет работать с объектом Date
, который доступен во всех веб-браузерах.
Объект Date
представляет один момент времени. Он содержит число, представляющее миллисекунды с 1 января 1970 года по всемирному координированному времени.
Ниже показано, как создать новый объект Date
, представляющий текущую дату и время:
const now = new Date();
В этом примере показано, как вызвать метод getTime()
объекта Date
, чтобы получить количество миллисекунд с January 1, 1970 00:00:00 UTC
:
const time = now.getTime(); console.log(time);
Чтобы создать новый объект Date
с указанной датой и временем, вы можете передать строку даты в конструктор Date()
следующим образом:
const d = new Date('February 02, 2020 01:02:03'); console.log(d.getTime()); // 1580580123000
Чтобы вычислить количество миллисекунд между двумя временами, вы вызываете метод 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); // 176400000
Расчет оставшегося времени
Таймер обратного отсчета должен будет рассчитать оставшиеся дни, часы, минуты и секунды из нескольких миллисекунд и отобразить эту информацию на веб-странице.
Следующий код объявляет переменную времени со значением 150000 миллисекунд:
const time = 150000; // ms
Чтобы преобразовать миллисекунды в минуты, вы делите миллисекунды на 1000, чтобы получить секунды, и делите секунды на 60, чтобы получить минуты. Например:
console.log(time / 1000 / 60);
Выход:
2.5
Чтобы получить оставшиеся минуты(2), вы используете функцию Math.floor()
:
const minutes = Math.floor(time / 1000 / 60); console.log(minutes); // 2
Чтобы получить оставшиеся секунды(30), вы используете оператор модуля( % ), который возвращает остаток от деления:
const seconds = Math.floor(time / 1000) % 60; console.log(seconds); // 30
Разработка класса обратного отсчета
Сначала создайте новый класс CountDown
в файле countdown.js
:
class CountDown { }
Класс CountDown
должен быть инициализирован тремя аргументами:
- просроченная дата.
- обратный вызов, отвечающий за рендеринг таймера обратного отсчета.
- и еще один обратный вызов, который будет вызван после завершения отсчета.
Конструктор класса будет выглядеть так:
class CountDown { constructor(expiredDate, onRender, onComplete) { this.onRender = onRender; this.onComplete = onComplete; // handle the expired Date .. } }
Основываясь на аргументе expiredDate
, вы можете рассчитать оставшееся время в миллисекундах:
const currentTime = new Date().getTime(); const timeRemaining = expiredDate.getTime() - currentTime;
Поскольку вам потребуется доступ к оставшемуся времени( timeRemaining
) в методах класса, вы должны определить его как свойство класса CountDown
.
Метод setExpiredDate()
Ниже определяется новый метод setExpiredDate()
, который инициализирует свойство timeRemaining
:
setExpiredDate(expiredDate) { // get the current time const currentTime = new Date().getTime(); // calculate the remaining time this.timeRemaining = expiredDate.getTime() - currentTime; }
Если 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(); }
Обратите внимание, что мы используем тернарный оператор ?:
для выполнения метода complete()
или start()
на основе значения свойства this.timeRemaining
.
Метод complete()
Метод complete()
проверяет, передан ли обратный вызов onComplete
, и вызывает его. Если onComplete
недоступен, complete()
ничего не сделает.
complete() { if(typeof this.onComplete === 'function') { onComplete(); } }
Функция 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); }
Если оставшееся время больше нуля, метод 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 }; }
Метод update()
Далее определяется метод update()
, который вызывает обратный вызов onRender()
с текущим оставшимся объектом времени, возвращаемым методом getTime()
:
update() { if(typeof this.onRender === 'function') { this.onRender(this.getTime()); } }
Метод 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); }
Ниже показан полный класс 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); } }
Обратный отсчет до Нового года
Во-первых, создайте новую функцию с именем getNewYear()
, которая возвращает новый год:
const getNewYear =() => { const currentYear = new Date().getFullYear(); return new Date(`January 01 ${currentYear + 1} 00:00:00`); };
Во-вторых, выберите и обновите элемент .year
. Он покажет четырехзначный номер нового года, например, 2021:
// update the year element const year = document.querySelector('.year'); year.innerHTML = getNewYear().getFullYear();
В-третьих, выберите .countdown-timer
, .message
и h1
:
// select elements const app = document.querySelector('.countdown-timer'); const message = document.querySelector('.message'); const heading = document.querySelector('h1');
В-четвертых, определите функцию формата, которая дополняет число, если оно меньше 10. Например, 5 будет равно 05
. Но 10 останется прежним.
const format =(t) => { return t < 10 ? '0' + t : t; };
В-пятых, определите метод render()
, который составляет HTML-разметку из объекта времени и обновляет ее до элемента .countdown-timer
. Он покажет оставшиеся дни, часы, минуты и секунды.
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> `; };
Когда обратный отсчет завершается, отображается сообщение, например, "Happy New Year"
.
Следующая showMessage()
отображает сообщение « Happy New Year
. Кроме того, он очищает содержимое элемента .countdown-timer
и скрывает элемент заголовка:
const showMessage =() => { message.innerHTML = `Happy New Year ${newYear}!`; app.innerHTML = ''; heading.style.display = 'none'; };
В-шестых, обратный отсчет до Нового года должен отображать приветственное сообщение с Новым годом в течение определенного периода времени, а затем снова отображать обратный отсчет до Нового года.
Следующий код определяет функцию, которая скрывает приветственное сообщение и показывает элемент заголовка:
const hideMessage =() => { message.innerHTML = ''; heading.style.display = 'block'; }
В-седьмых, определите функцию complete()
, которая показывает сообщение в течение определенного периода времени, а затем скрывает его. Кроме того, она устанавливает expiredDate
на Новый год:
const complete =() => { showMessage(); // restart the countdown after showing the // greeting message for a day() setTimeout(() => { hideMessage(); countdownTimer.setExpiredDate(getNewYear()); }, 1000 * 60 * 24); };
Наконец, создайте новый экземпляр CountDown
и передайте дату Нового года, функцию render
и функцию complete
в его конструктор:
const countdownTimer = new CountDown( getNewYear(), render, complete );
Ниже показан полный файл 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 );
Если вы откроете index.html
, вы увидите, что обратный отсчет до Нового года уже запущен.
Заключение
В этом уроке вы узнали, как:
- Использовать класс ES6, чтобы определить повторно используемый компонент таймера обратного отсчета.
- Пользоваться объектом
Date
для управления временем. - Использовать setInterval() и clearInterval() для создания и отмены повторяющегося действия по времени.