¿Código para un simple temporizador de cuenta regresiva de JavaScript?

147

Quiero usar un temporizador de cuenta regresiva simple que comience a los 30 segundos desde que se ejecuta la función y termine en 0. Sin milisegundos. ¿Cómo se puede codificar?

Miguel
fuente

Respuestas:

255
var count=30;

var counter=setInterval(timer, 1000); //1000 will  run it every 1 second

function timer()
{
  count=count-1;
  if (count <= 0)
  {
     clearInterval(counter);
     //counter ended, do something here
     return;
  }

  //Do code for showing the number of seconds here
}

Para que el código del temporizador aparezca en un párrafo (o en cualquier otro lugar de la página), simplemente ponga la línea:

<span id="timer"></span>

donde quieres que aparezcan los segundos. Luego inserte la siguiente línea en su timer()función, para que se vea así:

function timer()
{
  count=count-1;
  if (count <= 0)
  {
     clearInterval(counter);
     return;
  }

 document.getElementById("timer").innerHTML=count + " secs"; // watch for spelling
}
Haga clic en Upvote
fuente
Gracias por la respuesta. Tengo dificultades para usarlo porque mi temporizador aparece en un párrafo. ¿Cómo puedo poner los 30, 29, 28, etc. en el medio de un párrafo?
Mike
1
Edité mi respuesta para mostrarle cómo mostrar el temporizador en el párrafo :)
Haga clic en Upvote el
2
En medio de un párrafo (horizontalmente): <p id = "timer" style = "text-align: center"> </p>
Alsciende el
Haga clic, su temporizador solo mostrará "0 segundos". Debería colocar la actualización innerHTML después de la disminución, no en el caso final.
Alsciende
1
Hola, ¿cómo puedo detener el funcionamiento del temporizador al cargar la página y, en cambio, solo cuando se presiona un botón? Además, ¿cómo puedo hacer que restablezca el temporizador cuando se presiona un botón después de que el temporizador ya se ha agotado?
crmepham
104

Escribí este script hace algún tiempo:

Uso:

var myCounter = new Countdown({  
    seconds:5,  // number of seconds to count down
    onUpdateStatus: function(sec){console.log(sec);}, // callback for each second
    onCounterEnd: function(){ alert('counter ended!');} // final action
});

myCounter.start();

function Countdown(options) {
  var timer,
  instance = this,
  seconds = options.seconds || 10,
  updateStatus = options.onUpdateStatus || function () {},
  counterEnd = options.onCounterEnd || function () {};

  function decrementCounter() {
    updateStatus(seconds);
    if (seconds === 0) {
      counterEnd();
      instance.stop();
    }
    seconds--;
  }

  this.start = function () {
    clearInterval(timer);
    timer = 0;
    seconds = options.seconds;
    timer = setInterval(decrementCounter, 1000);
  };

  this.stop = function () {
    clearInterval(timer);
  };
}
CMS
fuente
1
Me encantaría usar esto en lugar del otro. Cuando estaba atascado para reiniciar el número de inicio, veo que esto funciona bien ..
Oki Erie Rinaldi
Si necesito detener el temporizador por casualidad, ¿cómo hago eso?
SIJ
@SIJ myCounter.stop();
R3tep
54

Hasta ahora, las respuestas parecen depender del código que se ejecuta instantáneamente. Si configura un temporizador para 1000 ms, en realidad será alrededor de 1008.

Así es como debes hacerlo:

function timer(time,update,complete) {
    var start = new Date().getTime();
    var interval = setInterval(function() {
        var now = time-(new Date().getTime()-start);
        if( now <= 0) {
            clearInterval(interval);
            complete();
        }
        else update(Math.floor(now/1000));
    },100); // the smaller this number, the more accurate the timer will be
}

Para usar, llame al:

timer(
    5000, // milliseconds
    function(timeleft) { // called every step to update the visible countdown
        document.getElementById('timer').innerHTML = timeleft+" second(s)";
    },
    function() { // what to do after
        alert("Timer complete!");
    }
);
Niet the Dark Absol
fuente
2
¡Mira, como dijiste, esa es la única forma de hacerlo bien!
mcella
3
Le di un pulgar hacia arriba, con una advertencia: para fines de visualización, probablemente desee mostrar el techo (Math.ceil ()) en lugar del piso. Es realmente desorientador cuando el reloj llega a 0 un segundo antes de que se active la alerta. (Entonces, por supuesto, debe haber una llamada adicional para actualizar () antes de completar ())
Paul Williams
21

Aquí hay otro si alguien necesita uno por minutos y segundos:

    var mins = 10;  //Set the number of minutes you need
    var secs = mins * 60;
    var currentSeconds = 0;
    var currentMinutes = 0;
    /* 
     * The following line has been commented out due to a suggestion left in the comments. The line below it has not been tested. 
     * setTimeout('Decrement()',1000);
     */
    setTimeout(Decrement,1000); 

    function Decrement() {
        currentMinutes = Math.floor(secs / 60);
        currentSeconds = secs % 60;
        if(currentSeconds <= 9) currentSeconds = "0" + currentSeconds;
        secs--;
        document.getElementById("timerText").innerHTML = currentMinutes + ":" + currentSeconds; //Set the element id you need the time put into.
        if(secs !== -1) setTimeout('Decrement()',1000);
    }
Layton Everson
fuente
No debe pasar una cadena al primer parámetro de setTimeout, setTimeout(Decrement, 1000)es preferible. stackoverflow.com/questions/6232574/…
Scottux
Gracias por la sugerencia, he actualizado el script.
Layton Everson
3

// Javascript Countdown
// Version 1.01 6/7/07 (1/20/2000)
// by TDavid at http://www.tdscripts.com/
var now = new Date();
var theevent = new Date("Sep 29 2007 00:00:01");
var seconds = (theevent - now) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
ID = window.setTimeout("update();", 1000);

function update() {
  now = new Date();
  seconds = (theevent - now) / 1000;
  seconds = Math.round(seconds);
  minutes = seconds / 60;
  minutes = Math.round(minutes);
  hours = minutes / 60;
  hours = Math.round(hours);
  days = hours / 24;
  days = Math.round(days);
  document.form1.days.value = days;
  document.form1.hours.value = hours;
  document.form1.minutes.value = minutes;
  document.form1.seconds.value = seconds;
  ID = window.setTimeout("update();", 1000);
}
<p><font face="Arial" size="3">Countdown To January 31, 2000, at 12:00: </font>
</p>
<form name="form1">
  <p>Days
    <input type="text" name="days" value="0" size="3">Hours
    <input type="text" name="hours" value="0" size="4">Minutes
    <input type="text" name="minutes" value="0" size="7">Seconds
    <input type="text" name="seconds" value="0" size="7">
  </p>
</form>

Kedarnath
fuente
8
Este script utiliza prácticas muy malas de los años 90. Y también 1.5 horas no son 2 horas. Es 1 hora y 30 minutos. Deberías usar Math.floor, noMath.round
corbacho
3

Acabo de modificar la respuesta de @ ClickUpvote :

Puede usar IIFE (Expresión de función invocada inmediatamente) y recursividad para hacerlo un poco más fácil:

var i = 5;  //set the countdown
(function timer(){
    if (--i < 0) return;
    setTimeout(function(){
        console.log(i + ' secs');  //do stuff here
        timer();
    }, 1000);
})();

Rohit Sharma
fuente
2

Al ampliar la respuesta aceptada, su máquina se va a dormir, etc. puede retrasar el funcionamiento del temporizador. Puede obtener un tiempo real, a costa de un pequeño procesamiento. Esto le dará un verdadero tiempo restante.

<span id="timer"></span>

<script>
var now = new Date();
var timeup = now.setSeconds(now.getSeconds() + 30);
//var timeup = now.setHours(now.getHours() + 1);

var counter = setInterval(timer, 1000);

function timer() {
  now = new Date();
  count = Math.round((timeup - now)/1000);
  if (now > timeup) {
      window.location = "/logout"; //or somethin'
      clearInterval(counter);
      return;
  }
  var seconds = Math.floor((count%60));
  var minutes = Math.floor((count/60) % 60);
  document.getElementById("timer").innerHTML = minutes + ":" + seconds;
}
</script>
Patrick Knott
fuente
0

Puede hacer lo siguiente con JS puro. Solo necesita proporcionar la función con la cantidad de segundos y hará el resto.

var insertZero = n => n < 10 ? "0"+n : ""+n,
   displayTime = n => n ? time.textContent = insertZero(~~(n/3600)%3600) + ":" +
                                             insertZero(~~(n/60)%60) + ":" +
                                             insertZero(n%60)
                        : time.textContent = "IGNITION..!",
 countDownFrom = n => (displayTime(n), setTimeout(_ => n ? sid = countDownFrom(--n)
                                                         : displayTime(n), 1000)),
           sid;
countDownFrom(3610);
setTimeout(_ => clearTimeout(sid),20005);
<div id="time"></div>

Redu
fuente
0

Basado en la solución presentada por @Layton Everson, desarrollé un contador que incluye horas, minutos y segundos:

var initialSecs = 86400;
var currentSecs = initialSecs;

setTimeout(decrement,1000); 

function decrement() {
   var displayedSecs = currentSecs % 60;
   var displayedMin = Math.floor(currentSecs / 60) % 60;
   var displayedHrs = Math.floor(currentSecs / 60 /60);

    if(displayedMin <= 9) displayedMin = "0" + displayedMin;
    if(displayedSecs <= 9) displayedSecs = "0" + displayedSecs;
    currentSecs--;
    document.getElementById("timerText").innerHTML = displayedHrs + ":" + displayedMin + ":" + displayedSecs;
    if(currentSecs !== -1) setTimeout(decrement,1000);
}
Aiwatko
fuente
0

// Javascript Countdown
// Version 1.01 6/7/07 (1/20/2000)
// by TDavid at http://www.tdscripts.com/
var now = new Date();
var theevent = new Date("Nov 13 2017 22:05:01");
var seconds = (theevent - now) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
ID = window.setTimeout("update();", 1000);

function update() {
  now = new Date();
  seconds = (theevent - now) / 1000;
  seconds = Math.round(seconds);
  minutes = seconds / 60;
  minutes = Math.round(minutes);
  hours = minutes / 60;
  hours = Math.round(hours);
  days = hours / 24;
  days = Math.round(days);
  document.form1.days.value = days;
  document.form1.hours.value = hours;
  document.form1.minutes.value = minutes;
  document.form1.seconds.value = seconds;
  ID = window.setTimeout("update();", 1000);
}
<p><font face="Arial" size="3">Countdown To January 31, 2000, at 12:00: </font>
</p>
<form name="form1">
  <p>Days
    <input type="text" name="days" value="0" size="3">Hours
    <input type="text" name="hours" value="0" size="4">Minutes
    <input type="text" name="minutes" value="0" size="7">Seconds
    <input type="text" name="seconds" value="0" size="7">
  </p>
</form>

maztt
fuente
0

Mi solución funciona con formatos de fecha y hora de MySQL y proporciona una función de devolución de llamada. en cumplimiento. Descargo de responsabilidad: funciona solo con minutos y segundos, ya que esto es lo que necesitaba.

jQuery.fn.countDownTimer = function(futureDate, callback){
    if(!futureDate){
        throw 'Invalid date!';
    }

    var currentTs = +new Date();
    var futureDateTs = +new Date(futureDate);

    if(futureDateTs <= currentTs){
        throw 'Invalid date!';
    }


    var diff = Math.round((futureDateTs - currentTs) / 1000);
    var that = this;

    (function countdownLoop(){
        // Get hours/minutes from timestamp
        var m = Math.floor(diff % 3600 / 60);
        var s = Math.floor(diff % 3600 % 60);
        var text = zeroPad(m, 2) + ':' + zeroPad(s, 2);

        $(that).text(text);

        if(diff <= 0){
            typeof callback === 'function' ? callback.call(that) : void(0);
            return;
        }

        diff--;
        setTimeout(countdownLoop, 1000);
    })();

    function zeroPad(num, places) {
      var zero = places - num.toString().length + 1;
      return Array(+(zero > 0 && zero)).join("0") + num;
    }
}

// $('.heading').countDownTimer('2018-04-02 16:00:59', function(){ // on complete})
nikksan
fuente
0

Por el bien de las actuaciones, ahora podemos usar de forma segura requestAnimationFrame para un bucle rápido, en lugar de setInterval / setTimeout.

Al usar setInterval / setTimeout, si una tarea de bucle tarda más tiempo que el intervalo, el navegador simplemente extenderá el bucle de intervalo para continuar con la representación completa. Esto está creando problemas. Después de minutos de sobrecarga setInterval / setTimeout, esto puede congelar la pestaña, el navegador o toda la computadora.

Los dispositivos de Internet tienen una amplia gama de prestaciones, por lo que es bastante imposible codificar un intervalo de tiempo fijo en milisegundos.

Usando el objeto Fecha , para comparar la Fecha de inicio de Época y la actual. Esto es mucho más rápido que todo lo demás, el navegador se encargará de todo, a una velocidad constante de 60FPS ( 1000/60 = 16.66ms por cuadro ), un cuarto de parpadeo , y si la tarea en el bucle requiere más que eso , el navegador soltará algunos repintes.

Esto permite un margen antes de que nuestros ojos se den cuenta ( Humano = 24FPS => 1000/24 ​​= 41.66ms por cuadro = animación fluida!)

https://caniuse.com/#search=requestAnimationFrame

/* Seconds to (STRING)HH:MM:SS.MS ------------------------*/
/* This time format is compatible with FFMPEG ------------*/
function secToTimer(sec){
  const o = new Date(0), p =  new Date(sec * 1000)
  return new Date(p.getTime()-o.getTime()).toString().split(" ")[4] + "." + p.getMilliseconds()
}

/* Countdown loop ----------------------------------------*/
let job, origin = new Date().getTime()
const timer = () => {
  job = requestAnimationFrame(timer)
  OUT.textContent = secToTimer((new Date().getTime() - origin) / 1000)
}

/* Start looping -----------------------------------------*/
requestAnimationFrame(timer)

/* Stop looping ------------------------------------------*/
// cancelAnimationFrame(job)

/* Reset the start date ----------------------------------*/
// origin = new Date().getTime()
span {font-size:4rem}
<span id="OUT"></span>
<br>
<button onclick="origin = new Date().getTime()">RESET</button>
<button onclick="requestAnimationFrame(timer)">RESTART</button>
<button onclick="cancelAnimationFrame(job)">STOP</button>

NVRM
fuente