这是 Chrome 的一种已知行为。Firefox 似乎确实能够通过过渡顺利处理动画的移除,但 Chrome 不会这样做。我也曾在此线程中更早地看到过这种行为。
为什么在 Chrome 中删除动画不能与过渡一起使用?
虽然我无法对发生这种情况的原因提供 100% 万无一失的解释,但我们可以根据这篇关于 Chrome 中加速渲染的 HTML5Rocks 文章和这篇关于 Chrome 中 GPU 加速合成的文章对其进行一定程度的解码。
似乎发生的是该元素获得了自己的渲染层,因为它在其上设置了显式位置属性。当图层(或其中的一部分)因动画而失效时,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 被关闭时,由于元素上的转换,元素再次以线性方式返回到其原始位置。
$('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>