关于 CSS 转换的回调

当一个 CSS 转换已经完成时,是否有可能获得一个通知(如回调) ?

61824 次浏览

I know that Safari implements a webkitTransitionEnd callback that you can attach directly to the element with the transition.

Their example (reformatted to multiple lines):

box.addEventListener(
'webkitTransitionEnd',
function( event ) {
alert( "Finished transition!" );
}, false );

Yes, if such things are supported by the browser, then an event is triggered when the transition completes. The actual event however, differs between browsers:

  • Webkit browsers (Chrome, Safari) use webkitTransitionEnd
  • Firefox uses transitionend
  • IE9+ uses msTransitionEnd
  • Opera uses oTransitionEnd

However you should be aware that webkitTransitionEnd doesn't always fire! This has caught me out a number of times, and seems to occur if the animation would have no effect on the element. To get around this, it makes sense to use a timeout to fire the event handler in the case that it's not been triggered as expected. A blog post about this problem is available here: http://www.cuppadev.co.uk/the-trouble-with-css-transitions/ <-- 500 Internal Server Error

With this in mind, I tend to use this event in a chunk of code that looks a bit like this:

var transitionEndEventName = "XXX"; //figure out, e.g. "webkitTransitionEnd"..
var elemToAnimate = ... //the thing you want to animate..
var done = false;
var transitionEnded = function(){
done = true;
//do your transition finished stuff..
elemToAnimate.removeEventListener(transitionEndEventName,
transitionEnded, false);
};
elemToAnimate.addEventListener(transitionEndEventName,
transitionEnded, false);


//animation triggering code here..


//ensure tidy up if event doesn't fire..
setTimeout(function(){
if(!done){
console.log("timeout needed to call transition ended..");
transitionEnded();
}
}, XXX); //note: XXX should be the time required for the
//animation to complete plus a grace period (e.g. 10ms)

Note: to get the transition event end name you can use the method posted as the answer in: How do I normalize CSS3 Transition functions across browsers?.

Note: this question is also related to: - CSS3 transition events

The jQuery.transit plugin, a plugin for CSS3 transformations and transitions, can call your CSS animations from script and give you a callback.

I am using the following code, is much simpler than trying to detect which specific end event a browser uses.

$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function() {
//do something
});

Alternatively if you use bootstrap then you can simply do

$(".myClass").one($.support.transition.end,
function() {
//do something
});

This is becuase they include the following in bootstrap.js

+function ($) {
'use strict';


// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================


function transitionEnd() {
var el = document.createElement('bootstrap')


var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition'    : 'transitionend',
'OTransition'      : 'oTransitionEnd otransitionend',
'transition'       : 'transitionend'
}


for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}


return false // explicit for ie8 (  ._.)
}


// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false, $el = this
$(this).one($.support.transition.end, function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}


$(function () {
$.support.transition = transitionEnd()
})


}(jQuery);

This can easily be achieved with the transitionend Event see documentation here A simple example:

document.getElementById("button").addEventListener("transitionend", myEndFunction);


function myEndFunction() {
this.innerHTML = "Transition event ended";
}
#button {transition: top 2s; position: relative; top: 0;}
<button id="button" onclick="this.style.top = '55px';">Click me to start animation</button>