动画和过渡的组合无法正常工作

Combination of animation and transition not working properly

我一直在尝试放一些基本的 CSS3 动画。 objective 是在按钮的点击事件上切换一个 class 并根据添加的 class 动画一个 div。该代码对于 Firefox 中切换的第一次迭代非常有效,但对于 Chrome 等其他浏览器以及 Firefox 中的下一次迭代,转换会在眨眼间切换。请帮助我找出问题所在。

片段:

$('button').click(function() {
  $('div').toggleClass('clicked');
});
div {
  background-color: #ccc;
  height: 100px;
  width: 100px;
  transition-property: top, left;
  transition-duration: 1s;
  transition-timing-function: linear;
  position: relative;
  top: 0;
  left: 0;
}
.clicked {
  animation-name: clicked;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
@keyframes clicked {
  0% {
    top: 0;
    left: 0;
  }
  100% {
    top: 100px;
    left: 100px;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button">Click Me!</button>
<div></div>

我也准备了一个fiddlehere.

这是预期的行为。您需要使用两个单独的动画或只使用过渡。

A transition is an animation, just one that is performed between two distinct states - i.e. a start state and an end state. Like a drawer menu, the start state could be open and the end state could be closed, or vice versa.

If you want to perform something that does not specifically involve a start state and an end state, or you need more fine grain control over the keyframes in a transition, then you've got to use an animation.

这是使用过渡动画元素的方法:

$('button').click(function() {
  $('div').toggleClass('clicked');
});
div {
  background-color: #ccc;
  height: 100px;
  width: 100px;
  transition-property: top, left;
  transition-duration: 1s;
  transition-timing-function: linear;
  position: relative;
  top: 0;
  left: 0;
}
.clicked {
  top: 100px;
  left: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button">Click Me!</button>
<div></div>

这是 Chrome 的一种已知行为。 Firefox 似乎确实能够通过过渡平滑地处理动画的移除,但 Chrome 没有这样做。我之前也在 中看到过这种行为。

为什么移除动画不适用于 Chrome 中的过渡?

虽然我无法对为什么会出现这种情况提供 100% 万无一失的解释,但我们可以根据 this HTML5Rocks article about Accelerated rendering in Chrome and this one about GPU accelerated compositing in Chrome 在一定程度上对其进行解码。

似乎发生的情况是该元素获得了自己的渲染层,因为它在其上设置了明确的位置 属性。当图层(或其中的一部分)因动画而失效时,Chrome 只会重绘受更改影响的图层。当你打开 Chrome 开发者控制台,打开 "Show Paint Rects" 选项时,你会看到当动画发生时 Chrome 只绘制正在动画的实际元素。

但是,在动画的开始和结束时,整个页面都会重新绘制,这会将元素立即放回其原始位置,从而覆盖过渡行为。

$('button').click(function(){
  $('div').toggleClass('clicked');
});
div{
  background-color: #ccc;
  height: 100px;
  width: 100px;
  transition-property: top, left;
  transition-duration: 1s;
  transition-timing-function: linear;
  position: relative;
  top: 0;
  left: 0;
}
.clicked{
  animation-name: clicked;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
@keyframes clicked{
  0% {top: 0; left: 0;}
  100% {top: 100px; left: 100px;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button">Click Me!</button>
<div></div>


解决方法是什么?

由于您的运动实际上是从一个位置到另一个位置的线性运动,因此您无需任何动画即可实现。我们需要做的就是使用 translate 转换并将元素移动所需的编号。打开 class 时的像素数。由于通过另一个选择器将过渡分配给元素,因此移动将以线性方式发生。当 class 关闭时,由于元素上的过渡,元素再次以线性方式移回其原始位置。

$('button').click(function() {
  $('div').toggleClass('clicked');
});
div {
  background-color: #ccc;
  height: 100px;
  width: 100px;
  transition-property: transform;
  transition-duration: 1s;
  transition-timing-function: linear;
  position: relative;
  top: 0;
  left: 0;
}
.clicked {
  transform: translate(100px, 100px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<button type="button">Click Me!</button>
<div></div>