Как написать таймер обратного отсчета в JavaScript?

Просто хотел спросить, как сделать самый простой таймер обратного отсчета.

На сайте будет фраза:

«Регистрация закрывается через 05:00 минут!»

Итак, что я хочу сделать, так это создать простой таймер обратного отсчета js, который идет от «05:00» до «00:00», а затем сбрасывается на «05:00» по окончании.

Я уже задавал некоторые ответы раньше, но все они кажутся слишком важными (объекты даты и т. Д.) Для того, что я хочу сделать.


person Bartek    schedule 16.12.2013    source источник
comment
И снова вы упускаете соответствующий HTML-код, хотя, по крайней мере, на этот раз вы как бы объяснили проблему сложности. А если серьезно, вам нужно самому найти решение, а затем затем прийти и спросить нас о проблемах, с которыми вы столкнулись.   -  person David says reinstate Monica    schedule 16.12.2013
comment
Примеры кода с жалобами на то, насколько они слишком сложные? В любом случае, я думаю, вы могли бы легко setInterval и сделать его на основе .innerHTML, а не на основе даты.   -  person bjb568    schedule 16.12.2013
comment
Да, люди должны искать решение самостоятельно. Но с javaScript есть множество примеров выполнения общих задач. Я знаю, как сделать таймер обратного отсчета, но предпочитаю, если найду его в сети (например, компонент). Итак, благодаря этому вопросу и подробному ответу я нашел то, что искал. Логика обратного отсчета   -  person Carlos Rafael Ramirez    schedule 07.04.2015
comment
Я нашел эти решения более простыми: stackoverflow.com/questions/32141035/   -  person nu everest    schedule 26.08.2016
comment
Посмотрите это: sitepoint.com/build-javascript-countdown-timer- без зависимостей   -  person Erich García    schedule 16.01.2017


Ответы (3)


У меня есть две демонстрации, одна с jQuery, а другая без. Ни один из них не использует функции даты и настолько прост, насколько это возможно.

Демонстрация с использованием ванильного JavaScript

function startTimer(duration, display) {
    var timer = duration, minutes, seconds;
    setInterval(function () {
        minutes = parseInt(timer / 60, 10);
        seconds = parseInt(timer % 60, 10);

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.textContent = minutes + ":" + seconds;

        if (--timer < 0) {
            timer = duration;
        }
    }, 1000);
}

window.onload = function () {
    var fiveMinutes = 60 * 5,
        display = document.querySelector('#time');
    startTimer(fiveMinutes, display);
};
<body>
    <div>Registration closes in <span id="time">05:00</span> minutes!</div>
</body>

Демонстрация с jQuery

function startTimer(duration, display) {
    var timer = duration, minutes, seconds;
    setInterval(function () {
        minutes = parseInt(timer / 60, 10);
        seconds = parseInt(timer % 60, 10);

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.text(minutes + ":" + seconds);

        if (--timer < 0) {
            timer = duration;
        }
    }, 1000);
}

jQuery(function ($) {
    var fiveMinutes = 60 * 5,
        display = $('#time');
    startTimer(fiveMinutes, display);
});

Однако, если вам нужен более точный таймер, это немного сложнее:

function startTimer(duration, display) {
    var start = Date.now(),
        diff,
        minutes,
        seconds;
    function timer() {
        // get the number of seconds that have elapsed since 
        // startTimer() was called
        diff = duration - (((Date.now() - start) / 1000) | 0);

        // does the same job as parseInt truncates the float
        minutes = (diff / 60) | 0;
        seconds = (diff % 60) | 0;

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.textContent = minutes + ":" + seconds; 

        if (diff <= 0) {
            // add one second so that the count down starts at the full duration
            // example 05:00 not 04:59
            start = Date.now() + 1000;
        }
    };
    // we don't want to wait a full second before the timer starts
    timer();
    setInterval(timer, 1000);
}

window.onload = function () {
    var fiveMinutes = 60 * 5,
        display = document.querySelector('#time');
    startTimer(fiveMinutes, display);
};
<body>
    <div>Registration closes in <span id="time"></span> minutes!</div>
</body>

Теперь, когда мы сделали несколько довольно простых таймеров, мы можем начать думать о повторном использовании и разделении проблем. Мы можем сделать это, задав вопрос: «Что должен делать таймер обратного отсчета?»

  • Должен ли таймер обратного отсчета вести обратный отсчет? Да
  • Должен ли таймер обратного отсчета знать, как отображать себя в DOM? Нет
  • Должен ли таймер обратного отсчета знать, что он перезапустится, когда он достигнет 0? Нет
  • Должен ли таймер обратного отсчета предоставлять клиенту возможность узнать, сколько времени осталось? Да

Помня об этом, давайте напишем лучший (но все же очень простой) CountDownTimer

function CountDownTimer(duration, granularity) {
  this.duration = duration;
  this.granularity = granularity || 1000;
  this.tickFtns = [];
  this.running = false;
}

CountDownTimer.prototype.start = function() {
  if (this.running) {
    return;
  }
  this.running = true;
  var start = Date.now(),
      that = this,
      diff, obj;

  (function timer() {
    diff = that.duration - (((Date.now() - start) / 1000) | 0);

    if (diff > 0) {
      setTimeout(timer, that.granularity);
    } else {
      diff = 0;
      that.running = false;
    }

    obj = CountDownTimer.parse(diff);
    that.tickFtns.forEach(function(ftn) {
      ftn.call(this, obj.minutes, obj.seconds);
    }, that);
  }());
};

CountDownTimer.prototype.onTick = function(ftn) {
  if (typeof ftn === 'function') {
    this.tickFtns.push(ftn);
  }
  return this;
};

CountDownTimer.prototype.expired = function() {
  return !this.running;
};

CountDownTimer.parse = function(seconds) {
  return {
    'minutes': (seconds / 60) | 0,
    'seconds': (seconds % 60) | 0
  };
};

Так почему эта реализация лучше других? Вот несколько примеров того, что с ним можно делать. Обратите внимание, что все, кроме первого примера, не могут быть реализованы с помощью startTimer функций.

Пример, который отображает время в формате XX: XX и перезапускается после достижения 00:00

Пример, отображающий время в двух разных форматах

Пример с двумя разными таймерами и только один перезапускается

Пример, запускающий таймер обратного отсчета при нажатии кнопки

person robbmj    schedule 16.12.2013
comment
Ты мужчина! Это именно то, что я искал. Спасибо! Еще одна вещь: как я могу добавить 0 перед минутами, чтобы показывалось 04:59 вместо 4:59? - person Bartek; 16.12.2013
comment
В самой первой демонстрации с Vanilla JavaScript, что за переменная является таймером? Ничего подобного я еще не видел! А как его установить, когда еще не определены минуты и секунды? - person timbram; 29.06.2015
comment
@timbram timer, изначально это просто копия параметра duration, и это просто число. Причина, по которой это необходимо, состоит в том, чтобы отслеживать оставшееся время, что невозможно сделать с параметром duration, поскольку таймер необходимо сбросить, когда он достигнет 0. minutes и seconds рассчитываются на основе значения timer. Надеюсь это поможет. - person robbmj; 01.07.2015
comment
@timbram мне тоже сначала показалось странным, пока я не понял, что запятая после объявления var разделяет разные объявления. поэтому minutes и seconds просто объявленные (но неинициализированные) переменные. так что timer просто равно параметру duration, ни больше, ни меньше. - person abustamam; 16.07.2015
comment
Спасибо! Как лучше всего добавить функцию паузы / возобновления в последний скрипт? - person Sinan Erdem; 29.03.2016
comment
@SinanErdem Я написал код, который это делает. Я могу добавить этот код к ответу сегодня же. Я свяжусь с тобой, когда это будет сделано. - person robbmj; 29.03.2016
comment
Есть ли способ узнать текущее значение таймера или сколько времени прошло с его запуска? Я мог бы проанализировать значение html, но это немного глупо, когда есть реальное значение! - person Savvas Parastatidis; 12.04.2016
comment
Как вызвать функцию, когда таймер станет 00:00 ??? - person Sangamesh Davey; 16.06.2016
comment
Есть ли способ остановить демо-версию js от сброса, когда она достигнет 0? - person Santosh Pillai; 15.07.2016
comment
остановил его сброс с помощью if (--timer ‹0) {timer = 0; } - person Santosh Pillai; 15.07.2016
comment
Как добавить параметры сброса? А еще пауза и возобновление? Я попытался добавить поле this.reset и проверить это в закрытии. Но часы продолжают идти. - person Dzung Nguyen; 19.08.2016
comment
(diff / 60) | 0; - что здесь |? Как это называется? - person Edgar; 15.09.2016
comment
Я нашел этот ответ: stackoverflow.com/questions/7487977/. То, что я искал. - person Edgar; 15.09.2016
comment
@ Эдгар Ага, вот что он делает. - person robbmj; 15.09.2016
comment
@robbmj Привет, отличный пост. Спасибо. Вы когда-нибудь реализовывали функцию паузы? Могу действительно использовать это в одном из проектов, над которыми я работаю. - person Ricky Mason; 24.02.2017
comment
Чем точнее вторая версия? - person BornToCode; 01.09.2017
comment
@BornToCode Использование объекта Date для точного расчета оставшегося или прошедшего времени необходимо, поскольку setInterval и setTimeout не могут гарантировать, что они будут вызваны ровно через n миллисекунды. - person robbmj; 01.09.2017
comment
кто-нибудь знает, как добавить ike еще через 2 минуты после того, как он остановится на 0? - person shikiko; 12.01.2018
comment
@robbmj Мне очень нравится ваше решение ... первое, ванильное :) Если у вас есть минутка, не могли бы вы показать мне, как вы бы добавить кнопку сброса в это решение. Я имею в виду кнопку, которая НЕ останавливает таймер ... просто сбросьте его на 5:00 ... чтобы он автоматически перешел на 4:59 ... 4:58 ... и т. Д. - person Mike Pala; 26.01.2018
comment
Ответ неверен из-за использования setTimeout / Interval, поскольку он не срабатывает точно. - person epascarello; 09.02.2018
comment
@epascarello, пожалуйста, посмотрите последний раздел, чтобы узнать о более точном таймере, который учитывает неточность setTimeout и setInterval. - person robbmj; 10.02.2018
comment
в коде jquery есть ошибка: displayId.text (minutes +: + seconds); Правильный способ: displayId.html (минуты +: + секунды); - person Zoltán Süle; 01.08.2018
comment
@ ZoltánSüle Мне, вероятно, следует обновить ответ, чтобы обычный JS также использовал innerHTML. - person robbmj; 01.08.2018
comment
@robbmj Я ошибался. В этом случае нет реальной разницы между функциями text () и html (). - person Zoltán Süle; 01.08.2018
comment
@ ZoltánSüle не беспокойтесь, лучше указать на что-то и ошибиться, а затем позволить потенциальной ошибке проскользнуть. - person robbmj; 02.08.2018
comment
Как остановить таймер после нажатия кнопки ... и снова запустить его после следующего нажатия? - person Mostafa; 14.10.2018
comment
отличный таймер, одно предложение - сделать что-то вроде var objMyInterval = setInterval (function timer () {... теперь, чтобы остановить таймер через минут ‹= 0 & seconds‹ = 0, просто вызовите clearInterval (objMyInterval); - person Melu; 15.02.2019
comment
Как бы вы сделали простой пример, отображающий часы? - person V1xIII; 13.05.2020
comment
@ V1xIII Это должно делать то, что вы хотите: jsfiddle.net/ejdcwmuy - person robbmj; 19.05.2020
comment
хотя мне это не кажется simplest - person Shiz; 25.08.2020
comment
Если я хочу включить Hours, чтобы иметь вывод для отображения общего вывода Hrs: Mins: Sec, как мне изменить этот код? - person LeCoda; 18.05.2021

Если вам нужен настоящий таймер, вам нужно использовать объект даты.

Посчитайте разницу.

Отформатируйте вашу строку.

window.onload=function(){
      var start=Date.now(),r=document.getElementById('r');
      (function f(){
      var diff=Date.now()-start,ns=(((3e5-diff)/1e3)>>0),m=(ns/60)>>0,s=ns-m*60;
      r.textContent="Registration closes in "+m+':'+((''+s).length>1?'':'0')+s;
      if(diff>3e5){
         start=Date.now()
      }
      setTimeout(f,1e3);
      })();
}

Пример

Jsfiddle

не очень точный таймер

var time=5*60,r=document.getElementById('r'),tmp=time;

setInterval(function(){
    var c=tmp--,m=(c/60)>>0,s=(c-m*60)+'';
    r.textContent='Registration closes in '+m+':'+(s.length>1?'':'0')+s
    tmp!=0||(tmp=time);
},1000);

JsFiddle

person cocco    schedule 16.12.2013

Вы можете легко создать функцию таймера, используя setInterval. Ниже приведен код, который вы можете использовать для создания таймера.

http://jsfiddle.net/ayyadurai/GXzhZ/1/

window.onload = function() {
  var minute = 5;
  var sec = 60;
  setInterval(function() {
    document.getElementById("timer").innerHTML = minute + " : " + sec;
    sec--;
    if (sec == 00) {
      minute --;
      sec = 60;
      if (minute == 0) {
        minute = 5;
      }
    }
  }, 1000);
}
Registration closes in <span id="timer">05:00<span> minutes!

person Durai    schedule 16.12.2013
comment
Неточно отображает каждую секунду, отсчет идет слишком быстро. - person Scott Rowley; 21.11.2017
comment
Изменение 500 на 1000 кажется точным. - person Scott Rowley; 21.11.2017
comment
Гладкое решение, час следует изменить на минуту, чтобы избежать путаницы. - person embulldogs99; 27.05.2020