Android Chrome中requestAnimationFrame调用60次/秒但渲染仅30FPS问题咨询
为什么requestAnimationFrame调用次数和实际渲染次数不一致
requestAnimationFrame(以下简称rAF)的触发频率和实际屏幕上屏帧率是两个独立的统计维度,出现差异的核心原因有两个:
- 安卓Chrome的动态功耗调节策略:绝大多数安卓设备默认开启自适应刷新率,系统和浏览器会根据当前显示内容的优先级动态调整屏幕刷新率,静态内容、低优先级动画会被限制在30FPS以降低功耗,只有视频、交互类动画等场景才会拉高到60FPS及以上。你提供的最小demo绘制内容固定不变,Chrome会判定为低优先级动画,自动压低渲染帧率。
- 重复帧跳过机制:如果浏览器检测到前后两帧的视觉内容完全没有变化,会直接丢弃当前帧,不会提交到合成线程上屏,你当前的demo每帧都在同一位置绘制相同颜色的10x10方块,前后帧没有差异,大量重复帧被跳过,自然无法达到60FPS的上屏帧率。
- 额外注意:如果设备开启了全局省电模式,会强制所有应用锁30FPS,也会出现这个问题。
如何实现60FPS正常渲染
按照以下优先级排查修改即可:
- 先关闭设备的省电模式,在系统显示设置中把屏幕刷新率固定为60Hz,关闭自适应/智能刷新率选项,排除系统层面的帧率限制。
- 保证每帧有明确的视觉变化,避免重复帧被丢弃。你的demo可以修改为清屏后绘制动态变化的内容,示例代码如下:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); ctx.fillStyle = 'red'; // 用偏移量让每帧绘制内容产生变化 let offsetX = 0; var loop = function() { // 清空上一帧内容 ctx.clearRect(0, 0, canvas.width, canvas.height); // 更新绘制坐标 offsetX = (offsetX + 2) % canvas.width; ctx.fillRect(offsetX, 0, 10, 10); requestAnimationFrame(loop); } loop();
- 给Canvas元素添加
will-change: transformCSS属性,主动提示浏览器该元素会持续产生动画,需要优先分配高刷新率资源,避免浏览器主动压低帧率。 - 测试阶段移除不必要的
console.log调用,频繁的日志输出会占用主线程资源,极端情况下也会影响合成线程调度,导致帧率下降。
内容的提问来源于stack exchange,提问作者laltin
相关产品推荐
相关产品推荐

