问题
I need to detect if a CSS transition is completed before allowing a function to repeat again, to prevent messing up the margins.
So how cam I have something like
if (transitionend == true) {
// do stuff
} else {
// do nothing
}
回答1:
The code below will trigger on the transitionend event for whatever element(s) you have in the $element variable. There are four different event names as I believe these cover all of the cross-browser inconsistencies. Replace the '// your event handler' comment with whatever code you wish to run when the event is triggered.
$element.on('transitionend webkitTransitionEnd oTransitionEnd', function () {
// your event handler
});
回答2:
I think this link might be helpful to you.
There is a single event that is fired when transitions complete. In Firefox, the event is transitionend, in Opera, OTransitionEnd, and in WebKit it is webkitTransitionEnd.
el.addEventListener("transitionend", updateTransition, true);
回答3:
Use jQuery data to attach stateful data to the element. Use a boolean value to "block" events from happening and flip the boolean variable once transitionend completes. Use xram's code to hook up all cross-browser transitionend events at the same time.
So for your example...
- onclick set this.data('transitioning', true)
- when transitionend fires, set this.data('transitioning', false)
- don't perform animation if this.data('transitioning') == true. this is captured and checked in your click event.
回答4:
You can create a method which will keep in mind when the transition end has been called the last time, and thus only trigger the callback once.
function transitionEndsOnce($dom, callback) {
var tick = Date.now();
$dom.on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function(e) {
var diff = Date.now() - tick;
tick = Date.now();
if (diff > 20) { // this number can be changed, but normally all the event trigger are done in the same time
return callback && callback(e);
}
});
}
and then simply use it this way
transitionEndsOnce($('...'), function(e){
console.log('transition ends once');
});
回答5:
I noticed such similar questions like "how do I catch touchend events?" or "mouseup events?" etc.
They are all similar for these points of view
plural: handlers are fired many times even when we are expecting to be fired by a single event
depth: events are bubbling deeper in the tree before our handler catches them.
Examples:
a
touchstart
can be followed by amousedown
and vice versa in a device that has both a mouse and a touch screen,a
touchend
can be followed by amouseup
for the similar reasons,a
animationstart
can be followed by many other similar events depending on how you wrote the css,a
animationend
can also be followed by many similar events for the above reasons as well.
If we need to fire our handler once per a set of similar events, i.e. events that produced by a single action like a person that presses sth. we need to introduce an event lock and use 2 handlers one at the beginning of an event and one handler at the end even if we don't need or want a handler of the side event.
The lock can be a property at the parent node higer in the tree as you guessed.
For the infamous event couple: animationstart
- animationend
such a function can be:
var oneTransition = (function(){
var $parent,
type,
callback,
unlockCallback,
newCallback,
start = 'webkitTransitionStart otransitionstart oTransitionStart msTransitionStart transitionstart',
end = 'webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend';
unlockCallback = function(){
$parent.data('oneTransitionLock', false);
};
newCallback = function(e){
if($parent.data('oneTransitionLock'))
return;
else
$parent.data('oneTransitionLock', true);
callback(e);
};
return function(){
var args = Array.prototype.slice.call(arguments, 0);
$parent = $(args[0]); // 1st arg
type = args[1]; // 2nd arg
callback = args[2]; // 3rd arg
if((args.length < 3) || ((type != 'start') && (type != 'end')) || (typeof(callback) != 'function'))
return;
$parent.off(start).off(end);
if(type == 'start'){
$parent.data('oneTransitionLock', false);
$parent.on(start, newCallback);
$parent.on(end, unlockCallback);
}else if(type == 'end'){
$parent.on(start, unlockCallback);
$parent.on(end, newCallback);
}
}
})();
and you can call it like:
oneTransition(node, 'start' or 'end', funcion(){...});
The interesting part is that it can runs for either the start or the end of animation:
1st arg. a node reference,
2nd arg. a string representing the event for our callback and
3rd arg. our actual callback.
jsFiddle
来源:https://stackoverflow.com/questions/7134584/how-do-i-use-transitionend-in-jquery