[英]CSS3 animations - animationstart event won't fire when using transition:
鉴于以下情况:
.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
有什么等价的吗?
TL; DR(简答):
到目前为止,还没有在转换开始期间触发的事件。 转换总是只有在满足触发条件时才会发生,因此触发转换的事件可以粗略地视为等效于transitionstart
事件。
在下面的代码片段中,我添加了一个用户定义的函数 ( transitionStart
),它在.addClass('slide')
之后.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>
transitionend
事件可用,可用于识别转换的结束点,然后执行任何所需的函数调用或其他过程。 下面的代码片段有一个示例。
setTimeout(function() { $('.transitioned').removeClass('hide').addClass('slide'); transitionStart(); }, 1000); function transitionStart(){ console.log('Transition Started'); } $('.transitioned').bind('transitionend', function() { console.log('Transition Ended'); });
.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%); }
<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>
长答案:
首先, animation
和transition
并不相同,即使它们产生分配给属性的值的逐渐变化。 以下是一些主要区别:
hover
、 click
等)更改状态或通过 JS 向元素添加一些额外类时,才会启动转换。 加载页面时,动画可以自动启动。你可以阅读更多关于应该在使用它们以及何时之间的差异这篇文章。
动画事件( animationstart
、 animationend
等)不会在您的第一种情况(您正在使用transition
情况下)触发,因为元素上没有指定animation
或有效的@keyframe
规则。
根据 W3C 规范
定义了有效关键帧规则和非零持续时间的任何动画都将运行并生成事件; 这包括具有空关键帧规则的动画。
根据当前规范,与animation
开始时不同,在开始transition
时没有触发特定事件。 换句话说,没有transitionstart
事件。 目前只有一个转换事件( transitionend
)被实现。 ( W3C 规范)。
我不能肯定地说,不实施transitionstart
事件是有意识的决定,还是只是一次失误。 但事实是,我们目前没有一个等效的。
就个人而言,我不认为这是一个很大的思念,因为开发人员应该知道确切的触发点的transition
(如通过JS或通过它也可以通过JS检测到用户交互事件增加了一个新的类的)。 因此,我们总是可以说在满足触发条件的同一时刻开始了转换。 对于您的情况, transition
已在执行.addClass('slide')
同时开始。 因此,在执行.addClass('slide')
之后,可以直接调用您想要执行(或)要调用的任何额外步骤。
注意事项:
animationstart
事件。 原因是因为animationstart
事件只有在设置的animation-delay
过期后才会触发。 在您的代码段中,动画或过渡都没有延迟,因此这不是一个大问题。 如果确实有延迟,则必须获取transition-delay
属性的值并在调用所需的函数(或)操作之前执行另一个超时。transitionstart
事件,但它是非标准的,因此不推荐。现在是 2020 年:
使用过渡时,必须使用transition
事件而不是animation
事件。
兼容性表(甚至适用于 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>
以下代码有效。 尽管您已为侦听器指定了 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.