Faruk At.eş

New Creation: jQuery Runloop Plugin

TL;DR links for the eager:

Earlier this week I was working on a project that involved one larger animation during which several separate animations would trigger, but not all at the same time, and not all on the same elements. As jQuery provided insufficient functionality to suit my needs, I went on a hunt across the Web in search for a runloop plugin, with these requirements:

  1. It should allow for executing custom code at specified keyframes, not just run a jQuery effect chain like .animate();
  2. It should be easy to rearrange keyframes or adjust keyframe locations without having to deal with adjusting callbacks;
  3. It should play well with jQuery’s Effects Queue (ruling out doing a custom setInterval thing);
  4. It should support triggering animations that run independently from the main animation runloop, so that it's possible to have a main loop of 5 seconds with a keyframe at 90% triggering a 2-second animation, and not having that cut off; in other words: separate timings of the main runloop to animations triggered at specified keyframes.

Alas, my traipsing across the Web yielded no results. However, after deciding to write my own plugin, I came across this concept by Ben Nadel which inspired me, and gave me a clear idea for what to do. I then adopted Ben’s idea of using the .animate() function’s step: method and turned it into a full-fledged runloop system, and am now making it available as a plugin for jQuery. I’m pleased to give you: jQuery Runloop. Suffice to say, it satisfies all of my requirements listed above.

Want a demo before reading on? That’s cool, go check out the demo.

Basic usage

Runloop is not a common jQuery plugin in that it is not chainable. This is very much on purpose, because it was designed to support customized animations running across many different elements, so chaining this to one element made no sense.

There is one very important thing to keep in mind: jQuery Runloop only supports keyframes at 5% intervals, and only at 10% intervals if you give it a duration of < 500ms!

The reason for this is that it runs one .animate() call on a div in nodespace, triggering at every step. However, steps are not round integers by nature, and animation timings will often cause certain single integers to be skipped over when rounded. That’s why it reduces each step to its nearest mod-5 value, and in the case of < 500ms (main) animations, to its nearest mod-10 value.

Now, making a custom animation stack with jQuery Runloop is quite easy. Here’s a quick example:

<!-- After including jQuery, include the plugin: -->
<script src="jquery.runloop.1.0.js"></script>
var loop = jQuery.runloop();

// Note: only use 5% intervals (10% for <500ms durations)!
loop.addKey('25%', function(){ // Some code or animations here  });
loop.addKey('50%', function(){ // Different code/animations  });
loop.addKey('75%', function(){ // Even more different code/animations!  });

loop.play(1000); // duration set in milliseconds

A full documentation of all the features will be available on the Runloop github page soon. In the meantime, you can learn much from the source of the demo and the plugin code itself; I’ve documented it pretty extensively.

Lastly, I want to thank:

Now go play with jQuery Runloop.

Update: more sophisticated frameworks such as Sproutcore have pretty robust runloop and events queues already, so you might be asking yourself, why did I not just use something like that? Two main reasons: simplicity & accessibility. With jQuery and Runloop it’s easy to layer in complex animations on top of a nice, clean, semantic page that would still work just fine with JavaScript disabled. Not so much with any of those frameworks.

If you liked this, you should follow me on Twitter!

About me

Faruk Ateş

Faruk Ateş is a product designer, developer, and entreprenerd. He is the creator of Modernizr and co-creator of Presentate.

He resides in San Francisco, CA and works at Quantifind.

Read more about Faruk, or .

Upcoming talks

Here on My own website

Subscribe to this site