Twlig / issuesBlog

MIT License
3 stars 0 forks source link

倒计时 #74

Open Twlig opened 2 years ago

Twlig commented 2 years ago

为页面设置多个倒计时

<body style="height: 1000px">

<div id="container">
    <div class="item item-1">1</div>
    <div class="item item-2">2</div>
    <div class="item item-3">3</div>
    <div class="item item-3">4</div>
</div>

</body>
<script>
    let timeDom = function (id, time) {  //工厂模式,生成新对象
        let item = new Object({
            id: id,  //DOM节点
            time: new Date(time).getTime(),  //把传入结束时间单位转化成毫秒
            leftTime: undefined,   //剩余时间
            dd: undefined,  //根据剩余时间计算出来,倒计时的天数
            hh: undefined, //根据剩余时间计算出,倒计时小时
            mm: undefined, //分钟
            ss: undefined //秒
        })
        return item
    }
    const domList = document.getElementsByClassName('item')
    const time = ['2022-03-27 16:52:00', '2022-03-27 16:55:00', '2022-03-27 16:53:00','2022-03-27 16:54:00']
    timeDomList = Array.prototype.map.call(domList, (item,index) => timeDom(item, time[index])) //为四个DOM节点传入时间参数,并生成新对象

    function zeroP(n) {  //小于10,添0
        n = parseInt(n, 10);
        return n > 0 ? n < 9 ? ('0'+n) : (n+'') :'00';
    }

    function getFormat(item) {  //根据剩余时间(毫秒),得到剩余天数,小时,分钟,秒
        let leftTime = item.leftTime
        item.dd = zeroP(Math.floor(leftTime/(1000*60*60*24)))
        item.hh = zeroP(Math.floor(leftTime/(1000*60*60)%24))
        item.mm = zeroP(Math.floor(leftTime/(1000*60)%60))
        item.ss = zeroP(Math.floor(leftTime/(1000)%60))
    }

    //计时器逻辑
    function countDown(item, interval) {
        let timer = null
        let startTime = new Date().getTime()  //获取计时最开始的时间
        let count = 1  //计时次数
        function fn() {
            let now = Date.now()
            item.leftTime = item.time - now  //结束时间减去当前时间,得到剩余时间
            if(item.leftTime > 0) {
                let idealTime = count*interval  //执行到此处,预期总花费的时间
                let realTime = now - startTime  //实际的花费的时间
                let nextTime = interval - (realTime - idealTime)  //预期-实际=偏差时间,用定时间隔减去偏差,矫正此次的时间偏差
                count++ //计时次数加1
                if(nextTime < 0) { //如果计算出来的定时时间小于0,则立即加入宏任务事件队列
                    nextTime = 0
                }
                console.log(nextTime)
                getFormat(item) //格式化时间
                item.id.innerHTML = '还剩' + item.dd + '天' + item.hh + '时' + item.mm + '分' + item.ss + '秒'  //在DOM上绘制相应信息
                timer = setTimeout(fn, nextTime)  //设置定时器
            }else {
                item.id.innerHTML = '活动结束'
                clearTimeout(timer)
            }
        }
        fn()
    }
    timeDomList.forEach(item => { //遍历节点对象,为每一个对象计时
        countDown(item, 1000)
    })
</script>

思路:

还可以采用requestAnimationFrame屏幕刷新频率1秒60帧,或者Web Worker子线程。

参考文章: