【现象】
动画出现了明显的卡顿,且仅仅出现在 chrome 中。
【原因排查】
一开始使用了css动画的时候已经出现了卡顿。找到如下的文章:CSS3 动画卡顿解决方案、深入浏览器理解CSS animations 和 transitions的性能问题、解决Chrome动画”卡顿”的办法
文章中提到高度变化会引起 Relayout、Repaint。
做了如下修改:
- 移除改变高度的动画,换成 transform 的动画,以减少 Relayout、Repaint 的次数。
- 使用 transform: translateZ(0), 强制开启GPU渲染。
- 加上 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请求中来了。至于为何异步请求会引起动画响应变慢,暂时不得而知。