【问题标题】:Combination of animation and transition not working properly动画和过渡的组合无法正常工作
【发布时间】:2015-11-15 12:37:56
【问题描述】:

我一直在尝试放置一些基本的 CSS3 动画。目标是在按钮的单击事件上切换一个类,并根据添加的类为 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>

我还准备了一把小提琴here。

【问题讨论】:

  • 我在 Ubuntu 15.04 上使用 Chrome,它似乎对我有用。如果我单击一次按钮,动画就会开始。如果我再次单击该按钮,则 div 将返回其原始位置。然后,如果我再次单击该按钮,动画将再次开始,依此类推。
  • 你真的需要动画吗?即使没有直线运动也可以实现运动。我之前已经看到了 Chrome 的转换问题。您可以参考此线程以获取一些相关信息 - stackoverflow.com/questions/31806649/…(我将其链接只是因为我们发现在删除动画时过渡在 Chrome 中效果不佳 - 问题中也提到了这一点)。跨度>
  • @Mushtak:我使用的是 Windows 8.1,动画仅适用于 Firefox,从下一次迭代开始,动画并不像我提到的那样流畅,对于 Chrome/Opera,问题出现在第一次迭代中。跨度>
  • 如果你可以避免动画,你可以像here一样在没有它的情况下达到同样的效果。
  • @Harry:感谢您的参考链接和小提琴。这就是我一直在寻找的。​​span>

标签: javascript css css-transitions css-animations css-transforms


【解决方案1】:

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

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

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

似乎发生的事情是元素获得了自己的渲染层,因为它具有明确的位置属性设置。当图层(或其中的一部分)因动画而失效时,Chrome 只会重新绘制受更改影响的图层。当您打开 Chrome 开发者控制台,打开“显示绘制矩形”选项时,您会看到当动画发生时,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 转换并将元素移动所需的编号。打开类时的像素数。由于通过另一个选择器为元素分配了一个转换,因此移位将以线性方式发生。关闭类时,由于元素上的过渡,元素再次以线性方式移回其原始位置。

$('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>

【讨论】:

    【解决方案2】:

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

    过渡是一种动画,只是在两个动画之间执行的动画 不同的状态 - 即开始状态和结束状态。像一个抽屉 菜单,开始状态可以打开,结束状态可以关闭, 反之亦然。

    如果您想执行不具体涉及 开始状态和结束状态,或者您需要更细粒度的控制 过渡中的关键帧,那么您必须使用动画。

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

    $('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>

    【讨论】:

    • 抱歉,朋友在添加我的答案之前没有看到您的答案弹出窗口。为您的方法 +1,因为它也是实现它的正确方法。
    • @halfzebra:感谢您的回答。我希望我能接受这两个答案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 2016-02-05
    • 1970-01-01
    相关资源
    最近更新 更多