javascript 時鐘會停止計時?
在javascript中如果要在網頁上寫一個時鐘,比較簡單的方式是在固定時間執行一段程式讓網頁中的時間數字可以每隔1秒就加1(如以下程式),但這樣會有一個問題是當網頁因在使用其他分頁或者將瀏覽器縮小等動作,使得瀏覽器為了節省資源而進入休眠的時候就會造成這段期間javascript程式沒有執行加1的動作,而是當使用者再次點開網頁時javascript程式才會再次運行,如此一來計時器就無法達到計時的功用。(這個問題筆者之前也被困擾過,後來找到解決辦法如下)
javascript程式碼1–固定時間加1
var timer
function init() {
timer=document.getElementById("timer")
}
function start(){
document.getElementById("btn").disabled=true//將 開始計時的按鈕停用 以防止使用者多次點擊,多次執行start()函式,造成讀秒錯誤
//setInterval(function,time)每隔time 時間就執行一次function
time_count=window.setInterval(count,1000)//1000代表1秒
}
function count(){
timer.innerHTML=parseFloat(timer.innerHTML)+1 //parseFloat()將字串轉數字,因為innerHTML取出之格式為字串
}
解決辦法:
透過時間戳記(timestamp),紀錄開始計時當下的時間戳記(利用Date.now()函式取得自1970/01/01 00:00:00 UTC 起經過的毫秒數[1]),接著利用javascript計算當下的時間戳記與開始時的時間戳記時間差(如下圖所示),並將時間差換算成經過幾分幾秒並顯示出來,程式碼如下
javascript程式碼2–時間戳記
function start(event){
start_time = Date.now()
document.getElementById("btn").disabled=true//將 開始計時的按鈕停用 以防止使用者多次點擊,多次執行start()函式,造成讀秒錯誤
time_count=window.setInterval(count,10)//1000代表1秒
}
var day=0,hour=0,min=0,sec=0.0
function timer_calculator(timestamp,start_time,total_time){
current_time=timestamp
time_calcu=((total_time+current_time-start_time)/1000)
if(time_calcu>86400){
day=Math.floor(time_calcu/86400)
day_mod=parseFloat((time_calcu % 86400).toFixed(2))
hour=Math.floor(day_mod/3600)
hour_mod=parseFloat((day_mod % 3600).toFixed(2))
min=Math.floor(hour_mod/60).toString()
sec=parseFloat((hour_mod % 60).toFixed(2)).toString()
//result=day+":"+hour+":"+min +":"+sec
day_timer.style.visibility = "visible";
timer_1.style.visibility = "visible";
}
else if(86400>time_calcu && time_calcu>3600){
hour=Math.floor(time_calcu/3600).toString()
hour_mod=parseFloat((time_calcu % 3600).toFixed(2))
min=Math.floor(hour_mod/60).toString()
sec=parseFloat((hour_mod % 60).toFixed(2)).toString()
//result=hour+":"+min +":"+sec
hour_timer.style.visibility = "visible";
timer_2.style.visibility = "visible";
}
else if(3600>time_calcu && time_calcu>60){
min=Math.floor(time_calcu/60).toString()
sec=parseFloat((time_calcu % 60).toFixed(2)).toString()
//result=min +":"+sec
}else{
//result=parseFloat(time_calcu.toFixed(2)).toString()
sec=parseFloat(time_calcu.toFixed(2)).toString()
}
透過上述步驟就能夠避免程式因瀏覽器節省資源,而在休眠期間沒有執行javascript程式,導致計時錯誤的情形。因為時間戳記是一個與參考時間的時間差,因此即使瀏覽器休眠也可以,在重新運行的當下透過兩個時間戳記的差值算出經過的時間(如以下示意圖所示)。
參考:
[1]https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Date/now