Animating Awesomeness with Velocity.js

Julian Shapiro reached out, asking me if I'd take a look at a new animation framework he had built. The core concept of Velocity.js is to replace the $.animate function from jQuery with a much faster, more robust, and more diverse solution. The result? Julian has done his research and what he's built may just change the way we all think about JS and CSS animations.

Julian has documented Velocity.js extremely well so I won't waste your time reiterating that. Rather, I will try and show you just how cool Velocity.js can be.

Demo

I want to create a scene consisting of an earth and sky. One that would typically be found in a 2D video game. Then I want to animated it in a way that makes it appear to being built right in front of my eyes.

Animated town demo

First, I downloaded an amazing hexagon tile library from OpenGameArt and used the included sprites as a source for my scene. I determined the correct dimensions for a tile, a row, and styled my elements accordingly. Then I wrote a quick function to lay the tiles based on a JSON object.

var earth = {
  first: [ 
    { count: 4, tile: "ledge" }, 
    { count: 3, tile: "water-ledge" }, 
    { count: "rest", tile: "ledge" } 
  ],
  second: [ 
    { count: 4, tile: "grass" }, 
    { count: 4, tile: "water" }, 
    { count: "rest", tile: "grass" } 
  ],
  ...
};

layTiles(earth, 'earth');

The layTiles function loops through each row and lays out the specified tiles based on the window width. I wrote a helper function to plop structures on a specific row and spot, and I added an air element to provide the backdrop, or sky.

Now that the scene is displaying how I'd like, I want to animate it all. That's where Velocity comes in— we're going to loop through all of the tiles, animating them in different ways to give the impression that the world is coming together piece-by-piece.

First, I'll hide the tiles and raise the scene's holder element so I can "drop it in".

$('.canvas').css('bottom', ($(window).height()));
$('tile').css('opacity', 0);

Now, I can start with the animations. Using Velocity's complete callback, I'm able to wrap this all together and fire the animations one after another.

$('.canvas').velocity({bottom: "-1px"}, {duration: 600, 
  complete: function() {

    $($('earth tile').get().reverse()).each(function(i) {

      var $me = $(this);

      // Bounce down at first
      $me.velocity({
      	translateY: 15, 
      	opacity: 0.5}, 
      {
      	duration: 100, 
      	delay: (i*30), 
      	complete: function() {

          // Done. Bounce back up
          $me.velocity({
          	translateY: 0, 
          	opacity: 1}, 
          {
          	duration: 100, 
          	easing: "swing"
        });

        // Just before all tiles have bounced
        if(i==($('earth tile').length-15)) {
          
          $('structure').each(function(s) {

            var $structure = $(this);

            window.setTimeout(function() {
              
              // Build the structures, one-by-one
              $structure.find('tile').each(function(t) {

                $(this).velocity({
                	translateY: [0, 50], 
                	opacity: 1}, 
                {
                	duration: 200, 
                	delay: (t*50), 
                	easing: "spring"
                });
              });
            }, (s*200));
          });
        }
      }});
    });
  }
});

In the beginning, I'm animating my "canvas" down from above. After that completes, I'm looping through the earth's tiles. I complete two animations on each tile to give them the "bounce" effect I'm looking for. Just before the earth's tiles all finish animating, I move on to the structures with the goal of having them appear to be built from the ground up. Because I don't want them to all be built at the same time, I'm using the delay option. Lastly, I'm using the built-in "spring" variable for easing, which really gives the structures the illusion of being built piece-by-piece.

My next steps would be to add some elements to the sky followed by some extra pieces to the earth. Using Velocity, I could continue the animation of my evolving earth by plopping in plants, creatures, and more structures. After that, I could listen for a keypress or click then have Velocity animate my objects around my world.

In closing

Velocity is super impressive and I know I've only really scratched the surface. I wrote this same scene using CSS animations exclusively and Velocity doesn't skip a beat handling the same tasks, all the while giving me the power of an extremely robust API. I'm super excited about the possibilities and am really looking forward to implementing Velocity into some of my iOS projects.