FBJS/Animation
From Facebook Developers Wiki
FBJS exposes a powerful animation library which gives developers an easy way to improve their user interface with a line of code or two. All animations are CSS based, so a working knowledge of CSS will really help you out here. An open-source version of FBJS Animation that will work on pages outside of Facebook is available at: http://developers.facebook.com/animation/
The syntax for the open-source version is identical to the FBJS version (they're the same library) so the techniques you learn for FBJS Animation will work outside of Facebook, and vice versa.
Note: If you're using the open-source Animation library, it's best if your page is running in standards compliant mode (i.e. not quirks mode). Quirks mode may cause FBJS to behave oddly with certain animations. Information regarding quirks mode and how to activate standards compliant mode: http://www.quirksmode.org/css/quirksmode.html
While FBJS's Animation library delivers much of the same functionality as other animation libraries, the interface is much different. In our opinion, it's a great improvement over current libraries. Understanding the code doesn't require obtuse dictionaries of properties, but instead relies on intuitive method chaining.
Follow the tutorial below, and be sure to try out the Developer's FBML Console as you read to better understand how FBJS Animation works.
Contents |
[edit] Basic Animations
[edit] Tweening CSS attributes
We'll begin with some code:
| <a href="#" onclick="Animation(this).to('background', '#ffff4b').go(); return false;">Highlight</a> |
The first step is always to call Animation() with the DOM object you want to animate as the first parameter. Then from there you chain on whatever CSS you'd like to animate. In this case, we'll be animating "background" to a pale yellow (#ffff4b). Finally, call go() to let Animation know that you are done chaining.
You can use this pattern to animate as many attributes as you'd like.
| <a href="#" onclick="Animation(this).to('background', '#ffff4b').to('color', '#00a000').go(); return false;">Highlight</a> |
In this example we're animating both the text and background color. These both happen in one fluid animation.
The to method always animates from the current attribute to the value you specify. If you want to override this behavior you can use it in conjunction with the from method to specify in what state the animation should start. For instance... to create an animation that flashes a color and fades back you would do this:
| <a href="#" onclick="Animation(this).to('background', '#fff').from('background', '#ffff4b').go(); return false;">Flash</a> |
This tells Animation to start the animation from yellow and disregard the current color, and then fade back to white. The result is a nice flash \ fade effect on your link which could be used to call attention to something important on your page.
The final method used to interact directly with CSS attributes is the by method. It will increment the current CSS value by an amount:
| <a href="#" onclick="Animation(this).by('left', '15px').go(); return false;" style="position: relative; left: 0px">Move</a> |
This creates a link that, when clicked, will move 15 pixels to the right, and continue to move with each subsequent click.
There's a shorthand notation that may save you some time when using both the to and from methods. The example above (the "Flash" hyperlink) can instead be written like this:
| <a href="#" onclick="Animation(this).to('background', '#fff').from('#ffff4b').go(); return false;">Flash</a> |
Note that we changed from('background', '#ffff4b') to from('#ffff4b'). If a call to either to, from, or by is immediately preceded by a call to one of those methods and you supply only one argument it will default to the attribute supplied in the last call.
[edit] Custom durations
The default duration for animations you build is 1 second. If you need to adjust this, you can use the duration method:
| <a href="#" onclick="Animation(this).to('background', '#ffff4b').to('color', '#00a000').duration(2000).go(); return false;">Highlight</a> |
Now the animation will tween over 2 seconds instead of 1. (Note: duration accepts milliseconds, not seconds).
[edit] Animating Block-level Objects
[edit] Hiding \ shrinking
You can also animate block-level elements with FBJS's Animation library. You can use this to show and hide sections of your page at different times. We also provide several mechanisms to cater to specific animation use-cases. Here's an example:
| <div style="overflow: hidden" id="container"> <img src="http://static.ak.facebook.com/images/wiki_logo.png" /><br /> <a href="#" onclick="Animation(document.getElementById('container')).to('height', '0px').to('opacity', 0).hide().go(); return false;">Hide this div</a>. </div> |
Note the style="overflow: hidden" on the div, in this example, this is very important. Since animations are CSS-based, if we don't specify overflow: hidden the image will bleed out of the dimension-less div. Again, in this animation we're tweening two CSS styles at once (height and opacity) which gives us a very nice hiding effect. Also, you'll notice the hide method being used here. This is a simple flag that tells Animation to set the target's display style to "none" after the animation is completed, thus completely hiding it from the user. In this case it's not required, but it's still a good idea to use hide on animations where the entire target will disappear.
[edit] Preventing text wrapping
One common case of animating is shrinking or expanding a div which contains text in it. Take this code for example:
| <div id="container"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet.<br /> <a href="#" onclick="Animation(document.getElementById('container')).to('height', '0px').to('width', '0px').to('opacity', 0).hide().go(); return false;">Hide this div</a>. </div> |
You'll notice that as the div shrinks the text continues to wrap to fit the div, creating a very poor animation. When animating block-level elements that contain elements that may wrap, try using the blind method. Compare this animation to the above animation:
| <div id="container"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet.<br /> <a href="#" onclick="Animation(document.getElementById('container')).to('height', '0px').to('width', '0px').to('opacity', 0).blind().hide().go(); return false;">Hide this div</a>. </div> |
It's much smoother isn't it? blind works by creating another div directly inside the target with an explicit width and height. This prevents wrapping for the entirety of the animation, however once the animation is done, the extra helper-div will be removed, so be sure only to use blind when your animation target either starts or finishes completely hidden.
[edit] Revealing
You can also animate width and height to "auto" for when you want to completely show a div without having to calculate the specific dimensions of its parent:
| <div id="about" style="display: none"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet. </div> <a href="#" onclick="Animation(document.getElementById('about')).to('height', 'auto').from('0px').to('width', 'auto').from('0px').to('opacity', 1).from(0).blind().show().go(); return false;">About Facebook</a>. |
Here you can see many of the features of FBJS Animation coming together. Note our div starts off hidden (style="display: none") and we use Animation to expand it. We're using from here again to explicitly animate from nothingness (otherwise the animation would have no effect besides immediately showing the div, since width and height default to "auto", and opacity defaults to 1). We also use blind to prevent the text from wrapping again. The last method there is show which is the opposite of hide. It tells Animation to set display to "block" at the beginning of the animation.
[edit] Advanced Features
[edit] Checkpoints
There are some times when you want to build an animation that consists of two separate steps, but one logical animation. For cases like these we have checkpoints...
| <div id="about" style="display: none; border: 1px solid #bdc7d8; padding: 0px 3px"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet. </div> <a href="#" onclick="Animation(document.getElementById('about')).to('height', '0px').from('0px').to('width', 'auto').from('0px').show().blind().checkpoint().to('height', 'auto').blind().go(); return false;">About Facebook</a>. |
The checkpoint here separates the animation into two steps. The second part of the animation will execute immediately after the first part has finished. This particular animation first stretches the div to fit its parent, while keeping the height at 0. This part of the animation is visible because the div has a border. After that's complete, the div grows vertically to reveal the text inside. Animations can have has many checkpoints as you want, just continue to chain them on and they will all execute in succession.
[edit] Staggered checkpoints
Checkpoint also supports an extra parameter which can signal a checkpoint to fire before the previous animation is actually finished. It ranges between 0 and 1 (floating). 0 will make the checkpoint useless, and 1 will make the checkpoint fire immediately after the previous animation. 1 is the default.
| <div id="container"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet.<br /> <a href="#" onclick="Animation(document.getElementById('container')).to('height', '0px').blind().hide().checkpoint(0.5).to('opacity', 0).duration(500).go(); return false;">Hide this div</a>. </div> |
In this example we're using 0.5 which makes the second part of the animation start halfway through the first animation. Note the use of the duration method here to make sure that the second part of the animation finishes at the same time as the first. Since the first animation is 1 second long and the second animation starts halfway through, a duration of 500ms means they will finish at the same time.
[edit] Checkpoint callbacks
Checkpoints also support callbacks which can be used to fire off more animations or do any other related tasks:
| <div id="container"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet.<br /> <a href="#" onclick="Animation(document.getElementById('container')).to('width', '0px').to('height', '0px').to('opacity', 0).blind().hide() .checkpoint(1, function() { Animation(document.getElementById('next')).to('width', 'auto').from('0px').to('height', 'auto').from('0px').to('opacity', 1).from(0).blind().show().go(); }) .go(); return false;">Moving On...</a> </div> <div id="next" style="display: none"> All that's needed to join Facebook is a valid email address. To connect with coworkers or classmates, use your school or work email address to register. Once you register, join a regional network to connect with the people in your area. </div> |
Here we actually create a nested animation. The outer animation hides a div, the inner animation shows a new div afterwards. FBJS Animation is smart about chaining animations like this, it will make sure that the animations flow together well regardless of computer speed and frame rate.
[edit] Easing
Animation tweening by default is linear, meaning changes occur at a constant speed throughout the entire animation. Sometimes it can make the animation appear smoother by applying an ease, which manipulates distribution of the tween:
| <div id="container"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet.<br /> <a href="#" onclick="Animation(document.getElementById('container')).to('height', '0px').to('width', '0px').to('opacity', 0).blind().hide().ease(Animation.ease.end).go(); return false;">Hide this div</a>. </div> |
Notice how the animation starts slightly faster, but slows down when it's almost done.
[edit] Custom ease functions
There are three default eases that come with the animation library: begin, end, and both. begin will start slow and end fast, end will start fast and end slow, and both will start and end slow, but will be very fast in the middle. You can also define your own ease function. To create an ease function, just create a new function with a domain and range of 0 - 1 (floating).
| <div id="container"> Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet.<br /> <a href="#" onclick="Animation(document.getElementById('container')).to('height', '0px').blind().hide().ease(bounceEase).go(); return false;">Hide this div</a>. </div> <script> function bounceEase(p) { if (p <= 0.6) { return Math.pow(p * 5 / 3, 2); } else { return Math.pow((p - 0.8) * 5, 2) * 0.4 + 0.6 } } </script> |
Creating custom ease functions can unlock many different capabilities of FBJS Animation.
[edit] Tips
[edit] Use checkpoints to delay animation
Instead of creating timeouts like this:
| setTimeout(function() { Animation(obj).to('width', 'auto').go(); }, 2000); |
Try this:
| Animation(obj).duration(2000).checkpoint().to('width', 'auto').go(); |
Both are identical, except the 2nd method is much easier to implement.
[edit] Create abstractions for your animations
Do you find yourself using the same animation over and over? Instead of copy and pasting the same long Animation chain, put it into a function:
| function show(obj) { Animation(obj).to('height', 'auto').from('0px').to('width', 'auto').from('auto').to('opacity', 1).from(0).show().blind().go(); } |
[edit] Reporting Bugs
Please report bugs to http://bugs.developers.facebook.com/
