后端 JS30

wwwdaoseacom · August 12, 2021 · 0 hits

今天要来做一个倒数计时器,首先我们先将所有的 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();
    });
}

Demo
完整代码


,

/images/emoticon/emoticon32.gif

No Reply at the moment.
You need to Sign in before reply, if you don't have an account, please Sign up first.