How do I use transitionend in jQuery?

前端 未结 5 840
说谎
说谎 2020-12-01 05:08

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

5条回答
  •  一个人的身影
    2020-12-01 05:58

    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

    1. plural: handlers are fired many times even when we are expecting to be fired by a single event

    2. depth: events are bubbling deeper in the tree before our handler catches them.

    Examples:

    1. a touchstart can be followed by a mousedown and vice versa in a device that has both a mouse and a touch screen,

    2. a touchend can be followed by a mouseup for the similar reasons,

    3. a animationstart can be followed by many other similar events depending on how you wrote the css,

    4. 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:

    1. 1st arg. a node reference,

    2. 2nd arg. a string representing the event for our callback and

    3. 3rd arg. our actual callback.

    jsFiddle

提交回复
热议问题