改善CSS3背景位置动画的性能

use*_*846 8 css css3 css-transitions css-animations

我正在尝试改进CSS3动画,因为当前代码似乎导致一些过多的CPU负载,并且浏览器似乎有点滞后.

我能做什么?我有所有的供应商前缀等.我不确定我可以改进代码或重构它以使用它作为最佳代码实践.

小提琴演示

.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%;
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrapper">
  <div class="content"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

Har*_*rry 17

原因

动画background-position元素的动画始终是资源密集型的,并且几乎在所有浏览器中都很可能导致延迟动画.这是因为,background-position在所有浏览器中对重绘+组合的结果进行了更改(+它还会导致在Webkit中重新布局).由于需要执行如此多的昂贵操作,结果始终是滞后的.

有问题的片段:

以下代码段与您的小提琴相同(没有供应商前缀).启用"Show Paint Rects"选项后,运行此代码段并使用Chrome Dev工具进行检查.你会在元素的顶部看到一个红色或绿色的颜色框(这是画颜料矩形),并且该框将持续闪烁或在动画的整个持续时间内保持颜色.它表示经常发生重绘,因此会影响性能.

在Firefox中,可以通过nglayout.debug.paint_flashingabout:config页面中启用(将其设置为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%;
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrapper">
  <div class="content"></div>
</div>
Run Code Online (Sandbox Code Playgroud)


最好避免动画background-*属性(所有属性都是视觉属性)并使用类似的属性transform.使用在Blink(Chrome)和EdgeHTML中至少可以transform产生更好的性能,因为Blink只进行重新组合,而EdgeHTML仅首次触发重新布局(动画中的第一次更新).

片段没有问题:(或至少对Blink和EdgeHTML中的性能影响小得多)

下面的代码片段使用transform属性(translateXtranslateY)来实现与预期输出非常相似的(但不相同).如果使用开发工具检查此片段,您会看到绿色框(绘制矩形)仅在动画开始时出现一次.发布,浏览器只执行合成,因此性能要好得多.

.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%);
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrapper">
  <div class="content"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

Gecko和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%);
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrapper">
  <div class="content"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

有用的链接:

注意:正如我上面已经说过的那样,动画并不是100%与你所讨论的相同,但在我看来这是你能得到的最接近的动画.

  • 我从中学到了很多。非常感谢您花时间向我展示差异。我不知道。 (2认同)