css动画属性性能
性能主要表现:流量、功耗与流畅度
在现有的前端动画体系中,通常有两种模式:JS动画与CSS3动画。 JS动画是通过JS动态改写样式实现动画能力的一种方案,在PC端兼容低端浏览器中不失为一种推荐方案。 而在移动端,我们选择性能更优浏览器原生实现方案:CSS3动画。
然而,CSS3动画在移动多终端设备场景下,相比PC会面对更多的性能问题,主要体现在动画的卡顿与闪烁。
1,webkit-transform: translateX(3em) 使用优于left
- CSS动画属性会触发整个页面的重排relayout、重绘repaint、重组recomposite
- Paint通常是其中最花费性能的,尽可能避免使用触发paint的CSS动画属性,这也是为什么我们推荐在CSS动画中使用
webkit-transform: translateX(3em)
的方案代替使用left: 3em
,因为left
会额外触发layout与paint,而webkit-transform
只触发整个页面composite -
div { -webkit-animation-duration: 5s; -webkit-animation-name: move; -webkit-animation-iteration-count: infinite; -webkit-animation-direction: alternate; width: 200px; height: 200px; margin: 100px; background-color: #808080; position: absolute; } @-webkit-keyframes move{ from { left: 100px; } to { left: 200px; } } 使用left将持续触发页面重绘,有闪烁 @-webkit-keyframes move{ from { -webkit-transform: translateX(100px); } to { -webkit-transform: translateX(200px); } } 使用-webkit-transform页面只发生重组,效果好很多 详情移步:https://github.com/AlloyTeam/Mars/blob/master/performance/css-property-animation-performance.md
2,尽可能多的利用硬件能力,如使用3D变形来开启GPU加速
-webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); 如动画过程有闪烁(通常发生在动画开始的时候),可以尝试下面的Hack: -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000; -moz-perspective: 1000; -ms-perspective: 1000; perspective: 1000; 如下面一个元素通过translate3d右移500px的动画流畅度会明显优于使用left属性: #ball-1 { transition: -webkit-transform .5s ease; -webkit-transform: translate3d(0, 0, 0); } #ball-1.slidein { -webkit-transform: translate3d(500px, 0, 0); } #ball-2 { transition: left .5s ease; left: 0; } #ball-2.slidein { left: 500px; } 注:3D变形会消耗更多的内存与功耗,应确实有性能问题时才去使用它,兼在权衡
3,尽可能少的使用
box-shadows
与gradients
box-shadows
与gradients
往往都是页面的性能杀手,尤其是在一个元素同时都使用了它们,所以拥抱扁平化设计吧。4,尽可能的让动画元素不在文档流中,以减少重排
position: fixed; position: absolute;
5,优化 DOM layout 性能,减少渲染次数,示例如下:
// 触发两次 layout var newWidth = aDiv.offsetWidth + 10; // Read aDiv.style.width = newWidth + 'px'; // Write var newHeight = aDiv.offsetHeight + 10; // Read aDiv.style.height = newHeight + 'px'; // Write // 只触发一次 layout var newWidth = aDiv.offsetWidth + 10; // Read var newHeight = aDiv.offsetHeight + 10; // Read aDiv.style.width = newWidth + 'px'; // Write aDiv.style.height = newHeight + 'px'; // Write
详情移步:https://github.com/AlloyTeam/Mars/blob/master/performance/high-performance-css3-animation.md
另外,附上腾讯移动Web前端知识库
https://github.com/AlloyTeam/Mars
https://github.com/AlloyTeam/Mars/tree/master/issues
css3翻转动画实现
http://www.tuicool.com/articles/MV3UvuA
示例:左右翻转180度<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> /* entire container, keeps perspective */ .flip-container { perspective: 1000; } /* flip the pane when hovered */ .flip-container:hover .flipper, .flip-container.hover .flipper { transform: rotateY(180deg); } .flip-container, .front, .back { width: 320px; height: 480px; } /* flip speed goes here */ .flipper { transition: 5s; transform-style: preserve-3d; position: relative; } /* hide back of pane during swap */ .front, .back { backface-visibility: hidden; position: absolute; top: 0; left: 0; } /* front pane, placed above back */ .front { z-index: 2; background-color: antiquewhite; -webkit-box-shadow:30px 30px 30px aquamarine; } /* back, initially hidden pane */ .back { transform: rotateY(180deg); background-color: aqua; } </style> </head> <body> <div class="flip-container" ontouchstart="this.classList.toggle('hover');"> <div class="flipper"> <div class="front"> 1 <!-- 前面内容 --> </div> <div class="back"> 2 <!-- 背面内容 --> </div> </div> </div> </body> </html>