简体   繁体   English

CSS3 动画 - 使用过渡时不会触发 animationstart 事件:

[英]CSS3 animations - animationstart event won't fire when using transition:

Given the following:鉴于以下情况:

.slide{
  transition: all 1s ease 0s;
  transform: translateX(-100%);
}

and

document.documentElement.addEventListener('animationstart', function() {
  alert(1);
}, false); 

the event won't fire.该事件不会触发。

However, if the CSS is :但是,如果 CSS 是:

.slide {
  animation: slide 1s infinite
}

@keyframes slide {
  from {
    transform: translateX(0);
  }
  to { 
    transform: translateX(-100px);
   }
}

It does fire.它确实火了。

How come?怎么来的? It's an animation in both cases, however, in the first case we don't use the keyframes which have other negative consequences.在这两种情况下都是动画,但是,在第一种情况下,我们不使用具有其他负面影响的关键帧。

Isn't this an error in how browsers have implemented this feature?这不是浏览器如何实现此功能的错误吗?

Here is an example for the first:这是第一个示例:

http://jsbin.com/hizoyopimu/1/edit?html,css,js,console,output http://jsbin.com/hizoyopimu/1/edit?html,css,js,console,output

And second:第二:

http://jsbin.com/yegidehusi/1/edit?html,css,js,console,output http://jsbin.com/yegidehusi/1/edit?html,css,js,console,output

Is there something equivalent?有什么等价的吗?

TL;DR (Short Answer): TL; DR(简答):

As of now there is no event that gets fired during the start of a transition.到目前为止,还没有在转换开始期间触发的事件。 Transitions always happen only when a triggering condition is satisfied and so the event which triggers the transition can roughly be considered as equivalent to the transitionstart event.转换总是只有在满足触发条件时才会发生,因此触发转换的事件可以粗略地视为等效于transitionstart事件。

In the below snippet, I have added a user-defined function ( transitionStart ) which gets called right after the .addClass('slide') and this is kind of equivalent to 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>

A transitionend event is available and can be used to identify the ending point of the transition and then perform any required function calls or other process. transitionend事件可用,可用于识别转换的结束点,然后执行任何所需的函数调用或其他过程。 The below snippet has a sample for this.下面的代码片段有一个示例。

 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>


Long Answer:长答案:

First of all, animation and transition are not same even though they produce a gradual change of the values assigned to the properties.首先, animationtransition并不相同,即使它们产生分配给属性的值的逐渐变化。 Below are some key differences:以下是一些主要区别:

  • Transitions can have only one start state and one end state.转换只能有一种开始状态和一种结束状态。 Intermediate states are beyond the control of a developer and is determined by the UA.中间状态不受开发人员的控制,由 UA 确定。 When using animations, the developer can specify as many intermediate states between the start and end state as required.使用动画时,开发人员可以根据需要在开始和结束状态之间指定尽可能多的中间状态。
  • Transitions cannot start/be triggered automatically unlike animations.与动画不同,过渡不能自动启动/触发。 Transitions are started only when there is a change of state through user interaction like ( hover , click etc) or when some extra class is added to the element through JS.仅当通过用户交互(如hoverclick等)更改状态或通过 JS 向元素添加一些额外类时,才会启动转换。 Animations can start automatically when the page is loaded.加载页面时,动画可以自动启动。
  • There is no looping or iteration for transitions (unlike animations).过渡没有循环或迭代(与动画不同)。 A transition can run only once.一个转换只能运行一次。

You can read more about the differences between them and when one should be used in this article .你可以阅读更多关于应该在使用它们以及何时之间的差异这篇文章


Animation events ( animationstart , animationend etc) will not fire for your first case (the one where you are using transition ) because there is no animation or valid @keyframe rule specified on the element.动画事件animationstartanimationend等)不会在您的第一种情况(您正在使用transition情况下)触发,因为元素上没有指定animation或有效的@keyframe规则。

As per W3C Spec根据 W3C 规范

Any animation for which both a valid keyframe rule and a non-zero duration are defined will run and generate events;定义了有效关键帧规则和非零持续时间的任何动画都将运行并生成事件; this includes animations with empty keyframe rules.这包括具有空关键帧规则的动画。


As per current spec there is no specific event that is fired when a transition is started unlike when an animation starts.根据当前规范,与animation开始时不同,在开始transition时没有触发特定事件。 In other words, there is no transitionstart event.换句话说,没有transitionstart事件。 Currently there is only one transition event ( transitionend ) that is implemented.目前只有一个转换事件( transitionend )被实现。 ( W3C Spec ). W3C 规范)。

I cannot say for sure if it was a conscious decision to not implement transitionstart event or it was just a miss.我不能肯定地说,不实施transitionstart事件是有意识的决定,还是只是一次失误。 But the fact is that we don't have an equivalent one at present.但事实是,我们目前没有一个等效的。

Personally, I do not see this as a big miss because the developer should know the exact trigger points for a transition (like the addition of a new class via JS or through user interaction events which can also be detected via JS).就个人而言,我不认为这是一个很大的思念,因为开发人员应该知道确切的触发点的transition (如通过JS或通过它也可以通过JS检测到用户交互事件增加了一个新的类的)。 So, we can always say that a transition has started at the very same instant when the trigger condition was satisfied.因此,我们总是可以说在满足触发条件的同一时刻开始了转换。 For your case, the transition has started at the same time at which the .addClass('slide') is executed.对于您的情况, transition已在执行.addClass('slide')同时开始。 So, whatever extra steps you want to do (or) functions that you want to call can be called directly after the .addClass('slide') is executed.因此,在执行.addClass('slide')之后,可以直接调用您想要执行(或)要调用的任何额外步骤。

Points to note:注意事项:

  • The above way of finding a transition's start is not 100% equivalent to the animationstart event.上述查找过渡开始的方法并非 100% 等同于animationstart事件。 The reason is because the animationstart event is fired only after the animation-delay that is set has expired.原因是因为animationstart事件只有在设置的animation-delay过期后才会触发。 In your snippet there is no delay for either the animation or transition and hence this is not a big issue.在您的代码段中,动画或过渡都没有延迟,因此这不是一个大问题。 If you do have a delay then you'd have to get the value of the transition-delay property and execute another time-out before calling the required functions (or) actions.如果确实有延迟,则必须获取transition-delay属性的值并在调用所需的函数(或)操作之前执行另一个超时。
  • I remember reading earlier in another article that IE10 had transitionstart event but it is non-standard and hence is not recommended.我记得之前在另一篇文章中读到 IE10 有transitionstart事件,但它是非标准的,因此不推荐。

Now in 2020:现在是 2020 年:

When using transitions, you have to use transition events instead of animation events.使用过渡时,必须使用transition事件而不是animation事件。

Compatability table (works even in Edge v42) 兼容性表(甚至适用于 Edge v42)

  yourElement.addEventListener("transitionstart", () => {
      alert("transitionstart");
  });

Example:例子:

 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>

The following code works.以下代码有效。 Although you have specified animationstart for a listener , you have also defined the animation in css to be infinite which will cause the alert to fire only on the first initial start of the infinite loop .尽管您已为侦听器指定了 animationstart,但您还在 css 中将动画定义为无限,这将导致警报仅在无限循环的第一次初始启动时触发。 If you want to detect the animation on every stop/start/repeat cycle: one option would be looping the animation with javascript instead of infinite css.如果您想在每个停止/开始/重复循环中检测动画:一种选择是使用 javascript 而不是无限 css 循环动画。 Hopefully this helps your research.希望这有助于您的研究。

.slide {
        animation: slide 1s infinite
}

@keyframes slide {
        from {
                transform: translateX(0);
        }
        to { 
                transform: translateX(100px);
        }
}

JS JS

var x = document.querySelector('.slide');

x.addEventListener('animationstart',function(){
  alert(1)

},false)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM