AngularJS From Beginning: Mobile Animation - Part 19

I am here to continue the discussion around AngularJS. Today, we will discuss how to create mobile device related animation using angular js. Also in case you have not had a look at our previous articles of this series, go through the following links:

In the previous articles, we already discussed how to create animations using both JavaScript and CSS in the AngularJS context for native and custom directives. Now, in this article, we will learn how to enhance the user experience of our AngularJS web app, especially on mobile devices and tablets.

Enhance UX on mobile devices with animations

With the increasing use of smartphones and tablet devices, more people have started to visit websites via smartphones and other devices, so not optimizing a web app for small devices is not an option anymore. Nowadays, we create a single web app that is responsive to the device width using CSS3 media queries. So, we are able to define different styles for each device width size. We can provide a better experience based on the screen size. Currently, web apps are run on small screens of devices such as smartphones and also on screens as big as that of TVs. It's impossible to create a CSS style for each device width in the world, so usually, we work with different ranges of screen widths: smartphones, tablets and small desktops, and big desktops monitors. As we usually use CSS animations to animate in the AngularJS context, we are able to define animations in a specific media query. So, we might disable some heavy-processing animations and enable other GPU-accelerated animations for small screens.

The motion created by animations on web apps is better delivered when it seems more realistic. One of the material design guidelines is to avoid linear animations as it's a more mechanical and artificial movement than animations with acceleration and deceleration at the beginning and ending of an animation curve. This guideline is called authentic motion. Another important guideline is meaningful transitions, the next section's subject.

Transition between views

The Google material design website explains transitioning as follows:

"Transitioning between two visual states should be smooth, appear effortless, and above all, provide clarity to the user, not confusion. A well-designed transition does the heavy lifting and enables the user to clearly understand where their attention should be focused. A transition has three categories of elements."

The three categories of elements are the incoming elements, outgoing elements, and shared elements. A common transition to web apps is changing the main content view, for instance, using ngView or ngInclude. Smartphones and devices with touchscreens provide a different interaction for the user. Taps and gestures are used instead of clicks. The ngTouch module enables us to use swipe gestures and the ngClick directive is replaced for a better tap experience on touchscreen devices. To create this transition of views animation, we will use the ngInclude directive.
 
Index.html
  1. <!DOCTYPE html>  
  2. <html ng-app="myApp">  
  3. <head>  
  4.     <title>AngularJS Swipe Slider animation</title>  
  5.     <meta name="viewport" content="width=device-width,height=deviceheight,user-scalable=no">  
  6.     <link href="mobile.css" rel="stylesheet" />  
  7.     <link href="bootstrap.css" rel="stylesheet" />  
  8.   
  9.     <script src="angular.min.js"></script>  
  10.     <script src="angular-touch.min.js"></script>  
  11.     <script src="angular-animate.min.js"></script>  
  12.     <script src="tabsSwipeCtrl.js"></script>  
  13. </head>  
  14. <body>  
  15.     <div ng-controller="tabsSwipeCtrl as responsive">  
  16.         <div class="btn-group btn-group-justified">  
  17.             <div class="btn-group">  
  18.                 <button type="button" class="btn btn-default" ngclick="responsive.selectPage(0)" ng-class="{'active': responsive.ngIncludeSelected.index == 0}">  
  19.                     First  
  20.                 </button>  
  21.             </div>  
  22.             <div class="btn-group">  
  23.                 <button type="button" class="btn btn-default" ngclick="responsive.selectPage(1)" ng-class="{'active': responsive.ngIncludeSelected.index == 1}">  
  24.                     Second  
  25.                 </button>  
  26.             </div>  
  27.             <div class="btn-group">  
  28.                 <button type="button" class="btn btn-default" ngclick="responsive.selectPage(2)" ng-class="{'active': responsive.ngIncludeSelected.index == 2}">  
  29.                     Third  
  30.                 </button>  
  31.             </div>  
  32.             <div class="btn-group">  
  33.                 <button type="button" class="btn btn-default" ngclick="responsive.selectPage(3)" ng-class="{'active': responsive.ngIncludeSelected.index == 3}">  
  34.                     Fourth  
  35.                 </button>  
  36.             </div>  
  37.         </div>  
  38.         <div class="ngIncludeRelative">  
  39.             <div class="ngIncludeItem" ng-include="responsive.ngIncludeSelected.url" ng-class="{'moveToLeft' : responsive.moveToLeft}"></div>  
  40.         </div>  
  41.     </div>  
  42.       
  43. </body>  
  44. </html>  

We added the ngSwipeLeft and ngSwipeRight directives from the ngTouch module to the partial view, so the user can change between views by swiping gestures.

FirstSwipe.html
  1. <div class="firstPage page" ng-swipe-left="responsive.selectPage(1)">  
  2.     <h2>First page</h2>  
  3.     <p>Swipe to the left to go to second page</p>  
  4. </div>  
SecondSwipe.html
  1. <div class="secondPage page" ng-swipe-left="responsive.selectPage(2)"  
  2.      ng-swipe-right="responsive.selectPage(0)">  
  3.     <h2>Second page</h2>  
  4.     <p>Swipe to the right to go to first page</p>  
  5.     <p>Swipe to the left to go to third page</p>  
  6. </div>  
ThirdSwipe.html  
  1. <div class="thirdPage page" ng-swipe-left="responsive.selectPage(3)"  
  2.      ng-swipe-right="responsive.selectPage(1)">  
  3.     <h2>Third page</h2>  
  4.     <p>Swipe to the left to go to fourth page</p>  
  5.     <p>Swipe to the right to go to second page</p>  
  6. </div>  
FourthSwipe.html
  1. <div class="page" ng-swipe-right="responsive.selectPage(2)">  
  2.     <h2>Fourth page</h2>  
  3.     <p>Swipe to the right to go to third page</p>  
  4. </div>  

To create the desired animation effect, we will use a combination of ngInclude and ngClass. The ngClass directive will be used to learn the direction of the animation on the enter and leave events of the pages.

Mobile.css
  1. body {  
  2.     overflow-x: hidden;  
  3. }  
  4.   
  5. .ngIncludeItem {  
  6.     position: absolute;  
  7.     top: 35px;  
  8.     bottom: 0;  
  9.     right: 0;  
  10.     left: 0;  
  11.     animation-duration: 0.30s;  
  12.     animation-timing-function: ease-in-out;  
  13. }  
  14.   
  15. .page {  
  16.     position: inherit;  
  17.     top: 0;  
  18.     right: inherit;  
  19.     bottom: inherit;  
  20.     left: inherit;  
  21. }  
  22.   
  23. .firstPage {  
  24.     background-color: blue;  
  25. }  
  26.   
  27. .secondPage {  
  28.     background-color: red;  
  29. }  
  30.   
  31. .thirdPage {  
  32.     background-color: green;  
  33. }  
  34. /* When the page enters, slide it from the right */  
  35. .ngIncludeItem.ng-enter {  
  36.     animation-name: slideFromRight;  
  37.     -webkit-animation-name: slideFromRight;  
  38. }  
  39. /* When the page enters and moveToLeft is true, slide it from the  
  40. left(out of the user view) to the right (left corner) */  
  41. .ngIncludeItem.moveToLeft.ng-enter {  
  42.     animation-name: slideFromLeft;  
  43.     -webkit-animation-name: slideFromLeft;  
  44. }  
  45. /* When the page leaves, slide it to left(out of the user view) from  
  46. the left corner,  
  47. in other words slide it from the left(out of the view) to the left  
  48. corner but in reverse order */  
  49. .ngIncludeItem.ng-leave {  
  50.     animation-name: slideFromLeft;  
  51.     animation-direction: reverse;  
  52.     -webkit-animation-name: slideFromLeft;  
  53.     -webkit-animation-direction: reverse;  
  54. }  
  55. /* When the page leaves, slide it to the right(out of the user view)  
  56. from the the left corner,  
  57. in other words, slide it from the right but in reverse order */  
  58. .ngIncludeItem.moveToLeft.ng-leave {  
  59.     animation-name: slideFromRight;  
  60.     animation-direction: reverse;  
  61.     -webkit-animation-name: slideFromRight;  
  62.     -webkit-animation-direction: reverse;  
  63. }  
  64.   
  65. @keyframes slideFromRight {  
  66.     0% {  
  67.         transform: translateX(100%);  
  68.     }  
  69.   
  70.     100% {  
  71.         transform: translateX(0);  
  72.     }  
  73. }  
  74.   
  75. @keyframes slideFromLeft {  
  76.     0% {  
  77.         transform: translateX(-100%);  
  78.     }  
  79.   
  80.     100% {  
  81.         transform: translateX(0);  
  82.     }  
  83. }  

This combination of the moveToLeft, ng-enter, and ng-leave classes are used to trigger the animations in the mobile.css file using the direction based on the current page and the tab page the user will navigate to:

Tabswipectrl.js
  1. function tabsSwipeCtrlFn() {  
  2.     var responsive = this;  
  3.     responsive.ngIncludeTemplates = [  
  4.         { index: 0, name: 'first', url:    'firstSwipe.html' },  
  5.         { index: 1, name: 'second', url: 'secondSwipe.    html' },  
  6.         { index: 2, name: 'third', url: 'thirdSwipe.html' },  
  7.         { index:    3, name: 'fourth', url: 'fourthSwipe.html' }];  
  8.   
  9.     responsive.selectPage = selectPage;  
  10.   
  11.     responsiveresponsive.ngIncludeSelected =  
  12.     responsive.ngIncludeTemplates[0];  
  13.       
  14.     function selectPage(indexSelected) {  
  15.         if (responsive.ngIncludeTemplates[indexSelected].index >  
  16.         responsive.ngIncludeSelected.index) {  
  17.             responsive.moveToLeft = false;  
  18.         } else {  
  19.             responsive.moveToLeft = true;  
  20.         }  
  21.         responsiveresponsive.ngIncludeSelected =  
  22.         responsive.ngIncludeTemplates[indexSelected];  
  23.     }  
  24. }  
  25. var app = angular.module('myApp', ['ngAnimate', 'ngTouch']).controller('tabsSwipeCtrl', tabsSwipeCtrlFn);  

AngularJS 2.0 Touch Animations is currently being drafted, and its focus is to provide better solutions for mobile devices, the same focus as that of AngularJS 2.0. This draft includes better handling of scrolling through a list using a finger, circling through pictures in a carousel, removing of items on swipe, and more native app features. We can expect improvements for the future on AngularJS core, so things such as the infinite scrolling core will be standardized and not spread to many third-party AngularJS modules.

Mobile AngularJS frameworks

Nowadays, mobile features can be added to AngularJS web apps using external frameworks such as. It provides some great directives that uses the ngAnimate module behind the scenes to create those touch animations features. The Ionic framework is a framework for hybrid mobile apps with HTML5. In other words, the framework is focused on the use of native apps, not for responsive web apps. This is a good choice if you want to create native apps using HTML, CSS, and JavaScript together with Apache Cordova or PhoneGap.

The output of the above code is,