简体   繁体   中英

Trigger event on animation complete (no control over animation)

I've a scenario that requires me to detect animation stop of a periodically animated element and trigger a function. I've no control over the element's animation . The animation can be dynamic so I can't use clever setTimeout .

Long Story

The simplified form of the problem is that I'm using a third party jQuery sliding banners plugin that uses some obfuscated JavaScript to slide banners in and out. I'm in need of figuring out a hook on slideComplete sort of event, but all I have is an element id . Take this jsfiddle as an example and imagine that the javascript has been obfuscated. I need to trigger a function when the red box reaches the extremes and stops.

I'm aware of the :animated pseudo selector but I think it will need me to constantly poll the required element. I've gone through this , this , and this , but no avail. I've checked jquery promise but I couldn't figure out to use that in this scenario. This SO question is closest to my requirements but it has no answers.

PS Some more information that might be helpful:

  1. The element isn't created by JavaScript, it is present on page load.
  2. I've control over when to apply the plugin (that makes it periodically sliding banner) on the element

Most of the slideshow plugins I have used use changing classes at the end of the animation... You could extend the "addClass" method of jQuery to allow you to capture the class change as long as the plugin you use is using that method like it should:

(function($){

$.each(["addClass","removeClass"],function(i,methodname){
      var oldmethod = $.fn[methodname];
      $.fn[methodname] = function(){
            oldmethod.apply( this, arguments );
            this.trigger(methodname+"change");
            return this;
      }
   });
})(jQuery);

I threw together a fiddle here

Even with obfuscated code you should be able to use this method to check how they are sending in the arguments to animate (I use the "options" object when I send arguments to animate usually) and wrap their callback function in an anonymous function that triggers an event... like this fiddle

Here is the relevant block of script:

(function($){
$.each(["animate"],function(i,methodname){
      var oldmethod = $.fn[methodname];
      $.fn[methodname] = function(){
          var args=arguments;
          that=this;
          var oldcall=args[2];
          args[2]=function(){
              oldcall();
              console.log("slideFinish");
          }
          oldmethod.apply( this, args );

          return this;
      }
    });
})(jQuery);

Well since you didn't give any indication as to what kind of animation is being done, I'm going to assume that its a horizontal/vertical translation, although I think this could be applied to other effects as well. Because I don't know how the animation is being accomplished, a setInterval evaluation would be the only way I can guess at how to do this.

var prevPos = 0;
var isAnimating = setInterval(function(){
    if($(YOUROBJECT).css('top') == prevPos){
        //logic here
    }
    else{
        prevPos = $(YOUROBJECT).css('top');
    }
},500);

That will evaluate the vertical position of the object every .5 seconds, and if the current vertical position is equal to the one taken .5 seconds ago, it will assume that animation has stopped and you can execute some code.

edit --

just noticed your jsfiddle had a horizontal translation, so the code for your jsfiddle is here http://jsfiddle.net/wZbNA/3/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM