Fx.Scroll, Fx.Morph, Fx.Elements, and MooTools 1.3 Unified Timer

By Ryan Florence, published 2010-06-09

Part of the issue Migrated Articles From Original Site Structure..

MooTools 1.2 has a few different ways to do what seems like the same thing: Fx.Tween, Fx.Morph and Fx.Elements. A friend of mine recently asked what the difference was with each. What adds more to the fun is that MooTools 1.3 has some internal stuff going on that almost makes the differences meaningless!

Timers, Layout, and Paint

The big deal here are timers. When you call el.tween or fx.start a timer is installed in the browser and on each step causes two browser events: layout and paint.

Animating two elements at the same time

Consider this code:

var topFx, go, otherFx;

window.addEvent('domready', function(){

	topFx = new Fx.Tween('element1', {
		duration: 1000,
	});

	otherFx = new Fx.Tween('element2', {
		duration: 1000,
	});

	go = function(){
		topFx.start('margin-top', 0, 200);
		otherFx.start('right', 10, window.getSize().x - 60)
	};
	
	go();

});

This will install two timers, and on each step of both timers cause the layout and paint records for a grand total of 279 records because the timers aren’t synchronized.

screenshot

Now instead lets use Fx.Elements like so:

var elementsFx, go;

window.addEvent('domready', function(){
		
	elementsFx = new Fx.Elements([$('element1'), $('element2')], {
		duration: 1000
	});

	go = function(){
		elementsFx.start({
			0: { 'margin-top': [0, 200 ]},
			1: { 'right': [10, window.getSize().x - 60 ]}
		});
	};

	go();

});

screenshot

That gives us a single timer and only 186 records. Much more efficient. If we had 10 or even 100 elements being animated we’d see HUGE performance gains by using Fx.Elements.

Animating more than one property on a single element

When you animate two different effects on the same element, again Fx.Tween will install two timers and therefore fire double the layout and repaints for every step of every timer. That’s where morph comes in: it’ll install only one timer and do the calculations for all properties being animated before “stepping”. So there’s a shared step for all properties and therefore a shared layout and repaint. So …

leftFx = new Fx.Tween('element', {
	property: 'margin-left'
}).start(0, 200);

topFx = new Fx.Tween('element', {
	property: 'margin-top'
}).start(0, window.getSize().x - 80);

… becomes:

fx = new Fx.Morph('element').start({
	'margin-top': [0, 200],
	'margin-left': [0, window.getSize().x - 80]
});

Enter 1.3 Unified Timer!!

One limitation with these performance minded methods is that Fx.Morph or Fx.Elements have to share the same options for transitions, durations, etc. So you can’t animate the margin-left of an element for two seconds and the margin-top for only one without installing two different timers, and therefore multiple steps and repaints.

MooTools 1.3 has what’s called a unified timer (like other libraries) so all animations, regardless of when they are called or how long they go, they all share the same “steps” and therefore layout changes and repaints.

It lets us do stuff like this without sacrificing performance:

var leftFx, topFx, go;

window.addEvent('domready', function(){

	leftFx = new Fx.Tween('ball', {
		transition: 'cubic:out',
		duration: 1000,
		property: 'margin-left'
	});

	topFx = new Fx.Tween('ball', {
		transition: 'bounce:out',
		duration: 1000,
		property: 'margin-top'
	});

	go = function(){
		leftFx.start(0, window.getSize().x - 80);
		topFx.start(0, 200);
	};

});

With that exact code MooTools 1.2.4 causes 422 records and MooTools 1.3 only 297. Again, if we were doing one or two more properties or elements we’d be adding over 100 more browser events for each property or element. Btw, that animation is way cooler when leftFx duration is 2000, but it makes the unified timer look less awesome because the last second of the animation only has one timer with either version of MooTools.

MooTools 1.3 is in beta2, more information here.

Hi, I'm Ryan!

Location:
South Jordan, UT
Github:
rpflorence
Twitter:
ryanflorence
Freenode:
rpflo

About Me

I'm a front-end web developer from Salt Lake City, Utah and have been creating websites since the early 90's. I like making awesome user experiences and leaving behind maintainable code. I'm active in the JavaScript community writing plugins, contributing to popular JavaScript libraries, speaking at conferences & meet-ups, and writing about it on the web. I work as the JavaScript guy at Instructure.