繁体   English   中英

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

[英]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>


长答案:

首先, animationtransition并不相同,即使它们产生分配给属性的值的逐渐变化。 以下是一些主要区别:

  • 转换只能有一种开始状态和一种结束状态。 中间状态不受开发人员的控制,由 UA 确定。 使用动画时,开发人员可以根据需要在开始和结束状态之间指定尽可能多的中间状态。
  • 与动画不同,过渡不能自动启动/触发。 仅当通过用户交互(如hoverclick等)更改状态或通过 JS 向元素添加一些额外类时,才会启动转换。 加载页面时,动画可以自动启动。
  • 过渡没有循环或迭代(与动画不同)。 一个转换只能运行一次。

你可以阅读更多关于应该在使用它们以及何时之间的差异这篇文章


动画事件animationstartanimationend等)不会在您的第一种情况(您正在使用transition情况下)触发,因为元素上没有指定animation或有效的@keyframe规则。

根据 W3C 规范

定义了有效关键帧规则和非零持续时间的任何动画都将运行并生成事件; 这包括具有空关键帧规则的动画。


根据当前规范,与animation开始时不同,在开始transition时没有触发特定事件。 换句话说,没有transitionstart事件。 目前只有一个转换事件( transitionend )被实现。 W3C 规范)。

我不能肯定地说,不实施transitionstart事件是有意识的决定,还是只是一次失误。 但事实是,我们目前没有一个等效的。

就个人而言,我不认为这是一个很大的思念,因为开发人员应该知道确切的触发点的transition (如通过JS或通过它也可以通过JS检测到用户交互事件增加了一个新的类的)。 因此,我们总是可以说在满足触发条件的同一时刻开始了转换。 对于您的情况, transition已在执行.addClass('slide')同时开始。 因此,在执行.addClass('slide')之后,可以直接调用您想要执行(或)要调用的任何额外步骤。

注意事项:

  • 上述查找过渡开始的方法并非 100% 等同于animationstart事件。 原因是因为animationstart事件只有在设置的animation-delay过期后才会触发。 在您的代码段中,动画或过渡都没有延迟,因此这不是一个大问题。 如果确实有延迟,则必须获取transition-delay属性的值并在调用所需的函数(或)操作之前执行另一个超时。
  • 我记得之前在另一篇文章中读到 IE10 有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.

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