January 20 2016

Angular ngAnimate Tutorial & Example with UI Router

In this tutorial I'll show you how you can implement animations between routes in your Angular project using ngAnimate and the Angular UI Router.

The example in this post is built with Angular and ngAnimate version 1.4.8 and uses CSS transitions to perform the animations.

Here's the example application in action, it uses a fade transition between top level tabs and a slide in/out transition on the products page for adding and editing a product.

(See on Plunker at http://plnkr.co/edit/nzln5V?p=preview)

Project is also available on GitHub at https://github.com/cornflourblue/ng-animate-ui-router-example

The example uses bootstrap and a few other pieces as well but I'll focus on how the transitions work in this post, the rest is there so I could demonstrate the animations in a real world-ish example.

Add ngAnimate as a dependency to your Angular application

The first step is to add the angular animate library to your application, to do this add this script tag to your root html file (usually index.html):

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>


Then add 'ngAnimate' as a dependency to your angular application like this:

angular
    .module('app', ['ui.router', 'ngAnimate'])
    .config(config)
    .run(run);


Add CSS 'transition' styles to your views to enable animation

The way ngAnimate works is by adding the following classes to your view elements while changing between routes/states:

  • .ng-enter - added at the very start of the transition to enter/display a view
  • .ng-enter-active - also added at the start of the transition, immediately after adding .ng-enter
  • .ng-leave - added at the very start of the transition to leave/hide a view
  • .ng-leave-active - also added at the start of the transition, immediately after adding .ng-leave


IMPORTANT: To enable this functionality you must add a CSS 'transition' property to either/both of the .ng-enter/.ng-leave classes for the views that you want to animate.

For example the main view in the above plunk performs a 0.5 second fade in transition when entering into a view using the following styles:

main {
    /* start 'enter' transition */
    &.ng-enter {
        /* transition on enter for .5s */
        transition: .5s;

        /* start with opacity 0 (invisible) */
        opacity: 0;
    }

    /* end 'enter' transition */
    &.ng-enter-active {
        /* end with opacity 1 (fade in) */
        opacity: 1;
    }
}


As you can see there's only a transition on .ng-enter and not on .ng-leave, which is why the new view (that is entering) fades in on each tab change while the old view (that is leaving) disappears instantly without a transition.


A slightly trickier animation involving multiple child elements

Getting the slide in/slide out animation working for the product add/edit view is a bit trickier because it requires animating multiple child elements in different ways, i.e. the background div fades in and out while the content div slides in and out.

Even though I'm only animating child elements, I still need to add the CSS 'transition' property to the .ng-enter and .ng-leave classes for the view (since I'm animating on both enter and leave), otherwise ngAnimate would not be enabled for the view.

I then also added CSS transition rules for the .background and .content child elements in order to fade the background in and out while sliding the content in and out of view.

It's important to keep all of the child element transition times the same as the view transition time (in this case 0.5 seconds) to keep the transitions smooth.

Here's the snippet from the example app.less file showing all the style rules for the side form along with detailed comments:

/* side form */
.view-side-form {
    .side-form {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;

        .content {
            position: absolute;
            z-index: 100;
            top: 0;
            right: 0;
            width: 80%;
            height: 100%;
            overflow: auto;
            background: #fff;
            padding: 20px;
            border-left: 1px solid #e0e0e0;
        }

        .background {
            background: #000;
            opacity: .8;
            width: 100%;
            height: 100%;
        }
    }


    /* TRANSITION ANIMATIONS FOR SIDE FORM VIEW
    ------------------------------------------*/

    /* enable animations for side form view */
    &.ng-enter, 
    &.ng-leave {
        /* transition on enter and leave for .5s */
        transition: .5s;
    }

    /* start 'enter' transition */
    &.ng-enter {
        .side-form {
            .content {
                /* start with content 80% off the right of the page */
                right: -80%;
            }

            .background {
                /* start with background opacity 0 (invisible) */
                opacity: 0;
            }
        }
    }

    /* end 'enter' transition */
    &.ng-enter-active {
        .side-form {
            .content {
                /* transition the right position which 
                   slides the content into view */
                transition: right .5s;

                /* end with content aligned to the right of the page */
                right: 0;
            }

            .background {
                /* transition the background opacity to fades it in */
                transition: opacity .5s;

                /* end with background opacity 0.8 to give the overlay effect */
                opacity: .8;
            }
        }
    }

    /* end 'leave' transition */
    &.ng-leave-active {
        .side-form {
            .content {
                /* transition the right position which 
                   slides the content out of view */
                transition: right .5s;
                
                /* end transition with the content completely off the page */
                right: -100%;
            }

            .background {
                /* transition the background opacity to fades it out */
                transition: opacity .5s;

                /* end with background opacity 0 to hide it */
                opacity: 0;
            }
        }
    }
}

 

Web Development and AngularJS Development Sydney

Feel free to drop me a line if you're looking for web development or AngularJS development or consulting services in Sydney Australia, I also provide remote contracting services for clients outside Sydney.


Sponsored by