thanks kirupa


虽然 transition在CSS中着实占据一席之地,但它又与JavaScript有一定水平的协作。在与JavaScript协作时的事件领域展示了它自身。

你已知道transition有三个状态:

Animation Img

起始状态、过渡状态和终止状态。在这里,我将告诉你检测这三个状态的存在。不幸的是,这不可能做到的。你将必须接受这里只有一种状态存在,它是终止状态。这个事件被亲切的称之为transitionend,本章是关于这部分的内容。

Meet the transitionend Event

Transitionend事件原理很简单。该事件在transition一次过渡完成后被触发。让我给出CSS代码如下:

#blueCircle {
    transition: all .5s ease-out;
    opacity: .3;
}
#blueCircle:hover {
    transform: scale(3);
    opacity: 1;
}

CSS代码中,定义了一个transition,它应用在blueCircle 元素上,在半秒内影响到它所有的属性。当你鼠标移到blueCircle 上,设置的transform属性会使元素比例变大到300%,opacity变为1。当你移上去后,你能想象到它发生什么变化,0.5秒后元素会变的更大和变得更加清晰。十分简单的例子。

来看看如何检测transition到达终止状态吧。为了检测何时到达终止状态,将监听blueCircletransitionend事件何时触发。监听部分代码如下:

var blueCircle = document.querySelector("#blueCircle");

blueCircle.addEventListener("transitionend", detectTheEnd, false);
blueCircle.addEventListener("webkitTransitionEnd", detectTheEnd, false);
blueCircle.addEventListener("mozTransitionEnd", detectTheEnd, false);
blueCircle.addEventListener("msTransitionEnd", detectTheEnd, false);
blueCircle.addEventListener("oTransitionEnd", detectTheEnd, false);

function detectTheEnd(e) {

}

除了不考虑厂商前缀,事件监听和事件处理器两部分的代码都非常简单。当transitionend事件被监测时,detectTheEnd事件处理器将被调用。

The transitionend Event Handler

这个事件处理器内部什么都没做。Transitionend事件不仅是在transition完成后触发一次。而是在每个CSS属性的每次transition后都会触发。在我们的这个例子里,transitionend事件将被触发两次-一次是opacity属性,另一次是transform属性改变后。

因为事件被触发两次,意味着事件处理器也被调用两次。有可能的是,你不想让事件处理器调用两次-至少是在同一时延内的同一transition内。你不能阻止事件处理器调用两次。你能做什么呢,不过,在事件处理器中的代码可以保证你想的调用次数。 One way to ensure that is by checking the event argument's propertyName value for the CSS property the event is representing. Here is how that would look like when applied to our particular situation:==一种方法可保证,检测事件所代表的定义在事件参数propertyName的值。下面代码就是针对我们这个例子的参数检测:

function detectTheEnd(e) {
    if (e.propertyName == "opacity") {
        // do something interesting
    }
}

尽管detectTheEnd事件处理器将被调用两次,我关注的代码在if语句为真时只调用一次。当作为transitioned事件被opacity属性触发的结果,它的事件处理器只执行一次。

Dealing With Multiple Transitions

对于单一的transition影响多个属性(就像上面我们提到的例子),在事件处理器内,处理比较简单。你不能用propertyName来检测任意其它属性如transform。原因是,对于opacitytransform属性在经过.5秒后,两个transitionend事件几乎立即会触发。没有任何一点能打断代码的执行。

如果你有不同时延的transitions影响着不同的CSS属性,这没机会打断代码的执行。在这个用例里,transitionend事件将在不同的时间被触发,你可依赖CSS属性,处理不同的事件。

下面的代码就是处理刚才这种情形,两个transition结束于不同的时间点:

#blueCircle {
    transition: opacity .5s ease-out, transform 1s ease-in;
    opacity: .3;
}
#blueCircle:hover {
    transform: scale(3);
    opacity: 1;
}

在这个例子里,transitionend事件将在.5秒后触发一次和1秒后又触发一次。如果你想根据每个事件的transitionend单独影响每个实例,扩展刚才展示的代码:

function detectTheEnd(e) {
    if (e.propertyName == "opacity") {
        // do something interesting
    } else if (e.propertyName == "transform") {
        // do something interesting
    }
}

特意检测propertyName属性,根据哪个transitioned事件,保证正确的代码被执行。

Conclusion

乍一看,发现一个transition 什么时候结束貌似不那么重要。因为大多数第一眼,无法看到全部。一般情况,你不用关心transition何时结束。二般情况,知道transition何时结束极其重要的。尤其是在使用transition创建一个循环的动画时特别重要。在随后的文章里,我将着重介绍transitionend事件,能让你创建看似简单又很难做的相当相当有趣的动画。


翻译水平有限,敬请各位同学批评指正。


Comments

comments powered by Disqus