requestAnimationFrame进行循环渲染和事件触发限频

定义

requestAnimationFrame的作用是告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。回调函数一般一秒内执行60次,与屏幕刷新频率相同。

requestAnimationFrame的优势

一般来说,如果想要在网页上展示流畅的动画效果,动画的渲染帧率和用户的屏幕刷新率应当保持一致(一般为每秒60帧)。如果动画的帧率低于屏幕刷新率,那么会出现丢帧的问题,具体表现为页面卡顿。下图中位于两次渲染之间的空白帧就是一个page jank(页面垃圾),动画在此处会出现卡顿。
在这里插入图片描述
即使做到渲染操作与屏幕刷新保持一致,这些计算仍在主线程上运行,这意味着当应用程序运行JavaScript时,渲染流程可能会被阻塞,具体如下图所示,在JS执行的过程中,动画渲染被阻塞,导致出现大量的页面垃圾。
在这里插入图片描述
更好的方式是将JS运算切成很多小分片,并使用requestAnimationFrame()来安排它们在帧间空白时间内运行(图中的黄色块),避免其长时间阻塞渲染进程。
在这里插入图片描述

与setInterval、setTimeout的比较

requestAnimationFrame可以减少setInterval、setTimeout带来的跳帧、闪烁和画面割裂,提高动画的质量。

  • 画面割裂:在显示扫描过程中途向显示缓冲区显示新的画布缓冲区时,由于动画位置不匹配而导致画面出现剪切线。
  • 闪烁:在完全渲染画布之前将画布缓冲区呈现给显示缓冲区时,会导致闪烁
  • 跳帧:当渲染帧之间的时间与显示硬件不精确同步时,会导致跳帧。大多数设备的帧率是每秒60帧(或多倍),从而每16.666 … ms产生一个新帧,而计时器setTimeoutsetInterval使用整数值,它们永远无法与设备帧率完美匹配

动画循环渲染

let lastRenderTimestamp = null
let drawTimer = null
let renderFPS = 1 / 60

function render(timestamp) {
	if (lastRenderTimestamp && timestamp - lastRenderTimestamp < renderFPS) {
		return;
	}
	lastRenderTimestamp = timestamp;
	// render something
	drawTimer = window.requestAnimationFrame(render)
}
drawTimer = window.requestAnimationFrame(render)

// 如果想结束渲染
window.cancelAnimationFrame(drawTimer)

事件触发限频

let needRun = true

function update() {
	needRun = true
	// run event handler
}

window.addEventListener('mousemove', (e) => {
	if (needRun) {
	    needRun = false
		window.requestAnimationFrame(update)
	}
}, false)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZTao-z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值