H5页面在低端安卓机上卡顿严重怎么办?
我们做的H5活动页在iPhone上挺流畅的,但在一些低端安卓机上滑动特别卡,甚至有白屏。已经试过用transform: translateZ(0)开启硬件加速,但效果不明显。
页面里主要是用CSS3动画做了一些入场效果,还有滚动区域用了overflow: scroll。是不是这些写法有问题?有没有更有效的优化手段?
下面是我们用的一个简单动画片段:
.fade-in {
opacity: 0;
animation: fadeIn 0.6s ease-in forwards;
}
@keyframes fadeIn {
to { opacity: 1; }
}
你那个opacity动画其实还好,问题主要出在滚动区域。overflow: scroll在低端安卓机上很坑,滚动时不断触发重绘,内存小的机器直接炸。
几个有效的优化手段:
滚动区域改成这样试试:
.fade-in {
opacity: 0;
will-change: opacity;
animation: fadeIn 0.6s ease-in forwards;
}
滚动容器加上:
.scroll-container {
overflow-y: scroll; -webkit-overflow-scrolling: touch; / 关键,提升iOS和安卓的滚动体验 /
overscroll-behavior: contain; / 防止滚动穿透 /
}
如果还是卡,把滚动区域的DOM层级拍平,嵌套别太深。低端机最怕的就是复杂嵌套。
动画方面,translateZ(0)这种硬件加速不是不能用,但别满屏乱加,容易吃光内存。只在确实需要加速的元素上加,用完就删:
.el {
will-change: transform;
/ 动画结束后移除 /
}
.el.done {
will-change: auto;
}
如果入场动画还卡得不行,考虑砍掉部分动画效果,或者降级成JS的requestAnimationFrame自己控制,比CSS动画可控多了。
白屏的问题检查一下是不是图片太大或者请求太多,低端机加载不动就卡死在那了。适当压缩图片,首屏需要的资源先加载。
先说你那个动画片段,opacity这个属性在低端机上会触发重绘(repaint),GPU压力很大。改成用transform来做效果会好很多:
.fade-in {
opacity: 0;
transform: translateY(20px);
animation: fadeIn 0.6s ease-out forwards;
}
@keyframes fadeIn {
to {
opacity: 1;
transform: translateY(0);
}
}
或者更激进一点,直接用scale:
.fade-in {
opacity: 0;
transform: scale(0.9);
animation: fadeIn 0.6s ease-out forwards;
}
@keyframes fadeIn {
to {
opacity: 1;
transform: scale(1);
}
}
关于你试的translateZ(0)没效果的问题,这个东西不是万金油,用错了反而增加负担。正确用法是在动画元素上加will-change: transform,而且提前加、动画结束记得移除,别一直占着。
滚动区域的问题,overflow: scroll在安卓上是有坑的,很多机型支持不好。建议改成overflow: auto让系统自己选滚动方式。如果滚动区域内容多,可以考虑用better-scroll或者IScroll这些库,它们对安卓的兼容性处理得更细致。
最后说几点通用的:
一是页面DOM节点数尽量控制,动画元素别太多,有些低端机DOM超过200个节点就开始卡。
二是图片该压缩压缩,能用webp别用png,需要的话加个loading状态,别让用户看到白屏。
三是可以考虑在低端机上直接降级,把那些花哨的入场动画都关掉,用user-agent判断一下机型,做个适配。
总之低端机就一个字:省。能用GPU处理的就别让CPU干,能少渲染一次就少一次。