我正在尝试改进CSS3动画,因为当前代码似乎导致了一些过度的CPU负载,浏览器似乎很滞后。
我能做什么?我有所有的供应商前缀等等。我不确定我能不能改进代码或重构它以将其用作最佳代码实践。
Fiddle演示
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
-webkit-transform: translateZ(0);
transform: translateZ(0);
-webkit-transform-origin: 50% 50% 0;
-ms-transform-origin: 50% 50% 0;
transform-origin: 50% 50% 0;
v -webkit-animation-name: sideupscroll;
animation-name: sideupscroll;
/*animation-duration*/
-webkit-animation-duration: 80s;
animation-duration: 80s;
/*animation-timing-function*/
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
/*animation-iteration-count*/
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
background: url("http://i.imgur.com/wNna7D3.png") repeat fixed 0 0 indigo;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
/* Safari and Chrome */
@-webkit-keyframes sideupscroll {
0% {
background-position: 0 0;
}
50% {
background-position: -50% -100%;
}
100% {
background-position: -100% -200%;
}
}
@keyframes sideupscroll {
0% {
background-position: 0 0;
}
50% {
background-position: -50% -100%;
}
100% {
background-position: -100% -200%;
}
}
<div class="wrapper">
<div class="content"></div>
</div>
原因
为元素的background-position
设置动画总是资源密集型的,而且在几乎所有浏览器中都很有可能导致动画滞后。这是因为,对background-position
的更改会导致在所有浏览器中重新绘制+合成(+还会导致在Webkit中重新布局(。由于需要执行如此多昂贵的操作,结果总是滞后。
有问题的代码段:
下面的代码段与您的fiddle相同(没有供应商前缀(。在启用"Show Paint Rects"选项后,运行此代码段并使用Chrome Dev工具进行检查。您会在元素顶部看到一个红色或绿色的框(这是绘制矩形(,该框将持续闪烁,或者在整个动画期间保持彩色。这表明重新绘制经常发生,因此会影响性能。
在Firefox中,可以通过在about:config
页面中启用nglayout.debug.paint_flashing
(将其设置为true(来查看绘制矩形。
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
transform: translateZ(0);
transform-origin: 50% 50% 0;
animation-name: sideupscroll;
animation-duration: 80s;
animation-timing-function: linear;
animation-iteration-count: infinite;
background: url("http://i.imgur.com/wNna7D3.png") repeat fixed 0 0 indigo;
animation-fill-mode: both;
}
@keyframes sideupscroll {
0% {
background-position: 0 0;
}
50% {
background-position: -50% -100%;
}
100% {
background-position: -100% -200%;
}
}
<div class="wrapper">
<div class="content"></div>
</div>
解决方案
最好避免为background-*
属性(所有属性都是视觉属性(设置动画,并使用类似transform
的属性。使用transform
至少在Blink(Chrome(和EdgeHTML中产生更好的性能,因为Blink只进行重新组合,而EdgeHTML只第一次触发重新布局(动画中的第一次更新(。
没有问题的代码段:(或至少对Blink和EdgeHTML性能的影响小得多(
下面的代码段使用transform
属性(translateX
和translateY
(来实现与预期输出非常相似(但不相同(的内容。如果您使用开发工具检查这个片段,您会看到绿框(paint-rect(在动画开始时只出现一次。之后,浏览器只执行合成,因此性能要好得多。
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
overflow: hidden;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 200%;
height: 400%;
content: "";
background: url("http://i.imgur.com/wNna7D3.png") 0 0 indigo;
background-repeat: repeat;
}
.content {
position: relative;
height: 100%;
width: 100%;
animation-name: sideupscroll;
animation-duration: 80s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
@keyframes sideupscroll {
0% {
transform: translateX(0%) translateY(0%);
}
50% {
transform: translateX(-50%) translateY(-100%);
}
100% {
transform: translateX(-100%) translateY(-200%);
}
}
<div class="wrapper">
<div class="content"></div>
</div>
壁虎和Webkit怎么样
不幸的是,在撰写本文时,还没有针对使用这些渲染引擎的浏览器的解决方案。唯一的选择似乎是减少animation-duration
。动画持续时间的减少意味着所需的重新绘制+重新布局+重新构图周期的数量更少,因此动画的性能更好。
下面的片段在Firefox中看起来不那么拖沓,因为持续时间只有20秒。
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
overflow: hidden;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 200%;
height: 400%;
content: "";
background: url("http://i.imgur.com/wNna7D3.png") 0 0 indigo;
background-repeat: repeat;
}
.content {
position: relative;
height: 100%;
width: 100%;
animation-name: sideupscroll;
animation-duration: 20s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
@keyframes sideupscroll {
0% {
transform: translateX(0%) translateY(0%);
}
50% {
transform: translateX(-50%) translateY(-100%);
}
100% {
transform: translateX(-100%) translateY(-200%);
}
}
<div class="wrapper">
<div class="content"></div>
</div>
有用链接:
- CSS触发器-列出哪些属性导致触发哪些操作
- HTML5 Rocks-Chrome中的加速渲染-解释加速渲染在Chrome中的工作原理(以及如何启用"显示绘制矩形"选项(
注意:如上所述,动画与您所讨论的内容并非100%相同,但在我看来,这是最接近的。