Hacer un temporizador de cuenta regresiva jQuery

Al crear una página de evento o próximamente, se encuentra en la búsqueda de una buena manera de mostrar el tiempo restante. Una cuenta regresiva da la sensación de urgencia y, combinada con un campo de correo electrónico, generará más suscripciones a su boletín informativo.

Hoy vamos a crear un complemento jQuery ordenado para mostrar un temporizador de cuenta regresiva. Mostrará los días, horas, minutos y segundos restantes de su evento, así como actualizaciones animadas de cada segundo. Nota: el complemento también está disponible en Github.

¡Comencemos con el marcado!

El HTML

Le daremos al complemento el nombre creativo de "cuenta regresiva". Llamado a un elemento vacío, lo llenará con el HTML que se necesita para el temporizador de cuenta regresiva. No necesitas hacer nada más que elegir el elemento en el que quieres mostrarlo.

Marcado generado

<div id="countdown" class="countdownHolder">
    <span class="countDays">
        <span class="position">
            <span class="digit static"></span>
        </span>
        <span class="position">
            <span class="digit static"></span>
        </span>
    </span>

    <span class="countDiv countDiv0"></span>

    <span class="countHours">
        <span class="position">
            <span class="digit static"></span>
        </span>
        <span class="position">
            <span class="digit static"></span>
        </span>
    </span>

    <span class="countDiv countDiv1"></span>

    <span class="countMinutes">
        <span class="position">
            <span class="digit static"></span>
        </span>
        <span class="position">
            <span class="digit static"></span>
        </span>
    </span>

    <span class="countDiv countDiv2"></span>

    <span class="countSeconds">
        <span class="position">
            <span class="digit static"></span>
        </span>
        <span class="position">
            <span class="digit static"></span>
        </span>
    </span>

    <span class="countDiv countDiv3"></span>
</div>

En el ejemplo anterior, el complemento se invocó originalmente en un div con una identificación de cuenta regresiva . Luego, el complemento ha agregado un countdownHolder class (por lo que se aplican algunos estilos al elemento a través de CSS).

Dentro está el marcado de los dígitos. Hay dos dígitos se extiende por cada unidad de tiempo (días, horas, minutos y segundos), lo que significa que puede contar hacia atrás hasta una fecha que no sea más de 99 días en el futuro (para tales períodos de tiempo probablemente no debería usar el temporizador de todos modos, sería desalentador).

La clase estática de los dígitos les da su fondo degradado y su sombra de cuadro. Cuando está animada, esta clase se elimina para que estos toques de CSS3 no ralenticen la animación. Los dígitos se juntan en grupos para que pueda diseñarlos fácilmente. Agregar una declaración de tamaño de fuente a .countDays , afectará el tamaño de los dígitos de ambos días.

El .countDiv los tramos son los divisores entre las unidades. Los dos puntos se forman con los elementos :before/:after.

Pero, ¿cómo se genera exactamente este marcado?

JQuery

Primero, escribamos dos funciones auxiliares utilizadas por el complemento:

  • iniciar genera el marcado que viste arriba;
  • cambiar de dígito toma un lapso .position y anima los dígitos dentro de él;

Extraer esta funcionalidad como funciones separadas nos permite mantener limpio el código del complemento.

activos/cuenta regresiva/jquery.countdown.js

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

        // Creating the markup inside the container
        $.each(['Days','Hours','Minutes','Seconds'],function(i){
            $('<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);

            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 = $('<div>',{
            'class':'digit',
            css:{
                top:'-2.1em',
                opacity:0
            },
            html:number
        });

        // The .static class is added when the animation
        // completes. This makes it run smoother.

        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');
            });
    }

¡Excelente! Ahora avancemos con el cuerpo del complemento. Nuestro complemento debe tomar un objeto con parámetros para una mejor configurabilidad:una marca de tiempo del período hacia el que estamos contando y una función de devolución de llamada, que se ejecuta en cada tic y pasa el tiempo restante. Para abreviar, he omitido las funciones anteriores del código.

activos/cuenta regresiva/jquery.countdown.js

(function($){

    // Number of seconds in every time division
    var days    = 24*60*60,
        hours   = 60*60,
        minutes = 60;

    // Creating the plugin
    $.fn.countdown = function(prop){

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

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

        // Initialize the plugin
        init(this, options);

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

        (function tick(){

            // Time left
            left = Math.floor((options.timestamp - (new Date())) / 1000);

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

            // Number of days left
            d = Math.floor(left / days);
            updateDuo(0, 1, d);
            left -= d*days;

            // Number of hours left
            h = Math.floor(left / hours);
            updateDuo(2, 3, h);
            left -= h*hours;

            // Number of minutes left
            m = Math.floor(left / minutes);
            updateDuo(4, 5, m);
            left -= m*minutes;

            // Number of seconds left
            s = left;
            updateDuo(6, 7, s);

            // Calling an optional user supplied callback
            options.callback(d, h, m, s);

            // Scheduling another call of this function in 1s
            setTimeout(tick, 1000);
        })();

        // This function updates two digit positions at once
        function updateDuo(minor,major,value){
            switchDigit(positions.eq(minor),Math.floor(value/10)%10);
            switchDigit(positions.eq(major),value%10);
        }

        return this;
    };

    /* The two helper functions go here */
})(jQuery);

La función tick se llama a sí misma cada segundo. Dentro de él, calculamos la diferencia de tiempo entre la marca de tiempo dada y la fecha actual. El updateDuo La función luego actualiza los dígitos que componen la unidad de tiempo.

¡El complemento está listo! Aquí está cómo usarlo (como se ve en la demostración):

activos/js/script.js

$(function(){

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

    if((new Date()) > ts){
        // The new year is here! Count towards something else.
        // Notice the *1000 at the end - time must be in milliseconds
        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);
        }
    });

});

Por supuesto, para que esto funcione, deberá incluir el archivo css y js de la carpeta de cuenta regresiva en su página.

¡Listo!

Puede usar este script como el complemento perfecto para cada página de inicio. Lo mejor de esto es que no usa una sola imagen, todo se hace solo con CSS. Aumentar o disminuir el tamaño de la fuente hará que todo se escale bien, y solo necesita una display:none declaración para ocultar las unidades que no necesita.