基于RequestAnimationFrame实现高精度毫秒级正向计时器

最近做了一个周末嘉年华的活动【免费领取「王者荣耀千元账号」】,效果图如下。玩法也很简单:点击开始,计时器开始计时,点击停止,点击开始按钮后会变成停止,当计时结束时,秒表显示时间为 10:00 时,即可获取 「价值千元的王者荣耀账号」!,图片,编组,点我体验 !!!,若遇到活动未开始或者活动结束,可以前往转转app搜索【游戏】即可参与更多活动,各种福利拿到手软!,从图上可以看出来,核心就是一个正向计时器。通过js实现一个普通的正向计时器很简单,大多数想到都是使用setInterval来实现。那么还有没有其他的实现方式呢?又怎么去实现一个高精度的毫秒级正向计时器呢?,最近看了vant4的倒计时组件的源码,发现其并没有使用setInterval, 而是封装了requestAnimationFrame 和利用 Date.now()来处理毫秒级渲染和倒计时实现。那么能不能通过requestAnimationFrame来实现一个正向计时器呢?,先看看效果图,接下来将会一步步去实现:,图片,体验地址: https://suyxh.github.io/timer-demo/,首先呢,来看看使用setInterval是如何实现的。在网上看了很多文章,大多都是使用的 setInterval 去实现,大致效果如下:,图片,setinterval,从效果图上我们可以发现,最后一位始终为0,甚至还是有些小bug,很明显不是我们想要的。具体代码如下:,上文中提到vant的CutDown组件,主要就是利用 Date.now() 会自己走的原理,结合 requestAnimationFrame 去做时间计算;那么正向计时器则是利用了 requestAnimationFrame 回调函数的参数去做时间计算,从而实现毫秒级的计时器。,「window.requestAnimationFrame()」 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行,当你准备更新动画时你应该调用此方法。这将使浏览器在下一次重绘之前调用你传入给该方法的动画函数 (即你的回调函数)。,
,「注意:」 若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用 window.requestAnimationFrame(),MDN requestAnimationFrame,一个 long 整数,请求 ID,是回调列表中唯一的标识。是个非零值,没别的意义。你可以传这个值给 window.cancelAnimationFrame() 以取消回调函数。,通过 requestAnimationFrame API可以知道,回调函数中的参数就是一个 DOMHighResTimeStamp参数,该参数与performance.now()的返回值相同,它表示requestAnimationFrame() 开始去执行回调函数的时刻。,那我们直接使用该值不就可以了吗?试试看:,效果如下:,图片,测试版,虽然比较简陋,但是并没有出现 setInterval版 的bug,接下来在一步步优化。,我们加上格式化时间的函数 parseTime() 和 parseFormat(), 代码如下:,效果如下:,图片,简易版,又看到了我们熟悉的时间格式啦, 格式化的方法也是来源于vant的CutDown组件中的格式化代码!,格式化虽然是完成了,但是怎么去停止呢?能不能支持暂停、继续、重置呢?,接下来继续完善。,我们直接通过 window.cancelAnimationFrame() 去取消回调函数即可!在 useCountUp函数中添加一下 pause 即可!,效果如下:,图片,进阶版,不少的小伙伴已经发现,停止虽然是没问题了,当再次点击开始的时候,时间怎么不对了?有瑕疵!,因为我们少算补时时间,做如下修改,添加startTime 、 stopTime 和  goOn 方法:,这里基本上已经完成了暂停和继续的功能了,但是仍是有些bug的,可以多次点击继续试试 。,接下来,我们来修复上述的bug,方法:添加一个变量来表示当前计时器的状态。,在增加几个新功能:,核心代码如下,其他部分代码不变:,到此基本上就是实现了一个毫秒级的正向计时器!,只是对js的逻辑进行了一些封装,代码:https://github.com/SuYxh/timer-demo,预览:https://suyxh.github.io/timer-demo/,正向毫秒级计时器主要就是利用了window.requestAnimationFrame的回调函数的参数为DOMHighResTimeStamp,且与performance.now()的返回值相同;在实现暂停、继续时,需要计算一下补时时间。

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/18066.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34