Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

AngularJS applies animations


May 08, 2021 AngularJS


Table of contents


Apply an animation

In this final step, we'll enrich our mobile classification site app by adding CSS and JavaScript animations at the top of the template code we created earlier.

  • We now ngAnimate simulation to enable animation throughout the app.
  • We also use ng instructions to automatically trigger hooks that make animation access.
  • When an app is discovered, the animation runs between standard DOM operations, which are published on ngRepeat ngClass

Reset the workspace to step 12

git checkout -f step-12

Refresh your browser or check this step online: Step 12 Live Demo

The most important differences between steps 11 and 12 are listed below. You can see the full difference on GitHub.

Dependence

Angular provides ngAnimate module, which is released separately from the core Angler framework. In addition, we'll use jquery JavaScript animation in our project.

We are using Bower to install customer side dependencies. This step updates the bower.json profile to include new dependencies:

{
  "name": "angular-seed",
  "description": "A starter project for AngularJS",
  "version": "0.0.0",
  "homepage": "https://github.com/angular/angular-seed",
  "license": "MIT",
  "private": true,
  "dependencies": {
    "angular": "1.4.x",
    "angular-mocks": "1.4.x",
    "jquery": "~2.1.1",
    "bootstrap": "~3.1.1",
    "angular-route": "1.4.x",
    "angular-resource": "1.4.x",
    "angular-animate": "1.4.x"
  }
}
  • "angular-animate": "1.4.x" tells bower to install a version of the angular-animate component that is compatible with v1.4x.
  • "jquery": "~2.1.1" tells bower to install jQuery's v2.1.1 version. N ote that this is not an Angular library, it is a standard jQuery library. We can use bower to install a large scope of third-party libraries.

We must ask bower to implement it by downloading and installing dependencies to run the following instructions:

npm install
Warning: If you've released a new version of Angular since you last ran 'npm install', you may have trouble running the 'bower install' instruction because of a conflict between versions of the angular.js that need to be installed. If you're having this problem, just delete your 'app/bower_components' folder before running 'npm install'.
Note: If you are globally secured bower, you can run 'bower install', but for this project, we have pre-configured to run 'npm install' to run bower.

How animations work ngAnimate

To find out how animations work with AngelJS, read them first. AngularJS Animation Guide.

Template

Inside the HTML template code, you need to modify it to link the asat file, which defines the animation as well angular-animate.js file. The animation module, ngAnimate is angular-animate.js and contains the necessary code to make your application dynamic.

Here's where you need to modify it in the index file:

app/index.html .

...
  <!-- for CSS Transitions and/or Keyframe Animations -->
  <link rel="stylesheet" href="css/animations.css">

  ...

  <!-- jQuery is used for JavaScript animations (include this before angular.js) -->
  <script src="/attachments/image/wk/angularjs/jquery.js"></script>

  ...

  <!-- required module to enable animation support in AngularJS -->
  <script src="/attachments/image/wk/angularjs/angular-animate.js"></script>

  <!-- for JavaScript Animations -->
  <script src="/attachments/image/wk/angularjs/animations.js"></script>

...
Important: Make sure you use jQuery v2.1 or an updated version when using Augular 1.4; Make sure to load jQuery before all AngelJS scripts, otherwise AugularJS will not detect jQuery and the animation will not work as expected.

You can create animations.css or within animations.js But before we get started, let's create a new module that uses the ngAnimate module as a dependency, as we ngResource before.

Modules and animations

app/js/animations.js .

angular.module('phonecatAnimations', ['ngAnimate']);
  // ...
  // this module will later be used to define animations
  // ...

Now let's attach this module to our application module...

app/js/app.js .

// ...
angular.module('phonecatApp', [
  'ngRoute',

  'phonecatAnimations',
  'phonecatControllers',
  'phonecatFilters',
  'phonecatServices',
]);
// ...

Now, the mobile phone classification module is already dynamic. Let's make more animations!

Use CSS transition animation to get ngRepeat moving.

From this step, we'll add the CSS transition animation to the ngRepeat .html appear on the phone-list.html page. First let's add an additional CSS class to our repeating element, so we can connect it to our CSS animation code.

app/partials/phone-list.html .

<!--
  让我们改变重复器HTML,以包含一个新的CSS类,之后我们将用它实现动画:
-->
<ul class="phones">
  <li ng-repeat="phone in phones | filter:query | orderBy:orderProp"
      class="thumbnail phone-listing">
    <a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
    <a href="#/phones/{{phone.id}}">{{phone.name}}</a>
    <p>{{phone.snippet}}</p>
  </li>
</ul>

Notice how we're phone-listing CSS class? That's what we need to do to make the animation work in HTML code.

Here's the actual CSS transition animation code:

app/css/animations.css

.phone-listing.ng-enter,
.phone-listing.ng-leave,
.phone-listing.ng-move {
  -webkit-transition: 0.5s linear all;
  -moz-transition: 0.5s linear all;
  -o-transition: 0.5s linear all;
  transition: 0.5s linear all;
}

.phone-listing.ng-enter,
.phone-listing.ng-move {
  opacity: 0;
  height: 0;
  overflow: hidden;
}

.phone-listing.ng-move.ng-move-active,
.phone-listing.ng-enter.ng-enter-active {
  opacity: 1;
  height: 120px;
}

.phone-listing.ng-leave {
  opacity: 1;
  overflow: hidden;
}

.phone-listing.ng-leave.ng-leave-active {
  opacity: 0;
  height: 0;
  padding-top: 0;
  padding-bottom: 0;
}

As you can see, phone-listing CSS class combines with animated hooks, which appear when items are inserted or removed from the list.

  • When a new phone is added to the list and rendered on a Web page, the ng-enter element.
  • As the item moves around the list, the ng-move class is applied to the element.
  • When an item is removed from the list, the ng-leave element.

Adding or deleting phone list items depends on the data passed ng-repeat For example, if the filter data changes, the item annimately joins or exits the duplicate list.

There are some important things to note that when an animation occurs, two collections of CSS classes are added to the element:

  1. The Start class represents the style at the beginning of the animation.
  2. The Activation class represents the style at the end of the animation.

The name of the start class is the name of the event enter move leave with the ng- . So an enter causes a class ng-enter

The activation class name is the same as the start class name, but with a suffix -active These two types of CSS naming conventions allow developers to craft an animation from start to finish.

In our example above, when an element is added to a list, it extends from a height of 0 to a height of 120 pixels, and shrinks to 0 pixels before being removed from the list. A t the same time, there is a fading and fading effect. This is all handled by CSS transition animation, which is declared at the top of the sample code above.

Although most modern browsers support CSS transitions and CSS animations well. But if you want to make animations backward compatible with older browsers, consider using JavaScript-based animations, which are explained in more detail below.

Get ngView moving with CSS ngView animation

Next, let's add an animation to the transition between routes within ngView

First, let's add a new CSS class to HTML, as we did in the example above. T his time, instead of using ng-repeat add it to the element that contains the ng-view instruction. To do this, we need to make some small changes to the HTML code so that we can have more control over our animation, the animation between view changes.

app/index.html .

<div class="view-container">
  <div ng-view class="view-frame"></div>
</div>

With this change, ng-view instruction is nested inside a parent element with a view-container CSS class. This class adds a position: relative so during animation, ng-view positioned relative to this parent element.

Here, let's add CSS to the transition animation animations.css animation files:

app/css/animations.css .

.view-container {
  position: relative;
}

.view-frame.ng-enter, .view-frame.ng-leave {
  background: white;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.view-frame.ng-enter {
  -webkit-animation: 0.5s fade-in;
  -moz-animation: 0.5s fade-in;
  -o-animation: 0.5s fade-in;
  animation: 0.5s fade-in;
  z-index: 100;
}

.view-frame.ng-leave {
  -webkit-animation: 0.5s fade-out;
  -moz-animation: 0.5s fade-out;
  -o-animation: 0.5s fade-out;
  animation: 0.5s fade-out;
  z-index:99;
}

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@-moz-keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@-webkit-keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@-moz-keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@-webkit-keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* 别忘了供应商的前缀! */

Nothing amazing! I t's just a simple fade-out and fade-out effect between two pages. T he only unusual thing here is that when we implement a soft-switch animation between pages, we use absolute positioning above the previous page ng-leave classes) ng-enter So when the previous page is about to be deleted, it fades out, while the new page gradually appears on top of it.

Once you leave the end of the animation, the element is removed, and once you enter the end ng-enter and ng-enter-active CSS classes on the element are removed, causing it to re-render and reposition with its default CSS code (so there is no absolute positioning once the animation is over). This movement is very smooth, so the page flows naturally as the route changes without any beat.

The applied CSS class (start and end classes) ng-repeat E ach time a new page is loaded ng-view instruction, a copy of itself is created, the template is downloaded, and the content is appended. This ensures that all views are contained in a separate HTML element that allows for simple animation control.

To learn more about CSS animations, see the web platform documentation.

Use JavaScript to get ngClass moving

Let's add another animation to the application. S witching to phone-detail.html we see that there is already a great thumbnail exchanger. B y clicking on the thumbnail in the page column, the profile phone image changes. But how can we add animations while changing it?

Let's think about it first. B asically, when you click on an infographic, you're changing the state of the image to reflect the newly selected thumbnail. T he best way to specify a state change in HTML is to use a style class. Much like before, we use a CSS style class to specify an animation that occurs when the CSS class itself changes.

When a new phone thumbnail is elected, the status changes, .active CSS class is added to the matching profile image and the animation is played.

Let's get phone-detail.html HTML code on the phone-.html on the web. Note that we've changed the way large images are displayed:

app/partials/phone-detail.html .

<!-- We're only changing the top of the file -->
<div class="phone-images">
  <img ng-src="{{img}}"
       class="phone"
       ng-repeat="img in phone.images"
       ng-class="{active:mainImageUrl==img}">
</div>

<h1>{{phone.name}}</h1>

<p>{{phone.description}}</p>

<ul class="phone-thumbs">
  <li ng-repeat="img in phone.images">
    <img ng-src="{{img}}" ng-mouseenter="setImage(img)">
  </li>
</ul>

Like thumbnails, we use iterators to display all the data images as a list, but we haven't changed any iteration-related animations. I nstead, ng-class active class becomes true, it is applied to the element and rendered visible. O therwise, the data image is hidden. In our case, there is always an element with an active so there is always a phone profile image visible on the screen at any one time.

When an activation class is added to the element, active-add class and adtive-add-active to indicate that Angular raises an animation. When the activation class is removed from the element, active-remove active-remove-active which in turn triggers other animations.

To make sure that the phone image is displayed correctly the first time the page loads, we also fine-tune the CSS style of the detail page:

app/css/app.css

.phone-images {
  background-color: white;
  width: 450px;
  height: 450px;
  overflow: hidden;
  position: relative;
  float: left;
}

...

img.phone {
  float: left;
  margin-right: 3em;
  margin-bottom: 2em;
  background-color: white;
  padding: 2em;
  height: 400px;
  width: 400px;
  display: none;
}

img.phone:first-child {
  display: block;
  }

You might think we're going to create another CSS-available animation. While we can do that, let's seize the opportunity to learn how abnimate animations using the abnimate module approach.

app/js/animations.js .

var phonecatAnimations = angular.module('phonecatAnimations', ['ngAnimate']);

phonecatAnimations.animation('.phone', function() {

  var animateUp = function(element, className, done) {
    if(className != 'active') {
      return;
    }
    element.css({
      position: 'absolute',
      top: 500,
      left: 0,
      display: 'block'
    });

    jQuery(element).animate({
      top: 0
    }, done);

    return function(cancel) {
      if(cancel) {
        element.stop();
      }
    };
  }

  var animateDown = function(element, className, done) {
    if(className != 'active') {
      return;
    }
    element.css({
      position: 'absolute',
      left: 0,
      top: 0
    });

    jQuery(element).animate({
      top: -500
    }, done);

    return function(cancel) {
      if(cancel) {
        element.stop();
      }
    };
  }

  return {
    addClass: animateUp,
    removeClass: animateDown
  };
});

Note that we are using jQuery to implement this animation. j Query doesn't require JavaScript animations to work with Angel JS, but we'll use it because writing your own JavaScript animation library is beyond the scope of this tutorial. To learn more jQuery.animate see the jQuery documentation.

Elements that contain the classes we have registered call addClass callback function and the removeClass callback function, removeClass of whether a class is added to or .phone W hen a .active class .active to the ng-class instruction), addClass JavaScript callback function is raised with an argument element T he last argument passed in is done callback function. done of the done callback function is to let Angel know when the JavaScript animation ends by calling the function.

removeClass callback function works in the same way, but triggers a class when it is removed from an element.

In the JavaScript callback function, you create the animation by manipulating the DOM. I n the code above, this is element.css() element.animate() T he callback function 500px offset, moving the previous and 500px so that the two items move together. T his results in an animation of a replica conveyor belt. When animate function does its job, it calls done .

Note addClass removeClass return a function. T his is an optional function that is called when the animation is canceled (other animations occur on the same element) or when the animation is complete. P ass a Boolean parameter to this function that lets the developer know if the animation has been canceled. When the animation is complete, this function can be used to do some tail-sweeping work.

Summarize

Now you've learned! W e created a web application in a relatively short time. At the end of the article, we'll discuss where to go next.

Related tutorials

CSS tutorial