2015-12-09 134 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