How do I use transitionend in jQuery?

前端 未结 5 821
说谎
说谎 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:37

    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');
    });
    
    0 讨论(0)
  • 2020-12-01 05:50

    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);
    
    0 讨论(0)
  • 2020-12-01 05:56

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

    1. onclick set this.data('transitioning', true)
    2. when transitionend fires, set this.data('transitioning', false)
    3. don't perform animation if this.data('transitioning') == true. this is captured and checked in your click event.
    0 讨论(0)
  • 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

    0 讨论(0)
  • 2020-12-01 06:02

    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
    });
    
    0 讨论(0)
提交回复
热议问题