JS倒计时器 - 暂停功能

时间:2017-08-05 13:04:16

标签: javascript timer

这是一个简单的倒计时器,从9下降到0。 倒计时工作正常。但是如果我想在流程中暂停它然后从暂停的地方重新启动怎么办? 我试过(见下面的代码)来中断倒计时,保存它所在的数字,然后从新号码重启功能。但是倒计时会变得混乱,我看不出原因。有什么想法吗?

PS。我可以从其他地方剪切和粘贴计时器,但我这样做是为了学习体验。我确信有更好的方法来编写JS中的倒数计时器,但是我不知道我不能让这种方式工作并且认为我必须遗漏一些明显的东西。

非常感谢

var currentTimeInt = 10;
var minn = [];
var stop = 0;

 // stop
 function stopCounter() {
 currentTime = document.getElementById('mins').textContent; // grabs the number of minutes at moment of pause.

 stop = 1;
  }
 
 // restart
 function restart() {
 stop = 0;
 currentTimeInt = parseInt(currentTime, 10); // converts that number into an integer we can use
 document.getElementById("mins").innerHTML=currentTimeInt;
  newMinutes(); // restarts the newMinutes function with the start time currentTimeInt set to the time the counter stopped at
   }
 
function newMinutes() {
document.getElementById('mins').innerHTML= currentTimeInt; // displays the counter

for (aa = currentTimeInt-1; aa >= 0; aa--) {
minn.push(aa); // builds an array of numbers in descending order
document.getElementById('mins').innerHTML= minn[aa]; 
for (let bb=1; bb<=currentTimeInt; bb++) {
if (bb<currentTimeInt) {
    setTimeout( function timer(){
	if (stop == 0) {     // checks if "stop!" has been clicked and returns false to stop the function if that is the case
        document.getElementById('mins').innerHTML= minn[bb];
		console.log(minn[bb]);
	}
	else {return false;}
		}, bb*1000 );
	}

}	
}
console.log(currentTimeInt + " the end");

}
<span>Minutes: </span><span id= "mins"></span>
<button onclick="newMinutes()">Go!</button>
<button onclick="stopCounter()">Stop!</button>
<button onclick="restart()">Reset!</button>

5 个答案:

答案 0 :(得分:0)

你可以试试这个例子:

&#13;
&#13;
var timerId;
var counter;

function start() {
  console.log('start');
  if (!counter) {
    reset();
  } else {
    loop();
  }
}

function pause() {
  console.log('pause');
  if (timerId) {
    clearInterval(timerId);
    timerId = null;
  }
}

function reset() {
  console.log('reset');
  pause();
  counter = 10;
  loop();
}

function loop() {
  timerId = setInterval(function() {
    if (0 >= counter) {
      pause();
      return;
    }
    console.log('counter', counter);
    counter--;
  }, 500);
}
&#13;
<button onclick='start();'>Start</button>
<button onclick='pause();'>Pause</button>
<button onclick='reset();'>Reset</button>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

此处的第一个问题是currentTime未全局定义,因此无法从restart内访问它。只需将var currentTime;放在文件的开头即可。

但是你有另一个严重的问题,因为你以一种非常尴尬的方式使用setTimeout。您正在同时创建多个超时,并根据与currentTimeInt的关系给予延迟。这有两个问题。对于一个,使用两个for循环不是非常有效,并且似乎也是多余的,因为你的内部for循环无论如何都要计算到currentTimeInt。

其次,你永远不会清除(并且可能无法清除)超时。这意味着当您暂停后重新启动计时器时,如果尚未触发任何超时,那么您的程序将运行这些计时器,并使分钟在旧的超时和您在取消暂停后创建的新超时之间来回跳转。

我知道你在评论中说你想要让它发挥作用,因为你基本上是自己完成了整个事情,但可能不值得继续这条路。在看了一些之后,我认为修复你的程序需要重组它,或者要求它以一种非常低效的方式被黑客入侵。如果你是一个刚刚学习Javascript的人,那么最好重新开始并以正确的方式去做。

以下是使用setInterval而不是setTimeout的更好方法的示例,但您可以自行尝试解决这个问题。

(有一些方法可以改进下面代码的功能,但它应该足以让你了解一般的想法)

var startTimeInt = 10;
var currentTimeInt = startTimeInt;
var interval = undefined;

// start the timer
function startCounter() {
  if(!interval){
    document.getElementById('mins').innerHTML = currentTimeInt; 
    interval = setInterval(newNumber, 1000) // set an interval
  }
}

// stop
function stopCounter() {
  // clear the interval
  clearInterval(interval)
  interval = undefined;
}

// reset the timer
function resetCounter(){
  currentTimeInt = startTimeInt;
  document.getElementById('mins').innerHTML = currentTimeInt;
  //stopCounter(); startCounter();
}

// change the time and handle end of time event
function newNumber(){
  currentTimeInt--; // decrement the current time
  document.getElementById('mins').innerHTML = currentTimeInt; 
  if(currentTimeInt == 0){
    console.log("Done");
    stopCounter();
  }
}
<span>Minutes: </span><span id= "mins"></span>
<button onclick="startCounter()">Go!</button>
<button onclick="stopCounter()">Stop!</button>
<button onclick="resetCounter()">Reset!</button>

答案 2 :(得分:0)

这是一个有用的代码片段..

var paused = false;
var started = false;
var stopped = true;
var currentCount = 0;
var running = false;
interval = 1000;
maxCount = 10; 

function start() {
  if (stopped){
    started = true;
    paused= false;
    stopped = false;
    currentCount = maxCount;
    loop(); running = true; 
    return; 
  }
    paused= false;
}

function pause() {
  paused= true;
}
function stop(){
 paused = false;
 started = false;
 stopped = true;
 running = false;
 currentCount = 0;
}

function update(item){
  document.getElementById("status").innerHTML  = item; 
  //console.log(item);
  --currentCount;
  if(currentCount < 0){stop()}
}

function reset() {
  currentCount = maxCount;
  document.getElementById("status").innerHTML  = currentCount; 
}

function loop(){
  if (!stopped){
    if (!paused){update(currentCount);}
    setTimeout(function(){loop()}, interval)
  }
}
<button onclick='start();'>Start</button>
<button onclick='pause();'>Pause</button>
<button onclick='reset();'>Reset</button>
<button onclick='stop();'>Stop</button>
<div id="status"></div>

答案 3 :(得分:0)

这是我的START,PAUSE,RESUME,STOP&amp; amp;重置功能:

var jqcd_start_id = 'input#jqcd_start';
var jqcd_time_id = 'input#jqcd_time';
var jqcd_count_id = 'span#jqcd_count';
var jqcd_end_message = 'Time is up!';

var jqcd_countdown = '';
var jqcd_status = 'stopped';
var jqcd_current = '';
function jqcd(action){
  
  if (action == 'start') {
    if (jqcd_status == 'stopped') {
      jqcd_updtv(jqcd_start_id, 'Pause');
      jqcd_status = 'running';
      jqcd_current = jqcd_countdown;
      jqcd_updtt(jqcd_count_id, jqcd_countdown);
    }
    else if (jqcd_status == 'running') {
      jqcd_updtv(jqcd_start_id, 'Resume');
      jqcd_status = 'paused';
    }
    else if (jqcd_status == 'paused') {
      jqcd_updtv(jqcd_start_id, 'Pause');
      jqcd_status = 'running';
    }
  }
  else if (action == 'stop') {
    jqcd_updtv(jqcd_start_id, 'Start');
    jqcd_status = 'stopped';
    jqcd_updtt(jqcd_count_id, jqcd_end_message);
  }
  else if (action == 'reset') {
    jqcd_updtv(jqcd_start_id, 'Start');
    jqcd_status = 'stopped';
    jqcd_updtt(jqcd_count_id, jqcd_countdown);
  }
  
  var a =  jqcd_current.split(":");
  var m = a[0];
  var s = (a[1] - 1);
  
  if (s < 0) {
    if (parseInt(m) == 0) {
      jqcd_updtv(jqcd_start_id, 'Start');
      jqcd_status = 'stopped';
      jqcd_updtt(jqcd_count_id, jqcd_end_message);
    }
    else {
      m = m - 1;
      s = 59;
    }
  }
  
  if(s >= 0){
    setTimeout(function(){
      if (jqcd_status == 'running') {
        m = (parseInt(m) < 10)? "0" + parseInt(m): m;
        s = (parseInt(s) < 10)? "0" + parseInt(s): s;
        jqcd_updtt(jqcd_count_id, m + ":" + s);
        jqcd_current = m + ":" + s;
        jqcd('');
      }
    }, 1000);
  }
}

function jqcd_updtv(selector, value) {
  if (selector != '') {
    $(selector).val(value);
  }
}
function jqcd_updtt(selector, value) {
  if (selector != '') {
    $(selector).text(value);
  }
}

$(document).ready(function() {
  jqcd_countdown = $(jqcd_time_id).val();
  jqcd_updtt(jqcd_count_id, jqcd_countdown);
  
  $(jqcd_time_id).keyup(function() {
    jqcd_countdown = $(jqcd_time_id).val();
    jqcd_updtt(jqcd_count_id, jqcd_countdown);
    jqcd_updtv(jqcd_start_id, 'Start');
    jqcd_status = 'stopped';
  });
});
span#jqcd_count {
  font-size: 20pt;
  font-weight: bold;
}
input#jqcd_start,
input#jqcd_stop,
input#jqcd_reset {
  font-size: 12pt;
  font-weight: bold;
}
input#jqcd_start,
input#jqcd_stop,
input#jqcd_reset {
  width: 100px;
}
span#jqcd_count {
  font-family: "Lucida Console", Monaco, "Courier New", Courier, monospace !IMPORTANT;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="jqcd_count">00:30</span><br><br>
<input type="button" id="jqcd_start" value="Start" onClick="jqcd('start')" />
<input type="button" id="jqcd_stop" value="Stop" onClick="jqcd('stop')" />
<input type="button" id="jqcd_reset" value="Reset" onClick="jqcd('reset')" /><br><br>
<input type="text" id="jqcd_time" value="00:10" />
<br><br>

自定义非常简单。 JavaScript代码中的前四个变量可以调整为适用于您的特定HTML。

如果您希望每秒都执行一次操作,请在“jqcd_updtt”函数中添加您的代码行。

当然,CSS完全是可选的。

通过更改“jqcd_time”字段中的值来动态设置倒计时开始时间。但是,如果要为倒计时起点设置静态值,则可以更改JavaScript代码末尾的“$(document).ready(function(){”函数内的变量。

PS。 此倒计时没有分钟或秒的最大限制

答案 4 :(得分:0)

如何保持亲吻!

&#13;
&#13;
let i = 9,j
function chrono(){
  if (i>=0){
    now.innerText = i--
  }
}
&#13;
<h1><div id="now">⏰ Ready!</div>
<button onclick="setInterval(function(){ chrono() }, 1000);this.style.display='none'">Start</button>
<button onclick="i=10">Reset</button>
<button onclick="j=i;i=-1">Pause</button>
<button onclick="i=j">Continue</button>
&#13;
&#13;
&#13;

这是准备扩展的最基本的例子,大部分没有clearInterval

  

KISS原则指出,如果保留大多数系统,它们的效果最好   简单而不是复杂;因此简单应该是一个   应避免设计中的关键目标和不必要的复杂性。   https://en.wikipedia.org/wiki/KISS_principle

因此,js增量和setInterval似乎很容易,但它们隐藏了复杂的东西。

另一种使用date.now()的方法,它根据系统时钟提供准确的unix时间戳,并提供用于发出蜂鸣声的网络音频api。

&#13;
&#13;
i = Date.now();j=i+10000;z.innerText="Target @"+j
function d(){ 
    if(now.innerText < j){
        now.innerText = Date.now()
        k(3,603,80)
        }
    if(now.innerText > j){
        now.innerHTML = "<b>TARGETED!</b>"
        k(8,728,100)
        }        
  }

setInterval(function(){ d() }, 100)

a=new AudioContext()
function k(w,x,y){
  v=a.createOscillator()
  u=a.createGain()
  v.connect(u)
  v.frequency.value=x
  v.type="square"
  u.connect(a.destination)
  u.gain.value=w*0.01
  v.start(a.currentTime)
  v.stop(a.currentTime+y*0.001)
}
&#13;
EPOCH: <out id="now"></out><h6 id="z">
&#13;
&#13;
&#13;