移动端JS动画用requestAnimationFrame还是卡顿怎么办?

闲人子香 阅读 65

我用JS写了一个移动端的进度条动画,用requestAnimationFrame循环更新,但在手机上滑动页面时动画会卡顿。已经试过把动画层设为fixed定位,也给元素加了will-change: transform,但问题依旧存在。


<div class="progress-bar" style="width: 0"></div>

<script>
let progress = 0;
function animate() {
  const bar = document.querySelector('.progress-bar');
  bar.style.width = progress + '%';
  progress += 0.5;
  requestAnimationFrame(animate);
}
animate();
</script>

是不是因为每次循环都用querySelector导致性能问题?或者移动端对requestAnimationFrame的刷新频率有特殊限制?

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
司马树甜
querySelector每次循环都查太耗性能了,改成缓存元素引用。另外移动端requestAnimationFrame在页面滚动时确实会降频,建议改成CSS动画或者用transform代替width属性更新。

const bar = document.querySelector('.progress-bar');
let progress = 0;
function animate() {
bar.style.transform = scaleX(${progress / 100});
progress += 0.5;
requestAnimationFrame(animate);
}
animate();
点赞 10
2026-02-05 10:03
❤金静
❤金静 Lv1
你这问题很常见,主要原因有两个:

1. querySelector 每次都查DOM,性能浪费
2. 动画逻辑和渲染没分离,主线程被拖慢

### 改进点:
- 把 querySelector 提前缓存
- 用 transform 替代 width,减少重排
- 用 translateZ(0) 触发GPU加速(比 will-change 更轻量)

下面是优化后的代码:

const bar = document.querySelector('.progress-bar');
let progress = 0;

function animate() {
bar.style.transform = scaleX(${progress / 100});
progress += 0.5;
if (progress <= 100) {
requestAnimationFrame(animate);
}
}

// 启动动画
requestAnimationFrame(animate);


### 样式部分也加上:
.progress-bar {
transform-origin: left;
will-change: transform;
/* 或者用下面这句更轻量 */
/* transform: translateZ(0); */
}


这样改完动画会顺滑很多。如果还卡,说明你的页面还有别的重绘重排大户,得用 Performance 工具查具体瓶颈。
点赞 11
2026-02-04 21:02