{"id":168883,"date":"2014-04-30T08:54:26","date_gmt":"2014-04-30T15:54:26","guid":{"rendered":"http:\/\/css-tricks.com\/?p=168883"},"modified":"2014-05-18T01:55:42","modified_gmt":"2014-05-18T08:55:42","slug":"improving-ui-animation-workflow-velocity-js","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/improving-ui-animation-workflow-velocity-js\/","title":{"rendered":"Improving UI Animation Workflow with Velocity.js"},"content":{"rendered":"

The following is a guest post by Julian Shapiro<\/a>. Julian recently released Velocity.js, a more performant jQuery replacement for .animate()<\/code>. He recently wrote about<\/a> how<\/strong> JavaScript animations can be so fast over on David Walsh’s blog, a topic we’ve covered here<\/a> as well. In this article, Julian introduces Velocity.js itself.<\/em><\/p>\n

<\/p>\n

Velocity.js<\/a> is a jQuery plugin that re-implements jQuery’s $.animate()<\/code> function to produce significantly higher performance (making Velocity also faster than CSS transitions in many cases) while including several new features to improve animation workflow.<\/p>\n

In 7Kb (zipped), Velocity includes all of $.animate()<\/code>‘s features while also packing in transform animation, looping, class animation, and scrolling. In short, Velocity is designed to be the best of jQuery, jQuery UI, and CSS transitions.<\/p>\n

Velocity works everywhere \u2014 back to IE8 and Android 2.3. Further, since Velocity’s syntax is identical to $.animate()<\/code>‘s, none of your page’s code needs to change.<\/p>\n

The goal of Velocity is to be a leader in DOM animation performance and convenience. This article focuses on the latter. To learn more about the former, refer to Velocity’s performance comparisons over at VelocityJS.org<\/a>. In particular, this article demonstrates how to use Velocity to improve your UI animation workflow. In a concise showdown, eight of Velocity’s features are compared against their jQuery counterparts.<\/p>\n

If you feel that your current UI workflow is messy, poorly segregated, or too reliant upon jQuery\u2019s broad array of style functions, then this walkthrough is for you.<\/p>\n

Brief Overview<\/h3>\n

Before we dive into Velocity, let’s quickly cover the bases: It should be pointed out that both $.animate()<\/code> and $.velocity()<\/code> support a malleable options syntax. You can either pass in options as comma-separated values, or you can pass in a standalone options object.<\/p>\n

Here’s an example of the comma-separated syntax, in which an integer is treated as the animation’s duration, a string is treated as the easing type, and a function is treated as a callback (which is triggered upon the animation’s completion):<\/p>\n

$div.animate(\r\n  { \r\n    opacity: 1 \r\n  }, \r\n  1000, \r\n  \"linear\", \r\n  function() { \r\n    alert(\"Done animating.\"); \r\n  }\r\n);<\/code><\/pre>\n

Next, here’s an example of the object syntax:<\/p>\n

$div.animate(\r\n  { \r\n    opacity: 1 \r\n  }, \r\n  { \r\n    duration: 1000, \r\n    easing: \"linear\", \r\n    complete: function() { \r\n      alert(\"Done animating!\") \r\n    }, \r\n    queue: \"myQueue\" \r\n  }\r\n);<\/code><\/pre>\n

Beyond producing cleaner-looking code, using the options object provides access to additional animation parameters that are otherwise not able to be specified via the comma-separated syntax.<\/p>\n

An example of one such option provided by jQuery is “queue”. Velocity also provides the queue option, and multiple animation calls chained onto a single element automatically queue onto one another.<\/p>\n

Here, a div’s opacity will be animated to 1 for 1000ms then back down to 0 for the next 1000ms:<\/p>\n

$div\r\n  .animate({ opacity: 1 }, 1000)\r\n  .animate({ opacity: 0 }, 1000);<\/code><\/pre>\n

Now, with the bases out of the way, let’s start comparing Velocity to jQuery.<\/p>\n

Reversing<\/h3>\n

In place of a properties map, Velocity also accepts \"reverse\"<\/code> as its first parameter. Reverse animates the target element toward its values prior to its previous Velocity call.<\/p>\n

In jQuery, that would be like:<\/p>\n

$div\r\n  \/* Fade an element in while sliding it into view. *\/\r\n  .animate({ opacity: 1, top: \"50%\" })\r\n  \/* The values below are what we originally set the element to in our stylesheet. Animate back to them. *\/ \r\n  .animate({ opacity: 0, top: \"-25%\" });<\/code><\/pre>\n

In Velocity, it’s easier as it is not only less code, but you don’t have to repeat values from your stylesheet:<\/p>\n

$div\r\n  .velocity({ opacity: 1, top: \"50%\" })\r\n  .velocity(\"reverse\");<\/code><\/pre>\n

By default, Velocity’s reverse command uses the same options that were passed into the previous Velocity call. These options can be extended by passing new options into the “reverse” call. For example:<\/p>\n

$div\r\n  .velocity({ opacity: 1, top: \"50%\" }, 1000)\r\n  \/* Animate back to the prior visual state at half the duration of the previous animation. *\/\r\n  .velocity(\"reverse\", 500);<\/code><\/pre>\n

Scrolling<\/h3>\n

A popular UI technique is to scroll the browser so that it’s aligned with an element further down the page, then to animate that element with attention-grabbing flourishes. Pulling this off with jQuery involves messy, non-performant code:<\/p>\n

In jQuery, animating the scrollTop<\/code> property requires you to target both the html<\/code> element and the body<\/code> element in order for the animation to work in older versions of Internet Explorer.<\/p>\n

$(\"html, body\").animate(\r\n  { \r\n    scrollTop: $div.offset().top \r\n  }, \r\n  1000, \r\n  function() {\r\n    \/* We use a callback to fade in the div once the browser has completed scrolling. *\/\r\n    $div.animate({ opacity: 1 });\r\n  }\r\n);<\/code><\/pre>\n

In Velocity, you target the element you want to scroll to:<\/p>\n

$div\r\n  .velocity(\"scroll\", 1000)\r\n  .velocity({ opacity: 1 });<\/code><\/pre>\n

Just as with Velocity’s “reverse” command, “scroll” can be passed in as Velocity’s first parameter in place of a properties map. Also like the reverse command, the scroll command accepts animation options and can be chained onto other calls.<\/p>\n

The scroll command’s behavior is straightforward: Scroll the browser to the top of the element targeted by the Velocity call.<\/p>\n

Looping<\/h3>\n

Oftentimes, an element’s animation needs to be looped. Examples include shaking a dialog box to indicate invalid user input or bouncing a notification icon to grab the user’s attention.<\/p>\n

In jQuery, looping an animation entails messing your animation logic by breaking part of it out into a for statement:<\/p>\n

for (var i = 0; i < 5; i++) {\r\n  $div\r\n    \/* Slide the element up by 100px. *\/\r\n    .animate({ top: -100 })\r\n    \/* Then animate back to the original value. *\/\r\n    .animate({ top: 0 });\r\n}<\/code><\/pre>\n

In Velocity, simply set the loop option to an integer equal to the desired number of loop cycles. A single loop cycle consists of animating toward the values in the property map followed by reversing back to the original values.<\/p>\n

$div.velocity(\r\n  { top: -100 }, \r\n  { loop: 5 }\r\n);<\/code><\/pre>\n

Fading Elements<\/h3>\n

You’ll often find yourself fading in an element whose display property was initially set to none<\/code>, so that the element wasn’t immediately visible upon page load. Subsequently fading in these elements requires several lines of jQuery:<\/p>\n

$div\r\n  \/* Use jQuery's $.show() function to make the element visible by switching its display property to \"block\"\/\"inline\" as appropriate. *\/\r\n  .show()\r\n  \/* Set the element's starting opacity to 0 so that it can be gradually faded in by the subsequent animation call. *\/\r\n  .css(\"opacity\", 0)\r\n  \/* Fade in and slide into view. *\/\r\n  .animate({ \r\n    opacity: 1, \r\n    top: \"50%\" \r\n  });<\/code><\/pre>\n

In Velocity, you simply pass in display as an option. The display option accepts the same set of values that its CSS property counterpart does (e.g. “block”, “inline”, and “none”).<\/p>\n

$div.velocity(\r\n  { \r\n    opacity: 1, \r\n    top: \"50%\" \r\n  },\r\n  { \r\n    display: \"block\" \r\n  }\r\n);<\/code><\/pre>\n

When the display<\/code> option is set to a value other than none<\/code>, the element’s display<\/code> property is set to the provided value at the start<\/em> of the animation. Conversely, when display is passed a value of none<\/code>, the display property is set upon the animation’s completion<\/em>.<\/p>\n

$div\r\n  \/* Fade out and slide out of view. *\/\r\n  .animate({ opacity: 0, top: \"-50%\" })\r\n  \/* Then set the display property to \"none\" via a queued $.fadeOut() call. *\/\r\n  .fadeOut(1);<\/code><\/pre>\n
$div.velocity(\r\n  { \r\n    opacity: 0,\r\n    top: \"-50%\" \r\n  }, \r\n  { \r\n    display: \"none\" \r\n  }\r\n);<\/code><\/pre>\n

Further, if an element’s opacity<\/code> is being animated to a non-zero value while its display<\/code> option is being set to a value other than none<\/code>, Velocity conveniently defaults opacity<\/code>‘s start value to 0.<\/p>\n

Delaying<\/h3>\n

Velocity accepts a delay option that replaces having to sprinkle $.delay()<\/code> calls throughout your animation code:<\/p>\n

$div\r\n  .delay(1000)\r\n  .animate({ \r\n    opacity: 1 \r\n  });<\/code><\/pre>\n
$div.velocity(\r\n  { \r\n    opacity: 1 \r\n  }, \r\n  { \r\n    delay: 1000 \r\n  }\r\n);<\/code><\/pre>\n

Beyond consolidating animation logic into a single call, using Velocity’s built-in delay option allows Velocity to optimize chained animations by caching values between them.<\/p>\n

Sequences<\/h3>\n

A feature unique to Velocity is sequences<\/em>, which are macros for animations: An animation sequence is created once, then it can be subsequently triggered when desired across elements on all your pages.<\/p>\n

The benefits of sequences include:<\/p>\n