鉴于以下内容:
.slide{
transition: all 1s ease 0s;
transform: translateX(-100%);
}
和
document.documentElement.addEventListener('animationstart', function() {
alert(1);
}, false);
事件不会发生。
但是,如果CSS是:
.slide {
animation: slide 1s infinite
}
@keyframes slide {
from {
transform: translateX(0);
}
to {
transform: translateX(-100px);
}
}
它会解雇。
为什么?在这两种情况下都是动画,但是,在第一种情况下,我们不使用具有其他负面后果的关键帧。
这不是浏览器如何实现此功能的错误吗?
以下是第一个示例:
http://jsbin.com/hizoyopimu/1/edit?html,css,js,console,output
第二名:
http://jsbin.com/yegidehusi/1/edit?html,css,js,console,output
有没有相应的东西?
答案 0 :(得分:10)
TL; DR(简答):
截至目前,没有任何事件在转换开始时被触发。转换总是仅在满足触发条件时发生,因此触发转换的事件可以大致被视为等同于transitionstart
事件。
在下面的代码段中,我添加了一个用户定义的函数(transitionStart
),该函数在.addClass('slide')
之后立即调用,这相当于transitionstart
。
/* For Animation Start */
setTimeout(function() {
$('.animated').removeClass('hide').addClass('slide');
}, 1000);
$('.animated').bind('animationstart webkitAnimationStart', function() {
console.log('Animation Started');
});
/* For Transition Start */
setTimeout(function() {
$('.animated').removeClass('hide').addClass('slide');
transitionStart();
}, 1000);
function transitionStart(){
console.log('Transition Started');
}

.element {
padding: 10px;
background-color: #ccc;
width: 100px;
height: 100px;
}
.element.animated.hide {
display: none;
}
.animated.slide {
animation: slide 1s infinite
}
@keyframes slide {
from {
transform: translateX(0);
}
to {
transform: translateX(-100px);
}
}
.element.transitioned.hide {
transform: translateX(-100%);
}
.transitioned.slide {
transition: all 2s ease-in 0s;
transform: translateX(200%);
}

<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>
<h3>Element with Animation</h3>
<div class='element hide animated'>
box
</div>
<h3>Element with Transition</h3>
<div class='element hide transitioned'>
box
</div>
&#13;
transitionend
事件可用,可用于标识转换的结束点,然后执行任何所需的函数调用或其他过程。下面的代码段有一个示例。
setTimeout(function() {
$('.transitioned').removeClass('hide').addClass('slide');
transitionStart();
}, 1000);
function transitionStart(){
console.log('Transition Started');
}
$('.transitioned').bind('transitionend', function() {
console.log('Transition Ended');
});
&#13;
.element {
padding: 10px;
background-color: #ccc;
width: 100px;
height: 100px;
}
.element.transitioned.hide {
transform: translateX(-100%);
}
.transitioned.slide {
transition: all 2s ease-in 0s;
transform: translateX(200%);
}
&#13;
<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>
<h3>Element with Transition</h3>
<div class='element hide transitioned'>
box
</div>
&#13;
长答案:
首先,animation
和transition
不相同,即使它们会逐渐更改分配给属性的值。以下是一些主要差异:
hover
,click
等)或通过JS向元素添加一些额外类时,才会启动转换。加载页面时,动画可以自动启动。您可以详细了解它们之间的差异以及何时应在this article中使用它。
Animation events(animationstart
,animationend
等)不会针对您的第一个案例(使用transition
的情况)触发,因为没有animation
在元素上指定的有效@keyframe
规则。
根据W3C Spec
定义了有效关键帧规则和非零持续时间的任何动画都将运行并生成事件;这包括具有空关键帧规则的动画。
根据当前规范,与transition
启动时不同,启动animation
时不会触发特定事件。换句话说,没有transitionstart
事件。目前只实现了一个转换事件(transitionend
)。 (W3C Spec)。
我无法确定是否有意识地决定不执行transitionstart
事件,或者只是一次失败。但事实是,我们目前没有相同的产品。
就个人而言,我并不认为这是一个很大的错过,因为开发人员应该知道transition
的确切触发点(比如通过JS添加新类或通过用户交互事件也可以检测到通过JS)。因此,我们总是可以说转换已经在满足触发条件的同一时刻开始。对于您的情况,transition
已在.addClass('slide')
执行的同时启动。因此,在执行.addClass('slide')
之后,可以直接调用要执行的任何额外步骤(或)要调用的函数。
注意事项:
animationstart
事件。原因是因为animationstart
事件仅在设置的animation-delay
到期后才会触发。在您的代码段中,动画或转换都没有延迟,因此这不是一个大问题。如果确实有延迟,那么您必须获取transition-delay
属性的值并在调用所需的函数(或)操作之前执行另一个超时。transitionstart
事件,但它不符合标准,因此不推荐。答案 1 :(得分:2)
现在是2020年:
使用过渡时,必须使用transition
个事件而不是animation
个事件。
Compatability table(甚至在Edge v42中也可以使用)
yourElement.addEventListener("transitionstart", () => {
alert("transitionstart");
});
示例:
const div1 = document.querySelector(".div1");
div1.addEventListener("click", () => {
div1.classList.toggle("transition");
});
div1.addEventListener("transitionstart", () => {
console.log("transitionstart");
});
.div1{
transition: transform 1s ease-in-out;
background-color: darkseagreen;
display:inline-block;
}
.div1.transition{
transform: translateX(100px);
}
.div1.transition:after{
content: " again, when transition stopps!";
background-color: yellow;
}
<div class="div1"> CLICK ME</div>
答案 2 :(得分:1)
以下代码有效。虽然您已为侦听器指定了animationstart,但您还将css中的动画定义为无限,这将导致警报仅在无限循环的第一次初始启动时触发。如果你想在每个停止/开始/重复循环中检测动画:一个选项是使用javascript而不是无限的css循环动画。希望这有助于您的研究。
.slide {
animation: slide 1s infinite
}
@keyframes slide {
from {
transform: translateX(0);
}
to {
transform: translateX(100px);
}
}
JS
var x = document.querySelector('.slide');
x.addEventListener('animationstart',function(){
alert(1)
},false)