18行JavaScript代碼構建一個倒數計時器

18行JavaScript代碼構建一個倒數計時器


在這裏插入圖片描述
有時,您將需要構建一個JavaScript倒數時鐘。您可能有活動,銷售,促銷或遊戲。您可以使用原始JavaScript構建時鐘,而不用尋找最近的插件。雖然有很多很棒的時鐘插件,但是使用原始JavaScript可以帶來以下好處:

  • 您的代碼將是輕量級的,因爲它將具有零依賴性。
  • 您的網站將表現更好。您無需加載外部腳本和樣式表。
  • 您將擁有更多控制權。您將構建時鐘,使其行爲完全符合您希望的方式(而不是嘗試將插件彎曲到您的意願)

因此,事不宜遲,這裏介紹瞭如何僅用18行JavaScript來製作自己的倒計時時鐘。

基本時鐘:倒數到特定的日期或時間

  • 設置有效的結束日期。
  • 計算剩餘時間。
  • 將時間轉換爲可用格式。
  • 將時鐘數據輸出爲可重複使用的對象。
  • 在頁面上顯示時鐘,並在時鐘爲零時停止時鐘。

設定有效的結束日期

首先,您需要設置一個有效的結束日期。這應該是JavaScript的Date.parse()方法可以解析的任何格式的字符串。例如:

1、在ISO 8601格式:

const deadline = '2015-12-31';

2、簡短格式:

const deadline = '31/12/2015';

3、或者,長格式:

const deadline = 'December 31 2015';

4、這些格式中的每一種都允許您指定確切的時間和時區(對於ISO日期,則爲UTC的偏移量)。例如:

const deadline = 'December 31 2015 23:59:59 GMT+0200';

計算剩餘時間

下一步是計算剩餘時間。我們需要編寫一個函數,該函數需要一個表示給定結束時間的字符串(如上所述)。然後,我們計算該時間與當前時間之間的時差。看起來像這樣:

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
  };
}

首先,我們創建一個變量total,以保留剩餘時間直到截止日期。該Date.parse()函數將時間字符串轉換爲毫秒值。這使我們可以相減兩次,並獲得兩者之間的時間量。

const total = Date.parse(endtime) - Date.parse(new Date());

將時間轉換爲可用格式

現在,我們要將毫秒轉換爲天,小時,分鐘和秒。讓我們以秒爲例:

const seconds = Math.floor( (t/1000) % 60 );

讓我們分解一下這裏發生的事情。

  • 將毫秒除以1000可轉換爲秒:(t/1000)
  • 將總秒數除以60,然後取餘數。您不希望所有的秒數,僅需要計算分鐘數之後剩下的秒數:(t/1000) % 60
  • 四捨五入到最接近的整數。這是因爲您需要完整的秒數,而不是幾分之一秒:Math.floor( (t/1000) % 60 )
    重複此邏輯,將毫秒轉換爲分鐘,小時和天。

輸出時鐘數據作爲可重用對象

準備好幾天,幾小時,幾分鐘和幾秒鐘之後,我們現在可以將數據作爲可重用的對象返回:

getTimeRemaining(deadline).minutes

顯示時鐘並在達到零時停止

現在,我們有了一個可以花費剩餘的天,小時,分鐘和秒的功能,我們可以構建時鐘了。首先,我們將創建以下HTML元素來保存時鐘:

<div id="clockdiv"></div>

然後,我們將編寫一個在新div中輸出時鐘數據的函數:

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);
}

該函數有兩個參數。這些是包含我們時鐘的元素的ID,以及倒計時的結束時間。在函數內部,我們將聲明一個clock變量並將其用於存儲對我們的時鐘容器div的引用。這意味着我們不必繼續查詢DOM。

接下來,我們將使用setInterval每秒執行一個匿名函數。此功能將執行以下操作:

  • 計算剩餘時間。
  • 將剩餘時間輸出到我們的div。
  • 如果剩餘時間爲零,請停止計時。

此時,剩下的唯一步驟是像這樣運行時鐘:

initializeClock('clockdiv', deadline);

恭喜你!現在,您僅用18行JavaScript就擁有了一個基本時鐘。

準備顯示時鐘

在設置時鐘樣式之前,我們需要進行一些細化。

  • 消除初始延遲,使您的時鐘立即顯示。
  • 提高時鐘腳本的效率,以免持續重建整個時鐘。
  • 根據需要添加前導零。

消除初始延遲

在時鐘中,我們習慣於setInterval每秒更新一次顯示。多數情況下,這很好,除非在開始時會有一秒鐘的延遲。要消除此延遲,我們必須在間隔開始之前更新一次時鐘。

讓我們將要傳遞給setInterval它的匿名函數移到其自己的獨立函數中。我們可以命名這個函數updateClock。在updateClock外部調用該函數setInterval,然後在內部再次調用setInterval。這樣,時鐘顯示就沒有延遲了。

在您的JavaScript中,替換爲:

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(); // run function once at first to avoid delay
var timeinterval = setInterval(updateClock,1000);

避免持續重建時鐘

我們需要使時鐘腳本更高效。我們只想更新時鐘中的數字,而不是每秒重新構建整個時鐘。實現此目的的一種方法是將每個數字放在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');

接下來,我們需要更改updateClock功能以僅更新數字。新代碼如下所示:

function updateClock(){
    const t = getTimeRemaining(endtime);

    daysSpan.innerHTML = t.days;
    hoursSpan.innerHTML = t.hours;
    minutesSpan.innerHTML = t.minutes;
    secondsSpan.innerHTML = t.seconds;

    ...
}

添加前導零

現在時鐘不再每秒都在重建,我們還有另一件事要做:添加前導零。例如,不是讓時鐘顯示7秒,而是顯示07秒。一種簡單的方法是在數字的開頭添加字符串“ 0”,然後切掉最後兩位數字。

例如,要在“ seconds”值上添加前導零,您可以對此進行更改:

secondsSpan.innerHTML = t.seconds;

對此:

secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);

如果需要,您也可以在分鐘和小時中添加前導零。如果您走了這麼遠,恭喜!您的時鐘現在可以顯示了。

注意:您可能需要在CodePen中單擊“重新運行”才能開始倒計時。

自動安排時鐘

假設我們希望時鐘顯示在某些日子,而不是其他日子。例如,我們可能會發生一系列事件,並且不想每次都手動更新時鐘。這是提前安排事情的方法。

通過在CSS中將其display屬性設置爲隱藏時鐘none。然後將以下內容添加到initializeClock函數中(以開頭的行之後var clock)。一旦initializeClock調用此函數,這將導致時鐘僅顯示:

clock.style.display = 'block';

接下來,我們可以指定顯示時鐘的日期。這將替換deadline變量:

const schedule = [
    ['Jul 25 2015', 'Sept 20 2015'],
    ['Sept 21 2015', 'Jul 25 2016'],
    ['Jul 25 2016', 'Jul 25 2030']
];

schedule數組中的每個元素代表一個開始日期和一個結束日期。如上所述,可以包括時間和時區,但是我在這裏使用了簡單的日期來保持代碼的可讀性。

最後,當用戶加載頁面時,我們需要檢查是否在指定的時間範圍內。該代碼應替換先前對該initializeClock函數的調用。

// iterate over each element in the schedule
for (var i=0; i<schedule.length; i++) {
  var startDate = schedule[i][0];
  var endDate = schedule[i][1];

  // put dates in milliseconds for easy comparisons
  var startMs = Date.parse(startDate);
  var endMs = Date.parse(endDate);
  var currentMs = Date.parse(new Date());

  // if current date is between start and end dates, display clock
  if (endMs > currentMs && currentMs >= startMs ) {
    initializeClock('clockdiv', endDate);
  }
}

schedule.forEach(([startDate, endDate]) => {
  // put dates in milliseconds for easy comparisons
  const startMs = Date.parse(startDate);
  const endMs = Date.parse(endDate);
  const currentMs = Date.parse(new Date());

  // if current date is between start and end dates, display clock
  if (endMs > currentMs && currentMs >= startMs ) {
    initializeClock('clockdiv', endDate);
  }
});

現在,您可以提前安排時鐘,而無需手動更新。您可以根據需要縮短代碼。爲了便於閱讀,我讓我變得冗長。

從用戶到達起將計時器設置爲10分鐘

用戶到達或開始特定任務後,有必要在給定的時間內設置倒計時。我們將在此處將計時器設置爲10分鐘,但是您可以使用任意時間。

我們需要做的就是deadline用這個替換變量:

const timeInMinutes = 10;
const currentTime = Date.parse(new Date());
const deadline = new Date(currentTime + timeInMinutes*60*1000);

該代碼將花費當前時間,並增加十分鐘。這些值將轉換爲毫秒,因此可以將它們加在一起並變成新的截止日期。

現在,我們有了一個時鐘,可以從用戶到達時開始倒數十分鐘。隨意玩耍,嘗試不同的時間長度。

跨頁面保持時鐘進度

有時,有必要將時鐘狀態保留的時間不僅限於當前頁面。如果我們要在整個網站上設置10分鐘的計時器,則我們不希望在用戶轉到其他頁面時重置該計時器。

一種解決方案是將時鐘的結束時間保存在cookie中。這樣,導航到新頁面不會將結束時間重置爲現在的十分鐘。

這是邏輯:

  • 如果Cookie中記錄了截止日期,請使用該截止日期。
  • 如果不存在該cookie,則設置一個新的截止日期並將其存儲在cookie中。

要實現這一點,請用deadline以下內容替換變量:

let deadline;

// if there's a cookie with the name myClock, use that value as the deadline
if(document.cookie && document.cookie.match('myClock')){
  // get deadline value from cookie
  deadline = document.cookie.match(/(^|;)myClock=([^;]+)/)[2];
} else {
  // otherwise, set a deadline 10 minutes from now and 
  // save it in a cookie with that name

  // create deadline 10 minutes from now
  const timeInMinutes = 10;
  const currentTime = Date.parse(new Date());
  deadline = new Date(currentTime + timeInMinutes*60*1000);

  // store deadline in cookie for future reference
  document.cookie = 'myClock=' + deadline + '; path=/; domain=.yourdomain.com';
}

這段代碼利用了cookie正則表達式,它們本身就是單獨的主題。因此,我在這裏不再贅述。需要注意的一件事是,您需要更改yourdomain.com爲實際域。

有關客戶端時間的重要警告

avaScript日期和時間是從用戶計算機中獲取的。這意味着用戶可以通過更改計算機上的時間來影響JavaScript時鐘。在大多數情況下,這無關緊要。但是,在某些超級敏感的情況下,有必要從服務器獲取時間。可以使用一些PHP或Ajax來完成,這兩者都超出了本教程的範圍。

從服務器獲取時間後,我們可以使用本教程中的相同技術來使用它。

總結

在閱讀完本文中的示例之後,您現在知道如何僅用幾行原始JavaScript代碼創建自己的倒數計時器!我們已經研究瞭如何製作基本的倒數時鐘並有效顯示它。我們還介紹了添加一些有用的附加功能,包括計劃,絕對時間和相對時間,以及使用Cookie保留頁面和站點訪問之間的狀態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章