流畅JS动画的7个性能优化建议
引言
web动画的作用从一般的装饰效果已演进成实现特定用户体验的具体目标,
如, 当用户交互提供视觉反馈,指引用户注意力来完成应用目标,提供视觉线索帮助用户了解应用界面。
为了确保web动画能够胜任这些任务,保证动画在合适时机以流畅和平滑的方式运行十分重要。
这样用户通过动画了解应用,而不是尝试去做各种操作试图掌握应用。
卡顿动画可怕的效果之一就是丢帧,jankfree.org网站说
现代浏览器尝试保持设备刷新率一致来刷新屏幕内容。
现在大部分设备屏幕一秒钟刷新60次,即60赫兹。
如果屏幕的某些动画,如,滚动,渐变或动画,浏览器会1秒钟创建60帧来匹配设备刷新率。
当网站或应用无法保持刷新率时就会发生用户视觉的闪烁或停止。
如果动画失帧,用户将会最终越来越少地使用你的应用,进而产生副作用。
显然,没有人期待这种结果。
本文中,我收集几种性能优化建议帮助解决js动画的问题,可以更容易保证60fps刷新率,实现平滑动画。
1. 避免针对复杂css属性执行动画
无论你是否打算用css渐变或关键帧或jss实现css属性动画,明确哪些属性会导致页面布局变化很重要。页面布局意味着页面的其他元素不得不重新计算位置,有时绘制操作也会发生。
布局和绘制任务对于浏览器进程来说都很昂贵,特别是页面有很多元素时。
如果你避免那些会触发布局或绘制操作的css属性动画,坚持使用transform和透明度这些属性,由于浏览器本身针对这些属性做过优化,你会看到动画性能显著提升。
Css Triggers网站上可以找到实时更新的css属性和相关不同浏览器的触发信息。
提升web动画性能简单而有效的方式是改变那些只触发复合操作的css属性。
2. 提升想要执行动画元素到指定分层(谨慎操作)
如果动画执行元素在本身的复合器层,有些浏览器会启用硬件加速,将任务降载给GPU执行。
如果使用合理,这会对提升动画性能产生积极作用。
为了让元素保持在自身层,需要提升元素,一种方式就是使用css will-change 属性。
这个属性允许开发者提醒浏览器元素即将发生变化,这样浏览器可以提前进行必要的优化。
但是,不建议提升太多元素,实际上浏览器创建每一个层都会消耗昂贵的内存和管理成本。
3. 使用requestAnimationFrame替换setTimeout/setInterval
一般来说js动画都会使用setInterval和setTimeout。
var timer;
function animateElement() {
timer = setInterval( function() {
// animation code goes here
} , 2000 );
}
// To stop the animation, use clearInterval
function stopAnimation() {
clearInterval(timer);
}
尽管这两个API可以实现动画,但是丢帧的风险很高。因为回调函数会在帧中的某个时间点执行,也许是在最后面,会导致单个或多帧丢失。
现在你可以使用浏览器提供的原生js方法,专门为平滑动画优化,叫requestAnimationFrame。
requestAnimationFrame会在大部分浏览器合适的时机执行动画代码,一般都会在帧的开始。
function makeChange( time ) {
// Animation logic here
// Call requestAnimationFrame recursively inside the callback function
requestAnimationFrame( makeChange ):
}
// Call requestAnimationFrame again outside the callback function
requestAnimationFrame( makeChange );
4. 从动画代码中解耦事件处理
一秒钟执行60帧,浏览器有16.67毫秒在单帧中执行任务。
时间并不长,所以保持简洁代码可以提升动画流畅度。
从处理屏幕更新动画代码中解耦事件处理代码,如,滚动、窗口缩放、鼠标事件等等
能够很好提升动画性能。
5. 避免执行长耗时js代码
浏览器使用主线程执行js,伴随执行样式计算、布局和绘制操作。
长耗时js代码会对这些任务产生消极作用,导致丢帧和缓慢动画。
因此简化代码可以很好确保动画流畅运行。
对于那些不需要访问DOM的复杂js操作,可以考虑使用Web Worker,
worker线程执行任务时不会影响用户界面。
6. 使用浏览器开发者工具跟踪性能问题
浏览器开发者工具可以监控js代码或第三方库运行情况,同时提供了很多和帧率有关的信息。
你可以右键页面选择inspect,例如,使用性能工具录制网页可以发现页面的性能瓶颈。
chrome开发者工具指南可以帮助了解大部分功能,提供性能优化和其他的浏览器数据。
7. 复杂绘图操作优先使用离线Canvas
如果帧中包含复杂绘制操作,比较好的方法是创建一个离线canvas,有变化时,一次性执行所有绘制操作,然后在每帧中绘制离线canvas。
译者注
现在如果不想失去用户期望,优化代码提升性能是一项必要任务,但这项任务并不总是容易而直接。
这也是为什么有些动画性能不好的原因,但如果你尝试上面的方法,那么你可以避免大部分动画性能低下问题,进而提升网站或应用的用户体验。
-
原文有删减,因译者水平有限,如有错误,欢迎留言指正交流