关于前端:实战仅用18行JavaScript构建一个倒数计时器

25次阅读

共计 6282 个字符,预计需要花费 16 分钟才能阅读完成。

首发于公众号:《前端全栈开发者》
原文:https://www.sitepoint.com
作者:Nilson Jacques

有时候,你会须要构建一个 JavaScript 倒计时时钟。你可能会有一个流动、一个销售、一个促销或一个游戏。你能够用原生的 JavaScript 构建一个时钟,而不是去找一个插件。只管有很多很棒的时钟插件,然而应用原生 JavaScript 能够带来以下益处:

  • 你的代码将是轻量级的,因为它将具备零依赖性。
  • 你的网站将体现得更好。你不须要加载内部脚本和样式表。
  • 你将领有更多的控制权。你将会建设一个齐全依照你的志愿来体现的时钟。

所以,废话不多说,上面是如何在短短的 18 行 JavaScript 中制作本人的倒计时钟。

1. 根本时钟:倒数到特定的日期或工夫

以下是创立根本时钟所需步骤的简要概述:

  • 设置无效的完结日期。
  • 计算剩余时间。
  • 将工夫转换为可用格局。
  • 将时钟数据输入为可重复使用的对象。
  • 在页面上显示时钟,并在时钟为零时进行时钟。

2. 设置无效的完结日期

首先,你须要设置一个无效的完结日期。这应该是 JavaScript 的 Date.parse() 办法能够了解的任何格局的字符串。例如:

ISO 8601 格局:

const deadline = '2015-12-31';

简短格局:

const deadline = '31/12/2015';

或者,长格局:

const deadline = 'December 31 2015';

这些格局中的每一种都容许你指定一个精确的工夫和一个时区(或者在 ISO 日期的状况下指定一个与 UTC 的偏移)。例如:

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

3. 计算剩余时间

下一步是计算剩余时间。咱们须要编写一个函数,该函数须要一个示意给定完结工夫的字符串(如上所述)。而后,咱们计算该工夫与以后工夫之间的时差。看起来像这样:

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

4. 将工夫转换为可用格局

当初咱们要将毫秒转换为天,小时,分钟和秒。让咱们以秒为例:

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

让咱们合成一下这里产生的事件。

  1. 将毫秒除以 1000 可转换为秒:(t/1000)
  2. 将总秒数除以 60,而后取余数。你不须要所有的秒,只须要计算分钟数后剩下的那些:(t/1000) % 60
  3. 四舍五入到最靠近的整数。这是因为你须要残缺的秒数,而不是几分之一秒:Math.floor((t/1000)%60)

反复此逻辑,将毫秒转换为分钟,小时和天。

5. 将时钟数据输入为可重复使用的对象

在筹备好几天,几小时,几分钟和几秒钟之后,咱们当初能够将数据作为可重复使用的对象返回:

return {
  total,
  days,
  hours,
  minutes,
  seconds
};

这个对象容许你调用你的函数,并取得任何计算值。这是如何获取残余分钟数的示例:

getTimeRemaining(deadline).minutes

不便吧?

6. 在页面上显示时钟,并在时钟为零时进行时钟

当初咱们有了一个能够吐出残余天数、小时、分钟和秒数的函数,咱们就能够建设咱们的时钟了。首先,咱们将创立以下 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 就领有了一个根本时钟。

7. 筹备展现你的时钟

在设置时钟款式之前,咱们须要进行一些改良。

  • 打消初始提早,使你的时钟立刻显示。
  • 让时钟脚本更有效率,这样它就不会间断重建整个时钟。
  • 依据须要增加前导零。

7.1 打消初始提早

在时钟中,咱们应用 setInterval 每秒更新一次显示。少数状况下,这很好,除非在开始时会有一秒钟的提早。要打消此提早,咱们必须在距离开始之前更新一次时钟。

让咱们将传递给 setInterval 的匿名函数移到其本人的独自函数中,咱们能够将此函数命名为 updateClock。在 setInterval 外调用一次 updateClock 函数,而后在 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(); // 首先运行一函数能以防止提早
var timeinterval = setInterval(updateClock,1000);

7.2 防止一直重建时钟

咱们须要使时钟脚本更高效,咱们只想更新时钟中的数字,而不是每秒重建整个时钟。实现此目标的一种办法是将每个数字放在 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');

接下来,咱们须要批改 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

当初时钟不再每秒都在重建,咱们还有另一件事要做:增加前导零。例如,不是让时钟显示 7 秒,而是显示 07 秒。一种简略的办法是在一个数的结尾加上一串“0”,而后切掉最初两个数字。

例如,要在“seconds”值上增加前导零,你能够更改以下设置:

secondsSpan.innerHTML = t.seconds;

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

如果你违心,你也能够在分钟和小时的后面加零。如果你曾经走到这一步,祝贺你!你的时钟当初曾经能够显示了。

8. 更进一步

以下示例演示了如何为某些用例扩大时钟。它们都是基于下面的根本例子。

8.1 主动调节时钟

假如咱们想让时钟在特定的日子呈现,而不是在其余的日子。例如,咱们可能有一系列事件行将产生,而不心愿每次都手动更新时钟。以下是如何提前安顿事件的办法。

通过在 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 函数的调用:

// 遍历 schedule 中的每个元素
schedule.forEach(([startDate, endDate]) => {
  // 以毫秒为单位搁置日期以便于比拟
  const startMs = Date.parse(startDate);
  const endMs = Date.parse(endDate);
  const currentMs = Date.parse(new Date());

  // 如果以后日期在开始日期和完结日期之间,则显示时钟
  if (endMs > currentMs && currentMs >= startMs) {initializeClock('clockdiv', endDate);
  }
});

当初,你能够提前安顿你的时钟,而不用手动更新它。如果你违心,你能够缩短代码。为了便于浏览,我把我的代码写得很啰嗦。

8.2 从用户达到起将计时器设置为 10 分钟

用户达到或开始特定工作后,有必要在给定的工夫内设置倒计时。咱们将在此处将计时器设置为 10 分钟,然而你能够应用任意工夫。

咱们须要做的就是用以下命令替换 deadline 变量:

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

这段代码以以后工夫为基准,减少 10 分钟。这些值将转换为毫秒,因而能够将它们加在一起并变成新的截止日期。

当初咱们有一个时钟,从用户达到时开始倒计时十分钟,你能够自由发挥,尝试不同的工夫长度。

8.3 跨页面放弃时钟进度

有时,除了以后页面外,还须要保留时钟状态。如果咱们想在整个网站上设置 10 分钟的计时器,则咱们不心愿在用户转到其余页面时重置该计时器。

一个解决方案是将时钟的完结工夫保留在一个 cookie 中。这样一来,导航到一个新的页面就不会把完结工夫重置到十分钟当前。

这是逻辑:

  1. 如果 Cookie 中记录了截止日期,应用该截止日期。
  2. 如果不存在 Cookie,请设置一个新的截止日期并将其存储在 Cookie 中。

要实现这一点,请应用以下命令替换 deadline 变量:

let deadline;

// 如果有一个名为 myClock 的 cookie,则应用该值作为截止日期
if(document.cookie && document.cookie.match('myClock')){
  // 从 Cookie 获取截止日期值
  deadline = document.cookie.match(/(^|;)myClock=([^;]+)/)[2];
} else {
  // 否则,请设置从当初开始 10 分钟的截止日期,// 将其保留在具备该名称的 cookie 中

  // 创立从当初开始 10 分钟的截止日期
  const timeInMinutes = 10;
  const currentTime = Date.parse(new Date());
  deadline = new Date(currentTime + timeInMinutes*60*1000);

  // 将截止日期存储在 cookie 中以供未来援用
  document.cookie = 'myClock=' + deadline + '; path=/; domain=.yourdomain.com';
}

须要留神的是,你须要将 .yourdomain.com 改为你的理论域名。

9. 无关客户端工夫的重要正告

JavaScript 日期和工夫是从用户的计算机上获取的,这意味着用户能够通过更改计算机上的工夫来影响 JavaScript 时钟。在大多数状况下,这并不重要,但在一些超级敏感的状况下,就须要从服务器上获取工夫。能够应用一些 Node.js 或 Ajax 来实现,这两者都超出了本教程的范畴。

从服务器获取工夫后,咱们能够应用本教程中的雷同技术来应用它。

10. 总结

在实现本文中的示例之后,你当初晓得了如何应用几行简略的 JavaScript 代码创立本人的倒计时计时器!咱们曾经理解了如何制作一个根本的倒计时时钟并无效地显示它。咱们还介绍了增加一些有用的附加性能,包含日程安排、相对工夫与绝对工夫,以及在页面和网站拜访之间用 cookie 保留状态。

下一步是什么?

试着增加一些创意格调,或者新的性能(比方暂停和复原按钮)。之后,如果你想出了任何很酷的时钟例子,你想分享,让咱们在评论区见。

11. 代码

本示例代码和演示地址:https://coding.zhangbing.site


正文完
 0