Aaron
Aaron

Reputation: 2500

jQuery Animation Loop Callback

I've written a special function called .Ani() that works similar to jquery .animate (same syntax, etc just runs it through CSS first then .animate if transitions aren't supported).

What I'm trying to do is allow users to pass in a string of coordinates to animate along a path:

"0,0||5,5||10,10"

$(this).Ani({'top': 0, 'left': 0}, duration, easing, function() {
    // callback function
});

The above just animates to 1 of the coordinate, and I would need to animate to the next set of coordinates (5,5) inside the callback by running the same code (which itself would have a callback as well).

I've simplified the above by not splitting the values, etc since all I'm looking to accomplish at this point is how to loop through X number of times (the number of coordinate sets) and generate the animation line for each set of coordinates. Something similar to:

var path="0,0||5,5||10,10",
    COORDS=path.split('||');

for(var i=0, l=COORDS.length; i<l; i++) {
   $(this).Ani({ 'top' : COORDS[i].split(',')[1], 'left' : COORDS[i].split(',')[0] }, 500, ease, function() {
      // WHEN DONE ANIMATING TO THIS LOCATION 
      // RUN THE NEXT ANIMATION FOR THE NEXT SET OF COORDINATES (5,5)
   });
};

Upvotes: 1

Views: 156

Answers (3)

Ivan Nikolchov
Ivan Nikolchov

Reputation: 1574

Here is my suggestion:

function Animate(path, callback) {
  var animatedObject = $(this)
  var onCompleteCallback = callback || function() { };
  var COORDS=path.split('||');
  var size = COORDS.length;

  if (size === 0) {
    // maybe call onCompleteCallback(); ?
    return;
  }

  var step = COORDS[0].split(',');
  var currentStep = 0;


  function doAnimation() {
    animatedObject.Ani({ 'top' : step[1], 'left' : step[0] }, 500, ease, function() {
        ++currentStep;
        if (currentStep === size) {
           onCompleteCallback();
           return;
        }
        step = COORDS[currentStep].split(',');
        doAnimation();
    });
  }

  doAnimation();
};

And just call it with: Animate("0,0||5,5||10,10", callbackFunctionWhenItsDoneIfYouWant);

Upvotes: 1

adeneo
adeneo

Reputation: 318162

Something like this I suppose

$.fn.Ani = function(vals, dur, ease, callback) {
    var coords = vals.split('||'),
        self   = this,
        i      = 0;

    (function fn(cooo) {
        var arr = cooo.split(',');
        self.animate({top: arr[0], left: arr[1]}, dur, ease, function() {
            if (coords[++i]) {
                fn(coords[i]);
            } else {
                callback();
            }
        });
    })(coords[i]);
}

var path = "0,0||5,5||10,10";

$(element).Ani(path, 1200, 'swing', function() {
    // complete
});

FIDDLE

Upvotes: 0

Andrei
Andrei

Reputation: 3106

You could make Ani send a function as a parameter to the callback that when called, runs the Ani function for the next pair of coords and sends the rest of the parameters intact.

$(this).Ani({'top': 0, 'left': 0}, duration, easing, function(continueFunction) {
    continueFunction();
});

P.S. why not make Ani as an object that encapsulates the logic ? It could simplify the code and rise performance, but increase LOC.

Upvotes: 0

Related Questions