Те, кто занимается спортом, знают: часто нужен таймер. Кому-то надо отмерять интервалы по минуте, кому-то — сколько работаешь, столько отдыхаешь; кому-то нужны сложные интервалы и круги; кому-то просто секундомер. На всё это, конечно, в интернете полно готовых программ, но почему бы не сделать свою?
Если вы пропустили наш первый урок по созданию полноценных программ, где мы рассказываем про инструменты и основные моменты, прочитайте его сейчас. Без этого вам будет сложнее разобраться, что здесь происходит, и что это всё вообще такое.
Как устроен интервальный таймер
Наш сценарий работы такой: пользователь задаёт время одного упражнения и перерыва после него, а потом указывает, сколько раз он хочет выполнить это упражнение с перерывом. Например, стоять в планке на протяжении минуты, потом отдыхать 45 секунд, повторить восемь раз. Получается, что основных параметров у нас три: время тренировки, время отдыха, количество подходов.
Чтобы во время тренировки можно было не смотреть на экран, надо предусмотреть звуковое оповещение. Оно подскажет, что закончился очередной интервал, и нужно отдохнуть или снова приступить к упражнению.
Основа страницы
Возьмём стандартный шаблон страницы:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
Теперь поработаем со служебным разделом <head>..</head>
и наполним его нужными командами:
<!-- Это название страницы, выводится в табе браузера-->
<title>Интервальный таймер</title>
<!-- это служебная информация для браузера, пока можно не вникать -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
Подключаем там же фреймворк jQuery, который упростит нам работу с таймером и его компонентами:
<!-- подключаем фреймворк jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js" type="text/javascript"></script>
Теперь разместим все элементы интерфейса на странице. Начнём с общего блока, где будет наш таймер:
<div class="app_form_block app_main app_timer ">
<!-- внутри этого блока мы и будем размещать все элементы -->
</div>
Теперь будем размещать внутри этого блока интерфейс программы. Сразу подключим звуковые уведомления, за них отвечает тег <audio>
<!-- подключаем звуковые уведомления -->
<audio id="audio_beep">
<source src="s.mp3" type="audio/mp3" >
</audio>
Звук мы взяли где-то из интернета и положили в ту же папку, что и наша программа.
Чтобы мы могли менять время и параметры тренировки, сделаем форму и разместим все наши компоненты на ней.
<!-- делаем форму на сайте, где будем выводить наши элементы -->
<form name="timer_form" id="timer_form">
<!-- тут будут наш таймер и блок с настройками -->
</form>
Для начала поместим на форму специальный заголовок. Его хитрость в том, что он будет невидимой кнопкой, на которую нажмёт скрипт, когда всё загрузится. После такого виртуального нажатия наш таймер получит свои начальные значения и будет готов к работе.
<!-- пишем специальный заголовок страницы -->
<div class="block_row timer_types ">
<span class="timer_types_btn active" id="Secret">Интервальный таймер
</span>
</div>
Тег <span>
— это контейнер, как бы прозрачная обёртка для своего содержимого. С его помощью мы можем отдельно настроить внешний вид и поведение нашего текста. Теперь у нашего заголовка есть внутреннее имя "Secret"
и класс "timer_types_btn"
, который пока ещё нигде не прописан.
На этом этапе у нас будет пустая страница с надписью «Интервальный таймер». Пока что ничего интересного.
Интерфейс
Интерфейс таймера мы упакуем в собственный блок, чтобы можно было настраивать как общий вид, так и части по отдельности. Его мы вставляем в нашу форму после блока с заголовком:
<div class="block_row app_console">
<!-- основной блок со всеми цифрами -->
</div>
Первое, что мы в него добавим — интерфейс настроек тренировки, где можно будет выбрать время и количество повторений. Сначала добавим в него настройку времени на упражнения:
<!-- блок, который отвечает за время тренировки -->
<span class="timer_interval_work">
<!-- по умолчанию ставим время одного подхода 00 минут… -->
<span class="timer_interval_nums minutes green" contenteditable="true">00
</span>
<!-- разделитель — двоеточие -->
<span class="timer_sep">:
</span>
<!-- …и 25 секунд -->
<span class="timer_interval_nums seconds green" contenteditable="true">25
</span>
</span>
Внутри этого блока у нас три раздела: один отвечает за минуты, второй — за двоеточие, третий — за секунды. Свойство contenteditable="true"
означает, что этот контент можно изменять, щёлкая мышкой и вводя свои значения.
Так же добавим блоки количества подходов и времени отдыха:
<!-- блок, который отвечает за количество подходов -->
<span class="timer_interval_count">
<!-- какой сейчас идёт подход -->
<span class="timer_interval_nums times">1
</span>
<!-- разделитель — косая черта -->
<span class="timer_sep">/
</span>
<!-- и сколько подходов у нас всего -->
<span class="timer_interval_nums all_times" contenteditable="true">10
</span>
</span>
<!-- блок, который отвечает за время отдыха -->
<span class="timer_interval_rest">
<!-- по умолчанию ставим время отдыха 0 минут… -->
<span class="timer_interval_nums minutes red" contenteditable="true">00
</span>
<!-- разделитель — двоеточие -->
<span class="timer_sep">:
</span>
<!-- …и 5 секунд -->
<span class="timer_interval_nums seconds red" contenteditable="true">5
</span>
</span>
Вставляем это всё в нашу панель настроек и смотрим, что получилось:
Табло для отсчёта времени и кнопки
Для большого табло используем тот же код, что и для панели настроек, только применим потом другой класс оформления:
<!-- большая цифровая панель -->
<div class="timer_panel_nums">
<!-- минуты… -->
<span class="timer_nums minutes">00</span>
<span>:</span>
<!-- …и секунды -->
<span class="timer_nums seconds">00</span>
</div>
Кнопки сделаем с помощью стандартного тега <input>
. Каждой кнопке присвоим своё имя и идентификатор, чтобы можно было с ними работать из скрипта:
<!-- блок кнопок -->
<div class="block_row">
<!-- Кнопка «Сброс» -->
<input value="Сброс" name="timer_clear" id="timer_clear" class="timer_btn" type="button" />
<!-- Кнопка «Старт» -->
<input value="Старт" name="timer_run" id="timer_run" class="timer_btn run" type="button" />
<!-- Кнопка «Пауза», в самом начале она скрыта -->
<input value="Пауза" name="timer_pause" id="timer_pause" class="timer_btn pause hide" type="button" />
<!-- закончился блок кнопок -->
</div>
Вот наш интерфейс. Ставим его в форму на странице и смотрим на результат:
Настраиваем внешний вид
Очевидно, что таймер наш выглядит скромновато. Нужно его оформить. Для этого используем CSS — стили оформления элементов на странице.
Как вы помните, CSS-стили можно выносить в отдельный файл, а можно писать в разделе <head>
с помощью тега <script>
. Выберем второй способ и определим все стили прямо в этом же документе:
body {
text-align: center;
margin: 10;
font-family: Verdana, Arial, sans-serif;
font-size: 16px;
}
/*настраиваем отступы в полях ввода цифр, там, где задаётся время тренировки, отдыха, и количество повторов*/
.app_form_block input[type="number"] {
padding: 4px 4px;
}
/*задаём отступы у элементов*/
.app_main .block_row {
padding: 1em 0.5em;
}
/*устанавливаем размер цифр для количества повторов, времени тренировки и отдыха */
.app_timer .app_console .timer_panel_info {
font-size: 1.6em;
line-height: 1.2em;
letter-spacing: 0;
}
/*зелёный цвет*/
.green {
color: #bff08e;
}
/*красный цвет*/
.red {
color: #e56655;
}
/*задаём размер таймера*/
.app_timer .app_console .timer_panel_nums {
font-size: 4.8em;
line-height: 1.2em;
margin-top: 50px;
}
/*учим браузер скрывать временно ненужные кнопки*/
.app_timer .timer_btn.hide,
.app_timer .timer_nums.hide,
.app_timer .timer_sep.hide {
display: none;
}
/*задаём размер кнопок*/
.app_timer .timer_btn {
border-color: #777;
color: #777;
font-size: 1.2em;
font-weight: 400;
line-height: 1.8em;
padding: 8px 12px;
margin: 0 2px;
min-width: 180px;
}
/*настраиваем, как изменится цвет кнопки, если провести по ней мышкой*/
.app_timer .timer_btn:hover {
background-color: #777;
color: #fff;
}
/*задаём размер кнопок*/
.app_timer .timer_btn.run,
.app_timer .timer_btn.pause {
border-color: #5594e5;
color: #5594e5;
font-weight: 600;
}
/*настраиваем, как изменится цвет АКТИВНОЙ кнопки, если провести по ней мышкой*/
.app_timer .timer_btn.run:hover,
.app_timer .timer_btn.pause:hover {
background-color: #5594e5;
color: #fff;
}
Сохраняем код, обновляем страницу в браузере:
Класс! Время тренировки у нас выделено зелёным цветом, отдыха — красным. Благодаря этому мы не перепутаем числа. А ещё появилось большое табло отсчёта времени и две кнопки вместо трёх — «Пауза» автоматически исчезла после загрузки.
Собираем скрипт
Пока при нажатии на кнопки ничего не происходит — у нас нет скрипта, который бы это обрабатывал. В прошлый раз мы его писали там же, внутри страницы, теперь давайте вынесем его в отдельный файл. Так будет удобнее читать код: команд уже много, и если туда же добавить скрипт, будет совсем большая простыня текста. Поэтому создадим отдельный файл interval_timer_script.js
и подключим его на нашей странице с таймером такой командой:
<!-- подключаем наш код, который отвечает за правильную работу таймера -->
<script type="text/javascript" src="interval_timer_script.js" defer></script>
Смотрите, у нас появилась новая команда в теге скрипта: defer
. Она запрещает скрипту выполняться, пока страница полностью не загрузится. Это позволяет нам сначала подготовить страницу целиком, а только потом запускать таймер.
interval_timer_script.js
, но название у него может быть каким угодно, лишь бы из английских букв, цифр и без пробелов. Расширение .js
должно остаться таким же в любом случае. Меняете имя файла — не забудьте прописать его название в src="….js"
, чтобы страница знала, как называется нужный скрипт.Теперь наполним наш скрипт. Начнём с переменных:
// переменная, которая отслеживает, сколько секунд прошло
var now_seconds = 0;
// var now_times = 0;
// тренировка начинается с отсчёта рабочего времени, сразу ставим этот режим
var interval_type = 'work';
// переменная для отсчёта интервалов
var intervalVariable;
// переменная, которая следит за количеством секунд в таймерах
var seconds_1 = 0;
// ставим начальные значения счётчиков минут и секунд
var timer_minutes = 0;
var timer_seconds = 0;
Теперь напишем функцию, которая будет постоянно готовить к запуску наше звуковое оповещение. Она будет брать нужные нам файлы ogg и mp3 и подключать их к нашей странице:
// подготовка звукового оповещения
function audio_change() {
// находим аудиоэлемент на странице
var audio = $('#audio_beep');
// подключаем нужный файл со звуком. Файлов два, потому что разные браузеры играют разные форматы
$('#audio_beep source[type="audio/ogg"]').attr('src', 's.ogg');
$('#audio_beep source[type="audio/mp3"]').attr('src', 's.mp3');
// ставим звук на паузу и подгружаем его
audio[0].pause();
audio[0].load();
}
Перед тем, как работать с таймером и интервалами, давайте напишем маленькую функцию, которая переводит наше время из просто секунд в секунды, минуты и часы. Мало ли, вдруг кто-то фанат долгих упражнений:
// разбиваем секунды на часы, минуты и секунды
function secondsToTime(seconds) {
var h = parseInt(seconds / 3600 % 24);
var m = parseInt(seconds / 60 % 60);
var s = parseInt(seconds % 60);
return { 'hours': leadZero(parseInt(h)), 'minutes': leadZero(parseInt(m)), 'seconds': leadZero(parseInt(s)) };
}
Ну и добавим эстетики в программу — для красоты будем ставить первым ноль, если число минут или секунд меньше девяти:
function leadZero(num) {
var s = "" + num;
if (s.length < 2) {
s = "0" + s;
}
return s;
}
Отдельной функцией сделаем отображение времени на табло. Там как раз и пригодится наша функция, которая переводит секунды в минуты:
// отображение времени на табло
function renderTimerNums(seconds) {
var timer_nums = secondsToTime(seconds)
$('.timer_nums.minutes').text(timer_nums.minutes);
$('.timer_nums.seconds').text(timer_nums.seconds);
}
Теперь предусмотрим смену времени каждую секунду, пока работает таймер. Для этого будем отдельно обрабатывать два режима: тренировки и отдыха. Не забудем про красоту — время тренировки сделаем зелёным, как на панели настроек, а время отдыха — красным:
// функция, которая отвечает за смену времени на таймере
function timerTick(type, timer_params) {
// увеличиваем количество прошедших секунд на единицу
now_seconds++;
// если идёт время тренировки
if (interval_type == 'work') {
// и ещё осталось время на тренировку
if (timer_params.time_work - now_seconds > 0) {
// показываем, сколько осталось времени
renderTimerNums(timer_params.time_work - now_seconds);
}
// иначе, если тренировка закончилась
else {
// обнуляем табло
renderTimerNums(0);
// проигрываем звук уведомления
$('#audio_beep')[0].play();
// обнуляем секунды тренировки
now_seconds = 0;
// ставим режим «Отдых»
interval_type = 'rest';
// меняем цвет цифр на таймере
$('.timer_panel_nums .timer_nums').removeClass('green');
$('.timer_panel_nums .timer_nums').addClass('red');
}
}
// если началось время отдыха
else if (interval_type == 'rest') {
// и оно ещё не закончилось
if (timer_params.time_rest - now_seconds > 0) {
// показываем оставшееся время
renderTimerNums(timer_params.time_rest - now_seconds);
}
// а если всё-таки время отдыха закончилось
else {
// обнуляем табло
renderTimerNums(0);
// проигрываем звук уведомления
$('#audio_beep')[0].play();
// обнуляем секунды
now_seconds = 0;
// увеличиваем счётчик повторов на единицу
now_times++;
// если мы выполнили все повторы
if (now_times > timer_params.interval_count) {
// обновляем информацию на панели настроек
$('.timer_interval_nums.times').text(timer_params.interval_count);
$('#timer_pause').trigger('click');
now_seconds = 0;
$('.timer_panel_nums .timer_nums').removeClass('red');
}
// иначе, если количество пройденных повторов меньше, чем было задано
else {
// обновляем информацию на панели настроек
$('.timer_interval_nums.times').text(now_times);
$('.timer_panel_nums .timer_nums').removeClass('red');
$('.timer_panel_nums .timer_nums').addClass('green');
}
// ставим после отдыха снова режим тренировки
interval_type = 'work';
}
}
}
Продолжение скрипта: обрабатываем нажатия на кнопки
Начнём с кнопки «Старт». Логика работы такая: следим за тем, в каком режиме работает таймер, не забывая скрывать «Старт» и показывать «Паузу» после запуска. Как только перешли к отдыху или снова к тренировке — включаем звуковой сигнал. Если все тренировки прошли, но мы снова нажали «Старт», начнём всё сначала:
// обрабатываем нажатие на кнопку «Старт»
$('#timer_run').click(function () {
// настраиваем аудио
audio_change();
// делаем кнопку «Старт» невидимой
$(this).addClass('hide');
// а кнопку «Пауза», наоборот, видимой
$('#timer_pause').removeClass('hide');
// записываем установленные минуты и секунды
timer_minutes = $('.timer_nums.minutes').text();
timer_seconds = $('.timer_nums.seconds').text();
// переменная, которая будет хранить параметры интервального цикла
var timer_params = {};
// запускаем звуковое оповещение
$('#audio_beep')[0].play();
// устанавливаем размер тренировки...
timer_params.time_work = $('.timer_interval_work .minutes').text() * 60 + $('.timer_interval_work .seconds').text() * 1;
// ...отдыха,
timer_params.time_rest = $('.timer_interval_rest .minutes').text() * 60 + $('.timer_interval_rest .seconds').text() * 1;
// ...и количество повторений
timer_params.interval_count = $('.timer_interval_count .all_times').text() * 1;
// обновляем информацию о том, сколько подходов уже сделано
now_times = $('.timer_interval_count .times').text() * 1;
// если все тренировки прошли — начнём сначала
if (now_times >= timer_params.interval_count) {
now_times = 1;
$('.timer_interval_count .times').text(now_times);
}
// если сейчас режим тренировки, то делаем табло зелёным и запоминаем количество секунд
if (interval_type == 'work') {
$('.timer_panel_nums .timer_nums').addClass('green');
seconds_1 = timer_params.time_work;
}
// если сейчас режим отдыха, то делаем табло красным и запоминаем количество секунд
else if (interval_type = 'rest') {
$('.timer_panel_nums .timer_nums').addClass('red');
seconds_1 = timer_params.time_rest;
}
// задаём интервал обновления — одна секунда
intervalVariable = setInterval(timerTick, 1000, 'interval', timer_params);
// выходим из функции
return false;
});
Теперь очередь кнопки «Пауза». Она появляется в тот момент, когда мы нажимаем на кнопку «Старт», которая сразу исчезает. Логика чуть другая: при каждом нажатии мы просто останавливаем интервал и тоже включаем звук, чтобы обозначить смену режима:
// что будет, если мы нажмём на кнопку «Пауза»
$('#timer_pause').click(function (event, params) {
// если кнопка сработала нормально
if (params !== undefined) {
// но аудиопараметры ещё не задавались
if (params.audio === undefined) {
// задаём параметры оповещения
params.audio = 1;
}
}
// иначе сразу задаём параметры звука
else {
params = { audio: 1 };
}
// после нажатия на кнопку «Пауза» делаем её невидимой
$(this).addClass('hide');
// а кнопку «Старт» — наоборот, видимой
$('#timer_run').removeClass('hide');
// останавливаем таймер
clearInterval(intervalVariable);
// если со звуком всё в порядке
if (params.audio) {
// проигрываем звуковое оповещение
$('#audio_beep')[0].play();
}
// выходим из функции
return false;
});
Последнее, что осталось — запрограммировать реакцию на нажатие кнопки «Сброс». Порядок действий будет такой: виртуально щёлкаем по кнопке «Пауза», обнуляем табло, и выставляем стартовые значения по умолчанию в нашу панель настроек:
// что будет, если нажмём на кнопку «Сброс»
$('#timer_clear').click(function () {
// имитируем нажатие на кнопку «Пауза», чтобы остановить таймер
$('#timer_pause').trigger('click', { audio: 0 });
// ставим режим тренировки
interval_type = 'work';
// убираем красный цвет на табло, которое там осталось от включения паузы
$('.timer_panel_nums .timer_nums').removeClass('green red');
// обнуляем табло
renderTimerNums(0);
// обнуляем значения служебных переменных
now_seconds = 0;
now_times = 0;
// задаём начальное значение первого блока секунд
seconds_1 = 25;
// устанавливаем начальные значения времени тренировки, отдыха и количества повторов
$('.timer_interval_work .minutes').text('00');
$('.timer_interval_work .seconds').text('25');
$('.timer_interval_rest .minutes').text('00');
$('.timer_interval_rest .seconds').text('05');
$('.timer_interval_count .times').text('1');
$('.timer_interval_count .all_times').text('10');
// выходим из функции
return false;
});
Теперь собираем скрипт в один файл, сохраняем, обновляем нашу страницу и нажимаем на «Старт». Всё, успех — таймер начал отсчёт:
Если у вас не получилось всё правильно собрать в один файл и запустить — ничего страшного. Мы сами уже сделали это за вас и упаковали все нужные файлы в один архив. Вам нужно его скачать, распаковать и запустить файл int.html.