现在实现倒计时都这么卷了吗?

现在实现倒计时都这么卷了吗?

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

之前写了一篇「三分钟学会使用requestAnimationFrame实现倒计时」文章讲解了如何使用requestAnimationFrame实现倒计时,得到了很多小伙伴的好评,时间是准确了。

但是在校准时间的过程中,为了快速追赶落后的时间,时间跳动太快了,导致体验不太好,体感上感觉这时间不准呀,因此我再在那基础上再优化了一版

为求实现一版超准确!超平稳!性能极好!体验极佳的倒计时

旧版的功能实现代码,demo可点击

const totalDuration = 10 * 1000;
let requestRef = null;
let startTime;
let prevEndTime;
let prevTime;
let currentCount = totalDuration;
let endTime;
let timeDifferance = 0; // 每1s倒计时偏差值,单位ms
let interval = 1000;
let nextTime = interval;

setInterval(() => {
  let n = 0;
  while (n++ < 1000000000);
}, 0);

const animate = (timestamp) => {
  if (prevTime !== undefined) {
    const deltaTime = timestamp - prevTime;
    if (deltaTime >= nextTime) {
      prevTime = timestamp;
      prevEndTime = endTime;
      endTime = new Date().getTime();
      currentCount = currentCount - 1000;
      console.log("currentCount: ", currentCount / 1000);
      timeDifferance = endTime - startTime - (totalDuration - currentCount);
      console.log(timeDifferance);
      nextTime = interval - timeDifferance;
      // 慢太多了,就立刻执行下一个循环
      if (nextTime < 0) {
        nextTime = 0;
      }
      console.log(`执行下一次渲染的时间是:${nextTime}ms`);
      if (currentCount <= 0) {
        currentCount = 0;
        cancelAnimationFrame(requestRef);
        console.log(`累计偏差值: ${endTime - startTime - totalDuration}ms`);
        return;
      }
    }
  } else {
    startTime = new Date().getTime();
    prevTime = timestamp;
    endTime = new Date().getTime();
  }
  requestRef = requestAnimationFrame(animate);
};

requestRef = requestAnimationFrame(animate);

复制代码

然后有个细小的问题在于这段代码

// 慢太多了,就立刻执行下一个循环
if (nextTime < 0) {
    nextTime = 0;
}
复制代码

问题在于,假如遇到线程阻塞的情况,出现了倒计时落后情况严重,假设3s,我这里设置下一个循环是0s,然后现在倒计时当前15s,就会看到快速倒计时到12s,产品同学说你这倒计时还怎么加速了呀

这倒计时加速像极了职业生涯结束在加速倒计时一样,瑟瑟发抖的我立刻赶紧修复一下

其实很简单,就是把这个临近值0设置接近每次循环的时间数即可,那么其实是看不出来每次是有在稍微加速/减速的,这里每次循环的时间数是1s,那么我们可以将上面这段代码修改下,把以前立刻就追赶描述的操作,放缓一下追赶的脚步,以此优化用户体验

例如以前追赶2s3s~4s内立刻追赶上,那么波动是很明显的,但是如果把2s的落后秒数,平躺到接下来要倒计时的1min里,每次大概追赶30ms,那是看不出来滴

// 慢到一定临界点,比正常循环的时间数稍微慢点,再执行下一个循环
if (nextTime < 900) {
    nextTime = 900;
}
复制代码

这里我设置落后太多时,每秒追赶100ms,假如落后2s20s后就能追赶回来啦,而且看不出明显波动,时间又是被校验准确的,得到了产品同学的好评!

虽然修改很小,但是也是反复思考得到的~如果对时间要求比较严格,而且倒计时时间范围比较小,来不及把差距平摊到这么大的时间段,可建议让后端同学定时推送最新的倒计时给前端来校验时间准确性,这就万无一失啦

结语

以上是我使用requestAnimationFrame实现倒计时功能反复雕琢的心得,希望能对大家有帮助~如果能获得一个小小的赞作为鼓励会十分感激!!

更多文章推荐:

「不再迷茫!看了这篇文章让你上手Vue3.0开发有丝滑般体验」

「看一眼,Vue3 script-setup语法糖下组件通信就学会了(附源码)」

「超详细!监听微信小程序五种切后台情况」

分类:
前端