Chrome 下动画卡顿问题的另一种可能

时间:2024-03-08 11:20:09

【现象】

动画出现了明显的卡顿,且仅仅出现在 chrome 中。

【原因排查】

一开始使用了css动画的时候已经出现了卡顿。找到如下的文章:CSS3 动画卡顿解决方案深入浏览器理解CSS animations 和 transitions的性能问题解决Chrome动画”卡顿”的办法

文章中提到高度变化会引起 Relayout、Repaint。

做了如下修改:

  1. 移除改变高度的动画,换成 transform 的动画,以减少 Relayout、Repaint 的次数。
  2. 使用 transform: translateZ(0), 强制开启GPU渲染。
  3. 加上 will-change 属性,通知浏览器预处理。

动画的确略变流畅了。

然而高度变化还是很有必要,并觉得只由js去控制代码可维护性更好些,最后还是决定放弃了 css,改用js去做动画。考虑到 jQuery 封装的 animate() 十分简单易用,于是采用了 jQuery。

此时动画卡顿问题再次出现,而且在 IE、firefox 中非常流畅。查看资料,jQuery 的 animate 使用了老旧的SetInterval方法实现动画,并没用使用 RAF(Reques tAnimation Frame),不会开启 GUI。(后来发现此说法可能不对,在 jQuery 3 中源码中可以看出其使用了 RAF,jQuery 1中则同前描述)

最后决定改用velocity.js,velocity.js 已经可以脱离 jQuery 直接使用。看官方文档,宣传语是 “快” 。然而并没有什么用,使用之后,Chrome 一如既往的卡,IE 和 Firefox 则是一如既往的流畅。

开启 chrome 调试,查看timeline,发现了神奇的事情。

每次 network 发请求的时候,FPS 都会出奇地降至10一下。

尝试把请求删除,动画恢复正常。虽没有行云流水般流畅,但是肉眼看来已经没大问题了。

最后把请求放在动画结束之后在执行,搞定。

velocity(Div, \'slideUp\', {
    duration: 500,
    complete: function () {
... // DOM 操作 $.ajax(...);
... // setTimeout 操作 }
});

 

【结论】

问题虽然解决,还需进一步调查原因:

1、尝试把发送请求函数中的 DOM 操作删除,未见明显改善;

2、尝试把发送请求函数中的 setTimeout 定时器删除,未见明显改善;

3、尝试把发送请求函数中的 for in 循环删除,不再卡顿。

在 for in 中做了一个字符串拼接,这个字符串拼接的字符,传值到请求中

for (j in data) {
    if (data.hasOwnProperty(j)) {
        h.push(encodeURIComponent(j) + \'=\' + encodeURIComponent(data[j]));
    }
}

$.ajax({
...
  data: h,
...
});

测试push等性能并无问题,最终问题又回到了ajax请求中来了。至于为何异步请求会引起动画响应变慢,暂时不得而知。