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.
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();
});
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.