Таймер отсчета времени на jQuery

12-10-21 JavaScript 29

В этом уроке мы сделаем таймер обратного отсчета времени с помощью jQuery.

Сегодня мы создадим анимированный таймер, который будет считать дни, часы, секунды до определенного события и обновляться каждую секунду. Начнем с html разметки нашего таймера.

HTML

Следующий html код будет генерировать jQuery, вам не придется прописывать его вручную, надо только выбрать элемент в который он будет вставлен. В нашем случае это #countdown.

<div id="countdown">
	<span>
		<span>
			<span></span>
		</span>
		<span>
			<span></span>
		</span>
	</span>

	<span></span>

	<span>
		<span>
			<span></span>
		</span>
		<span>
			<span></span>
		</span>
	</span>

	<span></span>

	<span>
		<span>
			<span></span>
		</span>
		<span>
			<span></span>
		</span>
	</span>

	<span></span>

	<span>
		<span>
			<span></span>
		</span>
		<span>
			<span></span>
		</span>
	</span>

	<span></span>
</div>

Так же к нашему элементу будет добавлен класс countdownHolder. Для каждой временной единицы отведено 2 места для цифр, т.о. максимальное количество времени для отсчета — 99 дней.

jQuery

Сначала опишем две вспомогательные функции: init() — будет генерировать разметку нашего таймера и switchDigit() — будет принимать элемент .position и анимировать цифру.

function init(elem, options){
	elem.addClass('countdownHolder');

	// создаем разметку
	$.each(['Days','Hours','Minutes','Seconds'],function(i){
		$('<span>').html(
			'<span>\
				<span>0</span>\
			</span>\
			<span>\
				<span>0</span>\
			</span>'
		).appendTo(elem);

		if(this!="Seconds"){
			elem.append('<span></span>');
		}
	});

}

// анимирует переход от одной цифры к другой
function switchDigit(position,number){

	var digit = position.find('.digit')

	if(digit.is(':animated')){
		return false;
	}

	if(position.data('digit') == number){
		// эта цифра уже показана
		return false;
	}

	position.data('digit', number);

	var replacement = $('<div>',{
		'class':'digit',
		css:{
			top:'-2.1em',
			opacity:0
		},
		html:number
	});

	// класс .static добавляется, когда анимация завершена

	digit
		.before(replacement)
		.removeClass('static')
		.animate({top:'2.5em',opacity:0},'fast',function(){
			digit.remove();
		})

	replacement
		.delay(100)
		.animate({top:0,opacity:1},'fast',function(){
			replacement.addClass('static');
		});
}

Теперь напишем основную часть плагина:

(function($){

	// Количество секунд в каждой единице времени
	var days	= 24*60*60,
		hours	= 60*60,
		minutes	= 60;

	$.fn.countdown = function(prop){

		var options = $.extend({
			callback	: function(){},
			timestamp	: 0
		},prop);

		var left, d, h, m, s, positions;

		// инициализация
		init(this, options);

		positions = this.find('.position');

		(function tick(){

			// осталось времени
			left = Math.floor((options.timestamp - (new Date())) / 1000);

			if(left < 0){
				left = 0;
			}

			// осталось дней
			d = Math.floor(left / days);
			updateDuo(0, 1, d);
			left -= d*days;

			// часов
			h = Math.floor(left / hours);
			updateDuo(2, 3, h);
			left -= h*hours;

			// минут
			m = Math.floor(left / minutes);
			updateDuo(4, 5, m);
			left -= m*minutes;

			// секунд
			s = left;
			updateDuo(6, 7, s);

			options.callback(d, h, m, s);

			setTimeout(tick, 1000);
		})();

		// обновление двух цифр одновременно
		function updateDuo(minor,major,value){
			switchDigit(positions.eq(minor),Math.floor(value/10)%10);
			switchDigit(positions.eq(major),value%10);
		}

		return this;
	};

	/* две функции объявленные ранее */
})(jQuery);

Функция tick вызывается каждую секунду. Она вычисляет разницу между текущим временем и заданным. Наш плагин готов! Применим его:

$(function(){

	var note = $('#note'),
		ts = new Date(2012, 0, 1),
		newYear = true;

	if((new Date()) > ts){
		// *1000 - время должно быть в миллисекундах
		ts = (new Date()).getTime() + 10*24*60*60*1000;
		newYear = false;
	}

	$('#countdown').countdown({
		timestamp	: ts,
		callback	: function(days, hours, minutes, seconds){

			var message = "";

			message += days + " day" + ( days==1 ? '':'s' ) + ", ";
			message += hours + " hour" + ( hours==1 ? '':'s' ) + ", ";
			message += minutes + " minute" + ( minutes==1 ? '':'s' ) + " and ";
			message += seconds + " second" + ( seconds==1 ? '':'s' ) + " <br />";

			if(newYear){
				message += "left until the new year!";
			}
			else {
				message += "left to 10 days from now!";
			}

			note.html(message);
		}
	});

});

Наш таймер готов! Преимущество данного таймера в том, что он сделан без картинок — на чистом CSS. Изменяя размер шрифта — вы можете изменять размер счетчика. Если вы не хотите отображать какую либо временную единицу (например — дни), достаточно добавить display:none в CSS.

Хочешь получать статьи на почту?

Подпишись на обновления!
* Ваш email не будет разглашен/продан. Вы сможете отписаться в любое время.

29 Комментариев

  1. Павел:

    Добрый день.

    куда закидывать этот архив?
    как плагин он не устанавливается.
    распишите, плиз, пути, которым необходимо следовать, чтобы залить в нужную папку и он начал работать.
    И, самый главный вопрос – как правильно прописать “работу” плагина на странице в выбраном месте? Либо в виде виджета на боковой панели?

    Сам плагин необходимо вставить ввиде виджета в боковую панель.

    цмс – вордпресс.

    1. root:

      Здравствуйте! Самый простой способ — добавить текстовый виджет:
      Виджет
      Перед этим надо подправить CSS файлы, чтобы изменить размеры таймера. Должно получиться что-то вроде этого:
      Виджет

      1. Павел:

        Спасибо за помощь) Помогло.

        Хотел бы еще выяснить одну вещь — можно ли этот таймер в виде виджета на боковой панели сделать «активным» — т.е. подключить к нему ссылку, и нажимая на таймер переходить на другой адрес ?
        И, можно ли, убрать внизу надпись: «Дней: 26, часов: 13, минут: 12 и секунд: 20» ?
        осталось до Нового г

        1. root:

          Да, можно, просто оберните тег, содержащий таймер в тег с ссылкой, а тег с текстом (id=»note») просто убрать:

          <a href="asd">
          <div id="countdown"></div>
          </a>
          
      2. Александр:

        А как сделать, чтобы таймер работал на определенную дату? Например, до 9 мая осталось столько-то.
        Т.е., чтобы можно было выставить дату в коде, и счетчик считал оставшиеся дни

        1. root:

          Здравствуйте!
          Для этого в файле script.js строку

          ts = new Date(2012, 0, 1)
          

          заменить на

          ts = new Date(2013, 4, 9)
          
  2. дмитрий:

    Здравствуйте. Все здорово, только в ИЕ не работает( Можно это как-то исправить?

    1. root:

      Здравствуйте! Для работы в IE, в файле jquery.countdown.js замените строки:

      			$('<span class="count'+this+'">').html(
      				'<span class="position">\
      					<span class="digit static">0</span>\
      				</span>\
      				<span class="position">\
      					<span class="digit static">0</span>\
      				</span>'
      			).appendTo(elem);
      

      на

      			$('<span class="count'+this+'">' +
      				'<span class="position">' +
      					'<span class="digit static">0</span>' +
      				'</span>' +
      				'<span class="position">' +
      					'<span class="digit static">0</span>' +
      				'</span>' +
      			'</span>').appendTo(elem);
      
      1. дмитрий:

        Спасибо, работает.

  3. Михаил:

    Как задать отсчет времени до конца текущих суток?
    Как уменьшить размер таймера.

    Заранее спасибо!

    1. root:

      Здравствуйте!
      Для уменьшения размеров в файле jquery.countdown.css в строке

      font: 40px/1.5 'Open Sans Condensed',sans-serif;
      

      измените размер шрифта, например:

      font: 20px/1.5 'Open Sans Condensed',sans-serif;
      

      Что бы таймер показывал время до конца текущих суток, в файле script.js значение ts должно вычисляться так:

      t = new Date();
      t.setDate(tr.getDate() + 1);
      t.setHours(0, 0, 0);
      ts = tr.getTime();
      
  4. Мыкола Баланов:

    Здравствуйте!
    А как задать заранее известное количество времени для срабатывания таймера? Скажем (1 час 15 минут и 12 секунд)?

  5. Семен:

    Добрый день! а как сделать, чтобы счетчик автоматически обновлялся после того как дойдет до 0? тоесть допустим изначально задали 48 часов, и после истечения этого времени снова выставлялся счетчик на 48 часов? спасибо

  6. BenPartik:

    Помогите пожалуйста! Я создаю сайт на Jquery >>html и JavaScript…
    — В одной странице у меня имеется таблица на Jquery, воот, очень хотел бы чтобы каждая строка в таблице имела свой код на удаления по установленному времени и дате. Например хочу чтобы первая строка таблицы удалилась ровно 19.01.2014 20:20:20 (Получается через неделю). Как это можно сделать? Пример кода html страницы:

    $(document).ready(function() {
    $(‘#example’).dataTable( {
    «scrollY»: «200px»,
    «scrollCollapse»: true,
    «paging»: false
    } );
    } );
    $(document).ready(function() {
    var table = $(‘#example’).DataTable();

    $(‘#example tbody’).on( ‘click’, ‘tr’, function () {
    if ( $(this).hasClass(‘selected’) ) {
    $(this).removeClass(‘selected’);
    }
    else {
    table.$(‘tr.selected’).removeClass(‘selected’);
    $(this).addClass(‘selected’);
    }
    } );

    $(‘#button’).click( function () {
    table.row(‘.selected’).remove().draw( false );
    } );
    } );

    Name
    Position
    Office
    Age
    Start date
    Salary

    Name1
    Position1
    Office1
    Age1
    Start date1
    Salary1

  7. l13k:

    как изменить размеры? перерыл весь ксс.
    счетчик микроскопических размеров

    1. root:

      Здравствуйте!
      В файле jquery.countdown.css в строке

      font: 40px/1.5 'Open Sans Condensed',sans-serif;
      

      просто измените размер шрифта

  8. Юрий:

    здравствуйте! а как изменить анимацию таймера? Можно ли это сделать?

    1. root:

      Здравствуйте!
      За анимацию в таймере отвечает функция switchDigit, в ней используется jQuery функция animate, соответственно, можно сделать любую анимацию, которую позволяет сделать эта функция (доки).
      Можно также использовать библиотеку animate.css.
      Для использования этой библиотеки достаточно добавить CSS класс с названием нужной анимации:

      	function init(elem, options){
      		elem.addClass('countdownHolder');
      
      		// Creating the markup inside the container
      		$.each(['Days','Hours','Minutes','Seconds'],function(i){
      			$('<span class="count'+this+'">' +
      				'<span class="position">' +
      					'<span class="digit animated bounceIn">0</span>' +
      				'</span>' +
      				'<span class="position">' +
      					'<span class="digit animated bounceIn">0</span>' +
      				'</span>' +
      			'</span>').appendTo(elem);
      			
      			if(this!="Seconds"){
      				elem.append('<span class="countDiv countDiv'+i+'"></span>');
      			}
      		});
      
      	}
      
      	// Creates an animated transition between the two numbers
      	function switchDigit(position,number){
      
      		var digit = position.find('.digit')
      		
      		if(digit.is(':animated')){
      			return false;
      		}
      		
      		if(position.data('digit') == number){
      			// We are already showing this number
      			return false;
      		}
      		
      		position.data('digit', number);
      
      		var replacement = $('<span>',{
      			'class':'digit animated bounceIn',
      			css:{
      				display:'none'
      			},
      			html:number
      		});
      		
      		digit.before(replacement);
      		digit.remove();
      
      		replacement.css('display', 'block');
      	}
      

      Пример можно посмотреть здесь.

  9. Ivan:

    Добрый день
    возможноли сделать несколько таймеров на 1 странице ? (в разных местах)
    Продублировал html, но второй таймер не появился, дублировать js как то не разумно,
    С Ув. Иван

  10. Ivan:

    Спасибо, додумался)
    нужно было подключать скрипт дважды!

  11. Виталий:

    Извините за глупый вопрос, но что делает этот таймер? Где функция, которую он выполняет после завершения отсчета?
    Если таймер считал до какого-то события, то должна хотя бы надпись появляться о том, что событие настало. Если он говорил о завершении какой-то акции, то человеку нужно описать, каких классных плюшек он лишился, чтобы впредь думал шустрее.

    1. root:

      Здравствуйте!
      При активации плагина, в опциях передается параметр «callback»:

      $('#countdown').countdown({
              timestamp   : ts,
              callback    : function(days, hours, minutes, seconds){
       
                  var message = "";
       
                  message += days + " day" + ( days==1 ? '':'s' ) + ", ";
                  message += hours + " hour" + ( hours==1 ? '':'s' ) + ", ";
                  message += minutes + " minute" + ( minutes==1 ? '':'s' ) + " and ";
                  message += seconds + " second" + ( seconds==1 ? '':'s' ) + " <br />";
       
                  if(newYear){
                      message += "left until the new year!";
                  }
                  else {
                      message += "left to 10 days from now!";
                  }
       
                  note.html(message);
              }
          });
      

      Эта функция будет вызываться ежесекундно, соответственно можно совершать какое-либо действие, когда переменные days, hours, minutes, seconds будут равны нулю.

      1. Виталий:

        Поскольку не знал и не знаю как работает callback, то сделал по другому: в функции tick вместо left = 0; вписал необходимые действия, а остальную часть функции обернул в else. Таким образом эта функция выполняется только до тех пор, пока не закончится время, а затем выполняет действие (заменяет ссылку на платную) и отключается. Не знаю насколько это правильней или неправильней, но у меня работает.
        А функция countdown у меня совсем не такая — я ее под куки изменил, чтобы перезагрузка страницы для конкретного человека не приводила к рестарту отсчета.

  12. Владмир:

    Здравствуйте!

    Каким образом можно разместить два таймера в разных местах на одной странице?
    Получалось только это http://prntscr.com/4dxi28 .

    1. root:

      Здравствуйте!
      Пример с двумя таймерами.

      1. Владимир:

        Здравствуйте!

        Спасибо, получилось настроить!

        Не подскажите как сделать так, чтобы таймер по окончанию отсчета начинал считать заново. На пример, чтобы обновлялся каждые 2 часа.

      2. Владимир:

        Пробовал менять код в файле jquery.countdown.js в блоке

        if(left < 0){
        left = 2;
        }

        Но ничего не вышло.

  13. Олег:

    Как запустить этот таймер от даты, чтобы считал вперед, например с 1 января, и год добавить желательно бы )

    1. Виктор:

      Для этого правится код в скрипте jquery_countdown_timer.js
      смотри ниже

      left = Math.floor(((new Date() — options.timestamp )) / 1000); // заменены местами new Date() и options.timestamp

      а вот как год добавить не знаю

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *