Skip to content

倒计时 #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Twlig opened this issue Mar 27, 2022 · 0 comments
Open

倒计时 #74

Twlig opened this issue Mar 27, 2022 · 0 comments

Comments

@Twlig
Copy link
Owner

Twlig commented Mar 27, 2022

为页面设置多个倒计时

<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子线程。

参考文章:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant