近日在作移动端web时发现一个问题就是在ios中若是动画元素使用了left top值时在微信易信客户端中不能使用系统的复制文本功能了。纠结了许久,后来在大神的提醒下,了解到是由于css的repaint致使的。改用了css3的translate之后就OK了, 查了一下资料,发现有如下的一些知识点,如今贴出来,有须要的人能够看看。参考资料:https://github.com/AlloyTeam/Mars/blob/master/performance/css-property-animation-performance.mdcss
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{ios
from { left: 100px; } to { left: 200px; }
}
以下图使用left将持续触发页面重绘,表现为红色边框:css3
movegit
@-webkit-keyframes move{github
from { -webkit-transform: translateX(100px); } to { -webkit-transform: translateX(200px); }
}web
以下图使用-webkit-transform页面只发生重组,表现为橙色边框:canvas
move2浏览器
CSS属性在CSS动画中行为表微信
浏览器绘制 DOM 的过程是这样子的:移动端web
获取 DOM 并将其分割为多个层(layer) 将每一个层独立地绘制进位图(bitmap)中 将层做为纹理(texture)上传至 GPU 复合(composite)多个层来生成最终的屏幕图像。
left/top/margin 之类的属性会影响到元素在文档中的布局,当对布局(layout)进行动画时,该元素的布局改变可能会影响到其余元素在文档中的位置,就致使了全部被影响到的元素都要进行从新布局[1],浏览器须要为整个层进行重绘并从新上传到 GPU,形成了极大的性能开销。
transform 属于合成属性(composite property),对合成属性进行 transition/animation 动画将会建立一个合成层(composite layer),这使得被动画元素在一个独立的层中进行动画。一般状况下,浏览器会将一个层的内容先绘制进一个位图中,而后再做为纹理(texture)上传到 GPU,只要该层的内容不发生改变,就不必进行重绘(repaint),浏览器会经过从新复合(recomposite)来造成一个新的帧[2]。
层创立的条件以下:
3D 或透视变换 CSS 属性 使用加速视频解码的 <video> 元素 拥有 3D (WebGL) 上下文或加速的 2D 上下文的 <canvas> 元素 复合插件(如 Flash) 进行 opacity/transform 动画的元素 拥有加速 CSS filters 的元素 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在本身的层里) 元素有一个 z-index 较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)
总结:
对布局属性进行动画,浏览器须要为每一帧进行重绘并上传到 GPU 中 对合成属性进行动画,浏览器会为元素建立一个独立的复合层,当元素内容没有发生改变,该层就不会被重绘,浏览器会经过从新复合来建立动画帧
另外能够参考http://csstriggers.com/ 里面有各类属性对页面布局,重绘,重排的影响关系。