Architecture & DesignIntro to Animations in AngularJS

Intro to Animations in AngularJS

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

By Lukas Ruebbelke

AngularJS was originally created as a framework to handle enterprise CRUD applications. With the introduction of the new animations API, AngularJS has broadened the possibilities to offer something for designers and developers alike.

The most powerful aspect of AngularJS is directives, and AngularJS animations are essentially class-based directives that have the power to harness complex animations with the addition of a single class to your markup.

In this article, we’re not going to examine CSS3 animations or JavaScript animations in depth, but rather endeavor to lay a strong foundation that you can let your creativity run wild on.

How AngularJS handles animations

AngularJS animations can be distilled down to five events and a class-based naming convention. Once you’ve grasped the events at play and the naming convention, AngularJS animations fade into the background and the animations themselves take center stage.

There are three types of animations that you can create with AngularJS: CSS transitions, CSS animations, and JavaScript animations. Each type of animation is well suited for varying contexts.

AngularJS doesn’t actually do any of the animations themselves, but simply provides the hooks for you to apply your own animations as you see fit. These hooks come in the form of events, and there are only five of them.

The five animation events are enter, leave, move, addClass, and removeClass (see table 1).

Table 1 The AngularJS animation furious five

Event

Function

Description

enter $animate.enter(element, parent, after, callback); Appends the element object after the after node or within the parent node and then runs the enter animation on the element
leave $animate.leave(element, callback); Runs the leave animation and then removes the element from the DOM
move $animate.move(element, parent, after, callback); Moves the element node either after the after node or inside of the v node and then runs the move animation on the element
addClass $animate.addClass(element, className, callback); Runs the addClass animation based on the className value and then adds the class to the element
removeClass $animate.removeClass(element, className, callback); Runs the removeClass animation based on the className value and then removes the class from the element

The enter and leave events are fired when a DOM element is added or removed from the DOM tree, respectively. The move event is fired when a DOM element changes position within the DOM tree. Last but not least, the addClass and removeClass events are fired when a class is added to or removed from an element, respectively.

The animation-naming convention

AngularJS animations are entirely class-based, which is a design decision that makes integration with third-party libraries easier. Even JavaScript animations follow a classbased naming convention for consistency.

The animation-naming convention follows a [class][event]-[state] pattern, as shown in figure 1. This figure indicates that we’re dealing with a mute class that’s being added and removed, as seen by .muteadd and .mute-remove. The animation defaults to the starting state and then progresses to the active state, as in “the class has been actively applied.” The starting state is .mute-add, and .mute-add-active is the active or completed state.

Angular1
Figure 1: The animation-naming convention applied to directives

If your animations are defined within CSS and the events are triggered by an AngularJS directive such as ng-if or ng-repeat, then the class name will be prefixed with an ng, as in ng-enter and ng-leave.

Animations enable!

The most logical place to start from a pragmatic sense is with how you enable animations within your AngularJS application. AngularJS animations aren’t part of the AngularJS core, so you have to include that as a separate file. We’ll use GreenSock Animation Platform (GSAP), which is a JavaScript animation framework. We want the TweenMax library, which contains everything GreenSock has to offer.

// client/assets/js/boot.js { file:
   '//cdnjs.cloudflare.com/ajax/libs/angular.js/
      1.3.3/angular-animate.min.js'
},
{ file:
   '//cdnjs.cloudflare.com/ajax/libs/gsap/latest/
      TweenMax.min.js'
},

(You can read more about GreenSock at http://www.greensock.com/gsap-js/.)

Now that angular-animate.min.js has been included, we need to inject it as a sub-module into our application:

// client/src/angello/Angello.js var myModule =
      angular.module('Angello', [ //...
   'ngAnimate', //...
]);

With those two steps completed, we’re ready to start adding animations to our application.

CSS transitions

The easiest animations to implement are CSS transitions. The ease of implementation comes from the fact that they’re entirely CSS-based and much more concise to express than CSS animations.

We’ll create a my-fade animation and apply it to a div that will trigger the animation when the div is added or removed from the DOM via ng-if. This animation will toggle the visibility of the story details in the right column when the Angello application is running in storyboard mode (see table 2).

Table 2: The animation-naming convention

Event

Starting CSS class

Ending CSS class

Directives that fire it

enter .ng-enter .ng-enter-active ngInclude ngIf, ngView
leave .ng-leave .ng-leave-active ngRepeat, ngInclude, ngIf, ngView
move .ng-move .ng-move-active ngRepeat

Define the base transition

The first thing you need to do when constructing a CSS transition within AngularJS is set up the base transition. Because we’re using ng-if to trigger the animation and the event is caused by an AngularJS directive, we need to define the classes for ng-enter and ng-leave:

/* client/assets/css/animations.css */
.my-fade-animation.ng-leave {
   -webkit-transition: 0.5s linear all;
   -moz-transition: 0.5s linear all;
   -o-transition: 0.5s linear all;
      transition: 0.5s linear 
}

In this code we define the transition for ng-enter and ng-leave on the my-fade animation to use linear easing that lasts for 0.5 seconds and applies to all properties.

Define the ng-enter transitions

The next step is to define the starting and stopping states for ng-enter. We’ll start with an opacity of 0 and finish with an opacity of 1. This means that when the element is added, it’ll start completely transparent and then fade in to full opacity.

/* client/assets/css/animations.css */
.my-fade-animation.ng-enter {
   opacity: 0;
}

.my-fade-animation.ng-enter.ng-enter-active {
   opacity: 1;
}

Define the ng-leave transitions

We’ll now define the transition for ng-leave, which is usually the reverse of what you did for ng-enter. We’ll start with an opacity of 1 and end with an opacity of 0:

.my-fade-animation.ng-leave {
   opacity: 1;
}

.my-fade-animation.ng-leave.ng-leave-active {
   opacity: 0;
}

For the sake of illustration, we’ve separated the ng-enter and ng-leave classes, but you could easily combine them for conciseness:

.my-fade-animation.ng-enter,
.my-fade-animation.ng-leave.ng-leave-active {
   opacity: 0;
}

.my-fade-animation.ng-leave,
.my-fade-animation.ng-enter.ng-enter-active {
   opacity: 1;
}

Making it move

Now that the CSS classes have been defined, it’s a matter of attaching them to the DOM for use. Now you’ll see what we mean when we say AngularJS transitions are essentially class-based directives that encapsulate animation functionality.

This is the HTML without the animation:

<!-- client/src/angello/storyboard/tmpl/storyboard.html -->
   <div class="details">

   <!-- ... -->
   <div ng-if="storyboard.detailsVisible">
      <!-- ... -->
   </div>
</div>

This is the HTML with the animation:

<!-- client/src/angello/storyboard/tmpl/storyboard.html -->
<div class="details">
   <!-- ... -->
   <div ng-if="storyboard.detailsVisible"
         class="my-fade-animation"
      > <!-- ... -->
   </div>
</div>

And so the only part left in this section is to actually toggle ng-if:

// client/src/angello/storyboard/controllers/StoryboardController.js
// angular.module('Angello.Storyboard')
   .controller('StoryboardCtrl', function ($scope, $log,
      StoriesModel, UsersModel, STORY_STATUSES,
      STORY_TYPES) { //...
      storyboard.detailsVisible = true; //...
      storyboard.setDetailsVisible = function (visible) {
         storyboard.detailsVisible = visible;

      };
});

In the StoryboardCtrl, we create a property on our $scope reference, called detailsVisible, that we’ll use to bind ng-if to. We also create a method called setDetailsVisible that we use to set detailsVisible to true or false based on the value of the visible parameter.

In the HTML, we bind to detailsVisible via ng-if=”storyboard.detailsVisible”:

<!-- client/src/angello/storyboard/tmpl/storyboard.html -->
<div class="details">
   <div class="details-nav">
      <div ng-if="!storyboard.detailsVisible">
         <button class="btn pull-left btn-default"
               ng-click="storyboard.setDetailsVisible(true)">
            <span class="glyphicon glyphicon-arrow-left"></span>
         </button>
      </div>
      <div ng-if="storyboard.detailsVisible">
         <button class="btn pull-right btn-default"
            ng-click="storyboard.setDetailsVisible(false)">
            <span class="glyphicon glyphicon-arrow-right"></span>
         </button>
      </div>
   </div>
   <div ng-if="storyboard.detailsVisible" class="my-fade-animation">
      <!-- ... -->
   </div>
</div>

Note that we also have two other divs that are being toggled based on the property of detailsVisible. If detailsVisible is true, then the button to set detailsVisible to false is shown, and vice versa.

We’ve now completed the functionality for attaching a CSS transition to our application.

Angular2

AngularJS: Intro to animations

By Lukas Ruebbelke

Excerpted from the book AngularJS in Action.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories