- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- JavaScript中怎么構建一個(gè)倒數計時(shí)器
JavaScript中怎么構建一個(gè)倒數計時(shí)器,相信很多沒(méi)有經(jīng)驗的人對此束手無(wú)策,為此本文總結了問(wèn)題出現的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。
首先,你需要設置一個(gè)有效的結束日期。這應該是JavaScript的 Date.parse() 方法可以理解的任何格式的字符串。例如:
ISO 8601格式:
const deadline = '2015-12-31';
簡(jiǎn)短格式:
const deadline = '31/12/2015';
或者,長(cháng)格式:
const deadline = 'December 31 2015';
這些格式中的每一種都允許你指定一個(gè)準確的時(shí)間和一個(gè)時(shí)區(或者在ISO日期的情況下指定一個(gè)與UTC的偏移)。例如:
const deadline = 'December 31 2015 23:59:59 GMT+0200';
3.計算剩余時(shí)間下一步是計算剩余時(shí)間。我們需要編寫(xiě)一個(gè)函數,該函數需要一個(gè)表示給定結束時(shí)間的字符串(如上所述)。然后,我們計算該時(shí)間與當前時(shí)間之間的時(shí)差??雌饋?lái)像這樣:
function getTimeRemaining(endtime){ const total = Date.parse(endtime) - Date.parse(new Date()); const seconds = Math.floor( (total/1000) % 60 ); const minutes = Math.floor( (total/1000/60) % 60 ); const hours = Math.floor( (total/(1000*60*60)) % 24 ); const days = Math.floor( total/(1000*60*60*24) ); return { total, days, hours, minutes, seconds }; }
首先,我們要創(chuàng )建一個(gè)變量 total 以保留到截止日期為止的剩余時(shí)間。Date.parse() 函數將時(shí)間字符串轉換為毫秒值,這樣我們就可以將兩次相減,得到中間的時(shí)間量。
const total = Date.parse(endtime) - Date.parse(new Date());
4.將時(shí)間轉換為可用格式
現在我們要將毫秒轉換為天,小時(shí),分鐘和秒。讓我們以秒為例:
const seconds = Math.floor( (t/1000) % 60 );
讓我們分解一下這里發(fā)生的事情。
鴻蒙官方戰略合作共建——HarmonyOS技術(shù)社區
將毫秒除以1000可轉換為秒:(t/1000)
將總秒數除以60,然后取余數。你不需要所有的秒,只需要計算分鐘數后剩下的那些:(t/1000) % 60
四舍五入到最接近的整數。這是因為你需要完整的秒數,而不是幾分之一秒:Math.floor((t/1000)%60)
重復此邏輯,將毫秒轉換為分鐘,小時(shí)和天。
5.將時(shí)鐘數據輸出為可重復使用的對象
在準備好幾天,幾小時(shí),幾分鐘和幾秒鐘之后,我們現在可以將數據作為可重復使用的對象返回:
return { total, days, hours, minutes, seconds };
這個(gè)對象允許你調用你的函數,并獲得任何計算值。這是如何獲取剩余分鐘數的示例:
getTimeRemaining(deadline).minutes
方便吧?
6.在頁(yè)面上顯示時(shí)鐘,并在時(shí)鐘為零時(shí)停止時(shí)鐘
現在我們有了一個(gè)可以吐出剩余天數、小時(shí)、分鐘和秒數的函數,我們就可以建立我們的時(shí)鐘了。首先,我們將創(chuàng )建以下HTML元素來(lái)保存時(shí)鐘:
<div id="clockdiv"></div>
然后,我們將編寫(xiě)一個(gè)函數,在新的div中輸出時(shí)鐘數據:
function initializeClock(id, endtime) { const clock = document.getElementById(id); const timeinterval = setInterval(() => { const t = getTimeRemaining(endtime); clock.innerHTML = 'days: ' + t.days + '<br>' + 'hours: '+ t.hours + '<br>' + 'minutes: ' + t.minutes + '<br>' + 'seconds: ' + t.seconds; if (t.total <= 0) { clearInterval(timeinterval); } },1000); }
該函數有兩個(gè)參數,這兩個(gè)參數是包含時(shí)鐘的元素的id,以及倒計時(shí)的結束時(shí)間。在函數內部,我們將聲明一個(gè) clock 變量,并使用它來(lái)保存對時(shí)鐘容器div的引用。這意味著(zhù)我們不必一直查詢(xún)DOM。
接下來(lái),我們將使用 setInterval 每秒執行一個(gè)匿名函數。此功能將執行以下操作:
計算剩余時(shí)間。
將剩余時(shí)間輸出到我們的div。
如果剩余時(shí)間為零停止計時(shí)。
此時(shí),剩下的唯一步驟是像這樣運行時(shí)鐘:
initializeClock('clockdiv', deadline);
恭喜你!現在,你僅用18行JavaScript就擁有了一個(gè)基本時(shí)鐘。
7.準備展示你的時(shí)鐘
在設置時(shí)鐘樣式之前,我們需要進(jìn)行一些改進(jìn)。
消除初始延遲,使你的時(shí)鐘立即顯示。
讓時(shí)鐘腳本更有效率,這樣它就不會(huì )連續重建整個(gè)時(shí)鐘。
根據需要添加前導零。
7.1 消除初始延遲
在時(shí)鐘中,我們使用 setInterval 每秒更新一次顯示。多數情況下,這很好,除非在開(kāi)始時(shí)會(huì )有一秒鐘的延遲。要消除此延遲,我們必須在間隔開(kāi)始之前更新一次時(shí)鐘。
讓我們將傳遞給 setInterval 的匿名函數移到其自己的單獨函數中,我們可以將此函數命名為 updateClock。在 setInterval 外調用一次 updateClock 函數,然后在 setInterval 內再次調用。
在你的JavaScript中,替換這個(gè)
const timeinterval = setInterval(() => { ... },1000);
新代碼
function updateClock(){ const t = getTimeRemaining(endtime); clock.innerHTML = 'days: ' + t.days + '<br>' + 'hours: '+ t.hours + '<br>' + 'minutes: ' + t.minutes + '<br>' + 'seconds: ' + t.seconds; if (t.total <= 0) { clearInterval(timeinterval); } } updateClock(); // 首先運行一函數能以避免延遲 var timeinterval = setInterval(updateClock,1000);
7.2 避免不斷重建時(shí)鐘
我們需要使時(shí)鐘腳本更高效,我們只想更新時(shí)鐘中的數字,而不是每秒重建整個(gè)時(shí)鐘。實(shí)現此目的的一種方法是將每個(gè)數字放在 span 標簽內,并僅更新這些 span 的內容。
這是HTML:
<div id="clockdiv"> Days: <span class="days"></span><br> Hours: <span class="hours"></span><br> Minutes: <span class="minutes"></span><br> Seconds: <span class="seconds"></span> </div>
現在讓我們參考這些元素。在定義 clock 變量的位置之后添加以下代碼
const daysSpan = clock.querySelector('.days'); const hoursSpan = clock.querySelector('.hours'); const minutesSpan = clock.querySelector('.minutes'); const secondsSpan = clock.querySelector('.seconds');
接下來(lái),我們需要修改 updateClock 函數,使其只更新數字。新的代碼是這樣的:
function updateClock(){ const t = getTimeRemaining(endtime); daysSpan.innerHTML = t.days; hoursSpan.innerHTML = t.hours; minutesSpan.innerHTML = t.minutes; secondsSpan.innerHTML = t.seconds; ... }
7.3 添加前導0
現在時(shí)鐘不再每秒都在重建,我們還有另一件事要做:添加前導零。例如,不是讓時(shí)鐘顯示7秒,而是顯示07秒。一種簡(jiǎn)單的方法是在一個(gè)數的開(kāi)頭加上一串“0”,然后切掉最后兩個(gè)數字。
例如,要在“seconds”值上添加前導零,你可以更改以下設置:
secondsSpan.innerHTML = t.seconds;
為
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
如果你愿意,你也可以在分鐘和小時(shí)的前面加零。如果你已經(jīng)走到這一步,恭喜你!你的時(shí)鐘現在已經(jīng)可以顯示了。
8.更進(jìn)一步
以下示例演示了如何為某些用例擴展時(shí)鐘。它們都是基于上面的基本例子。
8.1 自動(dòng)調節時(shí)鐘
假設我們想讓時(shí)鐘在特定的日子出現,而不是在其他的日子。例如,我們可能有一系列事件即將發(fā)生,而不希望每次都手動(dòng)更新時(shí)鐘。以下是如何提前安排事情的方法。
通過(guò)在CSS中將其 display 屬性設置為 none 來(lái)隱藏時(shí)鐘,然后將以下內容添加到 initializeClock 函數中(以 var clock 開(kāi)頭的行之后)。這將導致只有在調用 initializeClock 函數后才會(huì )顯示時(shí)鐘:
clock.style.display = 'block';
接下來(lái),我們可以指定顯示時(shí)鐘的日期。這將替換截止日期變量( deadline ):
const schedule = [ ['Jul 25 2015', 'Sept 20 2015'], ['Sept 21 2015', 'Jul 25 2016'], ['Jul 25 2016', 'Jul 25 2030'] ];
Schedule數組中的每個(gè)元素代表一個(gè)開(kāi)始日期和一個(gè)結束日期。如上所述,它可以包含時(shí)間和時(shí)區,但我在這里使用了普通的日期,以保持代碼的可讀性。
最后,當用戶(hù)加載頁(yè)面時(shí),我們需要檢查是否在指定的時(shí)間范圍內。此代碼應替換先前對 initializeClock 函數的調用:
// 遍歷schedule中的每個(gè)元素 schedule.forEach(([startDate, endDate]) => { // 以毫秒為單位放置日期以便于比較 const startMs = Date.parse(startDate); const endMs = Date.parse(endDate); const currentMs = Date.parse(new Date()); // 如果當前日期在開(kāi)始日期和結束日期之間,則顯示時(shí)鐘 if (endMs > currentMs && currentMs >= startMs ) { initializeClock('clockdiv', endDate); } });
現在,你可以提前安排你的時(shí)鐘,而不必手動(dòng)更新它。如果你愿意,你可以縮短代碼。為了便于閱讀,我把我的代碼寫(xiě)得很啰嗦。
8.2 從用戶(hù)到達起將計時(shí)器設置為10分鐘
用戶(hù)到達或開(kāi)始特定任務(wù)后,有必要在給定的時(shí)間內設置倒計時(shí)。我們將在此處將計時(shí)器設置為10分鐘,但是你可以使用任意時(shí)間。
我們需要做的就是用以下命令替換 deadline 變量:
const timeInMinutes = 10; const currentTime = Date.parse(new Date()); const deadline = new Date(currentTime + timeInMinutes*60*1000);
這段代碼以當前時(shí)間為基準,增加10分鐘。這些值將轉換為毫秒,因此可以將它們加在一起并變成新的截止日期。
現在我們有一個(gè)時(shí)鐘,從用戶(hù)到達時(shí)開(kāi)始倒計時(shí)十分鐘,你可以自由發(fā)揮,嘗試不同的時(shí)間長(cháng)度。
8.3 跨頁(yè)面保持時(shí)鐘進(jìn)度
有時(shí),除了當前頁(yè)面外,還需要保留時(shí)鐘狀態(tài)。如果我們想在整個(gè)網(wǎng)站上設置10分鐘的計時(shí)器,則我們不希望在用戶(hù)轉到其他頁(yè)面時(shí)重置該計時(shí)器。
一個(gè)解決方案是將時(shí)鐘的結束時(shí)間保存在一個(gè)cookie中。這樣一來(lái),導航到一個(gè)新的頁(yè)面就不會(huì )把結束時(shí)間重置到十分鐘以后。
這是邏輯:
如果Cookie中記錄了截止日期,使用該截止日期。
如果不存在Cookie,請設置一個(gè)新的截止日期并將其存儲在Cookie中。
要實(shí)現這一點(diǎn),請使用以下命令替換 deadline 變量:
let deadline; // 如果有一個(gè)名為myClock的cookie,則使用該值作為截止日期 if(document.cookie && document.cookie.match('myClock')){ // 從Cookie獲取截止日期值 deadline = document.cookie.match(/(^|;)myClock=([^;]+)/)[2]; } else { // 否則,請設置從現在開(kāi)始10分鐘的截止日期, // 將其保存在具有該名稱(chēng)的cookie中 // 創(chuàng )建從現在開(kāi)始10分鐘的截止日期 const timeInMinutes = 10; const currentTime = Date.parse(new Date()); deadline = new Date(currentTime + timeInMinutes*60*1000); // 將截止日期存儲在cookie中以供將來(lái)引用 document.cookie = 'myClock=' + deadline + '; path=/; domain=.yourdomain.com'; }
需要注意的是,你需要將 .yourdomain.com 改為你的實(shí)際域名。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站