How do I use transitionend in jQuery?

我与影子孤独终老i 提交于 2019-12-17 09:29:12

问题


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

  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.



回答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

  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



来源:https://stackoverflow.com/questions/7134584/how-do-i-use-transitionend-in-jquery

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!