requestanimationframe是唯一原生匹配屏幕刷新率的html函数,自动对齐60hz/90hz/120hz等物理刷新节奏;需闭环调用、用时间戳计算匀速运动,并避免强制同步布局以保障高刷屏流畅性。

requestAnimationFrame 是唯一需要匹配刷新率的 HTML 函数
其他所谓“HTML函数工具”都不直接感知或依赖屏幕刷新率;只有 requestAnimationFrame 由浏览器原生调度,自动对齐当前显示器的物理刷新节奏(60Hz、90Hz、120Hz 等)。你不需要为不同刷新率选不同工具,但必须正确使用它——否则高刷屏反而更卡。
- 错误做法:用
setTimeout模拟帧率,比如setTimeout(draw, 16),这在 120Hz 屏上会频繁错帧或挤帧 - 正确做法:每次
requestAnimationFrame回调结束前,必须再次调用它,形成闭环,例如:function animate() { /* 绘制逻辑 */ requestAnimationFrame(animate); } - 注意:回调参数是高精度时间戳(
DOMHighResTimeStamp),不是帧序号,需用它计算匀速位移,而非假设每帧固定间隔
高刷屏下 DOM 读写顺序比函数选择更重要
刷新率越高,每帧可用时间越短(120Hz ≈ 8.3ms),而 DOM 读操作(如 offsetTop、getBoundingClientRect())会强制触发同步 layout,极易超时掉帧。此时问题不在“用什么函数”,而在“怎么组织结构”。
- 避免读写穿插:不要在同帧内先读
el.offsetTop,再立刻改el.style.transform;应批量读取后统一写入 - 预设尺寸:图片、卡片、动态列表容器必须带
width/heightHTML 属性或 CSSmin-height,防止加载时重排打断 rAF 节奏 - 语义收敛:
<main></main>必须顶层独立,不能嵌套在<header></header>或<footer></footer>内,否则某些 WebView 下offsetTop返回值不可靠,导致反复校验拖慢帧率
Canvas 动画必须配合 clearRect 和 beginPath
当 requestAnimationFrame 驱动 Canvas 动画时,刷新率变化本身不改变渲染逻辑,但高刷屏放大了路径残留和清除遗漏的问题——旧图形未清、新路径连旧线,视觉上就是重影或错位。
- 每次动画帧开始前,必须调用
ctx.clearRect(0, 0, canvas.width, canvas.height),不能只靠canvas.width = canvas.width(会重置所有状态,包括字体、缩放) - 每次绘制独立图形前,必须调用
ctx.beginPath();漏掉它会导致后续lineTo()自动连接上一路径终点,产生意外连线 - 如果使用
ctx.drawImage()渲染视频帧或纹理,注意其默认不缩放,需显式传入目标宽高,否则在高刷屏滚动中易出现采样撕裂
Windows 上 WebView2 工具需确认是否启用 vsync
在 Windows 原生应用中嵌入 HTML 函数工具(如基于 WebView2 的桌面端工具),其 requestAnimationFrame 是否真正对齐显示器刷新,取决于 WebView2 运行时是否启用垂直同步(vsync)。默认开启,但部分旧版 SDK 或企业策略可能禁用。
- 检查方式:在 WebView2 控制台运行
console.log(window.devicePixelRatio, performance.timeOrigin),连续拖动窗口观察时间戳增量是否稳定接近 16.7ms(60Hz)或 8.3ms(120Hz) - 若增量跳变剧烈(如 5ms / 20ms 交替),说明 vsync 未生效,需升级 WebView2 Runtime 至 1.0.2241.44 或更高版本
- 不建议手动 patch:不要用
SetTimer或PostMessage替代requestAnimationFrame,这会绕过浏览器合成器管线,失去硬件加速与节流能力
高刷屏适配真正的难点,从来不是选哪个函数,而是让整个 HTML 结构、CSS 尺寸约束和 JS 执行节奏全部收敛到浏览器渲染管线里——requestAnimationFrame 只是那个暴露问题的开关。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











