今天要来做一个倒数计时器,首先我们先将所有的 buttons
都监听起来,在点击后,抓到设置的时间并当成参数传入 timer()
,再抓到要显示的区域。
const timerButtons = document.querySelectorAll('.timer__button');
const displayTimeLeft = document.querySelector('.display__time-left');
const displayEndTime = document.querySelector('.display__end-time');
function timerStart() {
const timeDiff = Number(this.dataset.time);
timer(timeDiff);
}
timerButtons.forEach(btn => btn.addEventListener('click', timerStart));
接着我们要设置一秒一次的计时器 timer
, 我们目前掌握两件事「显示剩余时间」(一秒一次) 和「显示结束时间」(一次),全部都用毫秒来算才不用判别进位问题。如果剩余秒数小于 0,就清掉计时器并 return
。
function timer(timeDiff) {
const now = new Date().getTime(); //取得1970到现在的毫秒
const nowSec = Math.round(now / 1000); //换成秒
const endMillionSec = (nowSec + timeDiff) * 1000; //结束毫秒数
showTimeLeft(timeDiff); //显示剩余时间
showEndTime(endMillionSec); //显示结束时间
let countDown = setInterval(function () {
secondLeft = Math.round((endMillionSec - Date.now()) / 1000);
if (secondLeft < 0) {
clearInterval(countDown);
return;
}
showTimeLeft(secondLeft); //刷新剩余时间
}, 1000);
}
写完上列代码,还不会跑起来,先把 showEndTime()
注解掉,我们先来处理 showLeftTime()
,首先我们将传进去的秒数整理成分跟秒,最后再渲染上 html
function showTimeLeft(secondLeft) {
const minLeft = Math.floor(secondLeft / 60);
secondLeft %= 60;
const timeLeft = `${minLeft}:${secondLeft}`;
displayTimeLeft.textContent = timeLeft;
}
处理完后会发现如果连续点击时间按钮会有多个计时器在计时,显示剩余时间会跳来跳去。
这时候要修改一下,每次在设置 timer 时,先把计时器清掉。因此必须在 function
外声明,不然会找不到 countDown
这个变量。
let countDown; //在外面声明
function timer(timeDiff) {
clearInterval(countDown);//清掉计时器
const now = new Date().getTime();
const nowSec = Math.round(now / 1000);
const endMillionSec = (nowSec + timeDiff) * 1000;
showTimeLeft(timeDiff);
showEndTime(endMillionSec);
countDown = setInterval(function () { //不需要声明
secondLeft = Math.round((endMillionSec - Date.now()) / 1000);
if (secondLeft < 0) {
clearInterval(countDown);
return;
}
showTimeLeft(secondLeft);
}, 1000);
}
接着我们要显示截止时间new Date(value)
,放入结束毫秒的 value ,即可拿到结束的时间。
再将时间渲染上去。
function showEndTime(endMillionSec) {
const end = new Date(endMillionSec)
let endHr = end.getHours();
let endMin = end.getMinutes();
const endTime = `计时器将在${endHr}:${endMin}到期`;
displayEndTime.textContent = endTime;
}
现在可以来跑看看成果了!会发现还是有问题,当秒针是个位数的时候显示的不是两位数。
因此我们要判断当秒数小于 10 的时候,会在前面补 0。
function showTimeLeft(secondLeft) {
...
const timeLeft = `${minLeft}:${secondLeft < 10 ? '0': ''}${secondLeft}`;
displayTimeLeft.textContent = timeLeft;
}
function showEndTime(endMillionSec) {
...
const endTime = `计时器将在${endHr}:${endMin < 10 ? '0':''}${endMin}到期`;
displayEndTime.textContent = endTime;
}
最后我们要监听submit
事件,要注意的是 submit 事件只有在 form 元素有效, input[type=text]
元素不能被监听 submit 事件,当 submit 事件发生,截取输入值并运行计时器
const minInput = document.querySelector('#custom');
function showEndTime(endMillionSec) {
minInput.addEventListener('submit', function (e) {
e.preventDefault();
const timeDiff = this.minutes.value;
timer(timeDiff * 60);
this.reset();
});
}
,