CSS3动画 - 使用转换时不会触发animationstart事件:

mom*_*omo 8 javascript css css3 css-transitions css-animations

鉴于以下内容:

.slide{
  transition: all 1s ease 0s;
  transform: translateX(-100%);
}
Run Code Online (Sandbox Code Playgroud)

document.documentElement.addEventListener('animationstart', function() {
  alert(1);
}, false); 
Run Code Online (Sandbox Code Playgroud)

事件不会发生.

但是,如果CSS是:

.slide {
  animation: slide 1s infinite
}

@keyframes slide {
  from {
    transform: translateX(0);
  }
  to { 
    transform: translateX(-100px);
   }
}
Run Code Online (Sandbox Code Playgroud)

它确实很火.

怎么会?在这两种情况下都是动画,但是,在第一种情况下,我们不使用具有其他负面后果的关键帧.

这不是浏览器如何实现此功能的错误吗?

这是第一个例子:

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

第二个:

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

有没有相当的东西?

Har*_*rry 11

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');
}
Run Code Online (Sandbox Code Playgroud)
.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%);
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

transitionend事件是可用的,并且可以用于识别过渡的结束点,然后执行任何所需的函数调用或其它过程.下面的代码段有一个示例.

setTimeout(function() {
  $('.transitioned').removeClass('hide').addClass('slide');
  transitionStart();
}, 1000);

function transitionStart(){
  console.log('Transition Started');
}

$('.transitioned').bind('transitionend', function() {
  console.log('Transition Ended');
});
Run Code Online (Sandbox Code Playgroud)
.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%);
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


答案很长:

首先,animationtransition是不是即使他们产生分配给该属性的值的逐渐变化相同.以下是一些主要差异:

  • 转换只能有一个开始状态和一个结束状态.中间状态超出了开发人员的控制范围,由UA决定.使用动画时,开发人员可以根据需要在开始和结束状态之间指定任意数量的中间状态.
  • 与动画不同,无法自动启动/触发过渡.只有当存在通过像用户交互(状态改变的转变被启动hover,click等),或者当一些额外的类是通过JS添加到元素.加载页面时,动画可以自动启动.
  • 转换没有循环或迭代(与动画不同).转换只能运行一次.

您可以阅读有关它们之间的差异以及何时应该在本文中使用它们的更多信息.


动画事件(animationstart,animationend(你正在使用的一个等)将不会触发您的第一种情况transition),因为不存在animation或有效@keyframe的元素指定的规则.

根据W3C规范

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


根据当前规范,transition启动a时不会触发特定事件,而不像启动时那样animation.换句话说,没有transitionstart事件.目前只实现了一个转换事件(transitionend).(W3C Spec).

我不能确定是否有意识地决定不实施transitionstart事件,或者只是一个未命中.但事实是我们目前没有同等的.

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

注意事项:

  • 上述查找转换开始的方式并非100%等同于animationstart事件.原因是因为animationstart事件仅在animation-delay设置过期后触发.在您的代码段中,动画或转换都没有延迟,因此这不是一个大问题.如果确实有延迟,那么transition-delay在调用所需的函数(或)操作之前,您必须获取属性的值并执行另一个超时.
  • 我记得早些时候在另一篇文章中读到IE10有transitionstart事件,但它是非标准的,因此不推荐.