2015-12-09 100 views
2

我正在用JavaScript编写一个简单的倒计时器,带有播放和暂停按钮。它启动时工作正常,但如果我暂停/播放几次计时器值随机更改,我不明白为什么。倒计时器javascript暂停的错误

这里是我的代码:

var minutesleft = 60; 
var secondsleft = 0; 
var millisecondsleft = 0; 
var bool = true; 
var paused = false; 
var end; 
var now; 

function pause(){ 
    paused = true; 
} 

function stop(){ 
    end = now; 
    bool = true; 
} 

function cd(){ 
    if (bool) { 
     end = new Date(); 
     end.setMinutes(end.getMinutes()+minutesleft); 
     end.setSeconds(end.getSeconds()+secondsleft); 
     end.setMilliseconds(end.getMilliseconds()+millisecondsleft); 
     bool = false; 
    } 
now = new Date(); 
diff = end - now; 
diff = new Date(diff); 
var msec = diff.getMilliseconds(); 
var sec = diff.getSeconds(); 
var min = diff.getMinutes(); 
if (min < 10){ 
    min = "0" + min; 
} 
if (sec < 10){ 
    sec = "0" + sec; 
} 
if(msec < 10){ 
    msec = "00" +msec; 
} 
else if(msec < 100){ 
    msec = "0" +msec; 
} 
if(now >= end){ 
    clearTimeout(timerID); 
    document.getElementById("cdtime").innerHTML = 'POLICE IS HERE'; 
} 
else{ 
document.getElementById("cdtime").innerHTML = min + ":" + sec + ":" + msec; 
} 
if (paused == false){ 
    timerID = setTimeout("cd()", 10); 
} 
else { 
    bool = true; 
    minutesleft = min; 
    secondsleft = sec; 
    millisecondsleft = msec; 
} 
paused = false; 
} 

这里有一个小提琴:提前https://jsfiddle.net/cw3s5124/

感谢

+0

什么是你的布尔变量实际上在做什么?考虑命名变量的描述性的东西,以帮助其他开发人员稍后调试您的代码......或在堆栈-o :) – Chizzle

+0

对不起,我只是一个布尔值,可以帮助我知道如果这是第一次调用该函数或者自从我暂停以来的第一次 – LongDuZboub

+0

我想我找到了字符串连接中的问题,并添加了0s – Chizzle

回答

1

看到跳跃的数字,主要问题是由于字符串连接,然后使用在该字符串日期功能。部分代码,例如这样的:

if (min < 10){ 
    min = "0" + min; 
} 

一个例子证明为什么发生这种情况

var end1 = new Date(); 
var minutesleft1 = 9; 
console.log("Minutes to assign to current time"); 
console.log(end1.getMinutes() + minutesleft1); // Logs expected amount of minutes to calculate 
end1.setMinutes(end1.getMinutes() + minutesleft1); 

var end2 = new Date(); 
var minutesleft2 = "09"; 
console.log("Wrong Minutes to assign to current time"); 
console.log(end2.getMinutes() + minutesleft2); // Logs big number 
end2.setMinutes(end2.getMinutes() + minutesleft2); 

console.log(end1); // Logs expected result 
console.log(end2); // Logs a time a day or so in the future 

说明:如果你要你的启动定时器设置为9在分钟var中,它会立即需要用0填充以显示。既然你现在设置minutesleft变量"09"你实际上在做9 + "09"当你调用end.setMinutes(end.getMinutes()+minutesleft);

一旦您将字符串"0"的数目,您可以有效尝试做数字运算用字符串,这是造成意外的结果。这不是发生在一开始,因为您的if语句尚未运行,因此min,secmsec变量仍然是数字。 您只能在显示时填充数字,而不是在计算本身。

我用从this post借来的填充函数替换了字符串连接。

我还添加了一个播放功能来重置您的暂停参数。这使得代码更易读,更易于理解。另外,由于定时器尚未运行,请将其更改为在启动时暂停。

var minutesleft = 10; 
 
var secondsleft = 05; // This would normally just be returned as 5, that's why we need the pad function for display 
 
var millisecondsleft = 0; 
 
var firstCall = true; 
 
var paused = true; 
 
var end; 
 
var now; 
 

 
function pause() { 
 
    paused = true; 
 
} 
 

 
function play() { 
 
    if (paused === false) // Shorcut out because we are already running 
 
    return; 
 

 
    paused = false; 
 
    cd(); 
 
} 
 

 
function stop() { 
 
    end = now; 
 
    paused = true; 
 
    cd(); 
 
} 
 

 
document.addEventListener("DOMContentLoaded", function(event) { 
 
    document.getElementById("cdtime").innerHTML = pad(minutesleft, 2) + ":" + pad(secondsleft, 2) + ":" + pad(millisecondsleft, 2); 
 
}); 
 

 
function cd() { 
 
    if (firstCall) { 
 
    end = new Date(); 
 
    end.setMinutes(end.getMinutes() + minutesleft); 
 
    end.setSeconds(end.getSeconds() + secondsleft); 
 
    end.setMilliseconds(end.getMilliseconds() + millisecondsleft); 
 
    firstCall = false; 
 
    } 
 
    now = new Date(); 
 
    diff = end - now; 
 
    diff = new Date(diff); 
 
    var msec = diff.getMilliseconds(); 
 
    var sec = diff.getSeconds(); 
 
    var min = diff.getMinutes(); 
 

 
    if (now >= end) { 
 
    clearTimeout(timerID); 
 
    document.getElementById("cdtime").innerHTML = 'POLICE IS HERE'; 
 
    } else { 
 
    document.getElementById("cdtime").innerHTML = pad(min, 2) + ":" + pad(sec, 2) + ":" + pad(msec, 2); 
 
    } 
 
    if (paused === false) { 
 
    timerID = setTimeout("cd()", 10); 
 
    } else { 
 
    bool = true; 
 
    minutesleft = min; 
 
    secondsleft = sec; 
 
    millisecondsleft = msec; 
 
    } 
 
} 
 

 
function pad(n, width, z) { 
 
    z = z || '0'; 
 
    n = n + ''; 
 
    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; 
 
}
<body> 
 
    <div id='timer'> 
 
    <button class='playerButtons' id='playT' type='submit' onclick='play()'>Play</button> 
 
    <button class='playerButtons' id='pauseT' type=' submit' onclick='pause()'>Pause</button> 
 
    <button class='playerButtons' id='stopT' type='submit' onclick='stop()'>Stop</button> 
 
    <div id='cdtime'></div> 
 
    </div> 
 
</body>

+0

谢谢你的工作!只需在cd()调用后在play函数中设置firstCall为true,以便在暂停后暂停定时器继续。再次感谢你! – LongDuZboub

+0

我是web开发新手,现在我有一个小问题:有没有一种方法可以从html中设置脚本中的变量值? 我想要的是,例如,一个html中的按钮,当点击时将2分钟添加到计数器,这可能吗? – LongDuZboub

+0

我刚刚意识到这就是我在暂停或播放时所做的,我设置了暂停的值。所以我尝试了一个addTime(){minutesleft + = 2}函数,我点击了一个按钮,但它不起作用,为什么? – LongDuZboub

1

您重置已暂停和布尔在错误的地方。如果你看的jsfiddle,你可以看到什么需要被删除

var minutesleft = 60; 
 
var secondsleft = 0; 
 
var millisecondsleft = 0; 
 
var bool = true; 
 
var paused = true; 
 
var end; 
 
var now; 
 

 
function pause(){ 
 
    paused = true; 
 
     //bool = false; //shouldn't be here (move to stop function) 
 
} 
 
function play(){ 
 
\t if (paused === true){ 
 
     paused = false; 
 
     bool = true; 
 
     cd(); 
 
    } 
 
} 
 

 
function stop(){ 
 
    end = now; 
 
    bool = false; //add here 
 
} 
 

 
document.addEventListener("DOMContentLoaded", function(event) { 
 
\t document.getElementById("cdtime").innerHTML = minutesleft + ":" + secondsleft + "0:" + millisecondsleft + "0"; 
 
}); 
 
function cd(){ 
 
    if (bool) { 
 
     end = new Date(); 
 
     end.setMinutes(end.getMinutes()+minutesleft); 
 
     end.setSeconds(end.getSeconds()+secondsleft); 
 
     end.setMilliseconds(end.getMilliseconds()+millisecondsleft); 
 
     bool = false; 
 
    } 
 
    now = new Date(); 
 
    diff = end - now; 
 
    diff = new Date(diff); 
 
    var msec = diff.getMilliseconds(); 
 
    var sec = diff.getSeconds(); 
 
    var min = diff.getMinutes(); 
 
    if (min < 10){ 
 
     min = "0" + min; 
 
    } 
 
    if (sec < 10){ 
 
     sec = "0" + sec; 
 
    } 
 
    if(msec < 10){ 
 
     msec = "00" +msec; 
 
    } 
 
    else if(msec < 100){ 
 
     msec = "0" +msec; 
 
    } 
 
    if(now >= end){ 
 
     clearTimeout(timerID); 
 
     document.getElementById("cdtime").innerHTML = 'POLICE IS HERE'; 
 
    } 
 
    else{ 
 
    document.getElementById("cdtime").innerHTML = min + ":" + sec + ":" + msec; 
 
    } 
 
    if (paused === false){ 
 
     timerID = setTimeout("cd()", 10); 
 
    } 
 
    else { 
 
     bool = true; 
 
     minutesleft = min; 
 
     secondsleft = sec; 
 
     millisecondsleft = msec; 
 
    } 
 
    //paused = false; //shouldn't be here 
 
}
<body> 
 
<div id='timer'> 
 
\t \t <button class='playerButtons' id='playT' type='submit' onclick='play()'>Play</button> 
 
\t \t <button class='playerButtons' id='pauseT' type=' submit'onclick='pause()'>Pause</button> 
 
\t \t <button class='playerButtons' id='stopT' type='submit' onclick='stop()'>Stop</button> 
 
<div id='cdtime'></div> 
 
</div> 
 
</body>

https://jsfiddle.net/cw3s5124/27/

+0

感谢对您的回答,我很是约布尔值,但仍然是与您的代码相同的错误(不太频繁,但仍然) – LongDuZboub

+0

您可以详细了解您所看到的问题吗? –

+0

当使用播放/暂停时,在某个时间点,计时器值随机更改,只需尝试一下,播放并暂停几次,您会看到。我无法解释它,这真的很奇怪。 – LongDuZboub