移动端CSS动画卡顿怎么办?

设计师利娟 阅读 3

我在做一个移动端的下拉刷新动画,用的是CSS的transform和transition,但在安卓机上特别卡,iOS还好一点。我试过加了will-change: transform,也用了translateZ(0)开启硬件加速,但效果不明显。

JS部分是监听touchmove事件动态设置transform的值,代码大概这样:

element.style.transform = <code>translateY(${offset}px)</code>;
if (offset > 60) {
  refreshIndicator.classList.add('active');
}

是不是这种频繁操作DOM的方式本身就容易掉帧?有没有更好的做法?

我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
瑞琴酱~
这个问题很常见,touchmove事件的触发频率太高了,每帧都去操作DOM确实容易掉帧。

你现在的做法有个坑:touchmove过程中不要加transition。transition是用于动画平滑过渡的,但你在touchmove里每帧都在改transform值,这时候transition反而会帮倒忙,导致动画卡顿和抖动。

核心解决方案是把这事分开处理:

触摸过程中(touchmove),直接设置transform的值,不要有任何过渡效果。只有在松手(touchend)需要回弹或者触发刷新的时候,才加上transition让它平滑过渡。

还有一个更彻底的做法是把坐标更新放到requestAnimationFrame里,避免每次touchmove都触发重绘:

let pendingUpdate = false;
let currentOffset = 0;

function updateTransform() {
element.style.transform = translateY(${currentOffset}px);
if (currentOffset > 60) {
refreshIndicator.classList.add('active');
}
pendingUpdate = false;
}

element.addEventListener('touchmove', (e) => {
currentOffset = e.touches[0].clientY - startY;

if (!pendingUpdate) {
pendingUpdate = true;
requestAnimationFrame(updateTransform);
}
});

element.addEventListener('touchend', () => {
element.style.transition = 'transform 0.3s ease';
// 回弹逻辑...
});


另外,will-change和translateZ(0)这种优化手段,对你这种场景帮助有限,因为瓶颈不在渲染层合成,而在JS和DOM交互的频率上。

如果还想进一步优化,可以考虑用CSS变量代替直接操作style:

element.style.setProperty('--offset', ${offset}px);


然后CSS里用var(--offset),但这样其实提升不大,requestAnimationFrame方案基本够用了。
点赞
2026-03-12 14:08