From ad5256452bb8f1d481d78e7ae15a59d288f0d8e9 Mon Sep 17 00:00:00 2001 From: Brian Ford Date: Tue, 8 Oct 2013 10:43:01 -0700 Subject: feat(tutorial): add step 12 of the phonecat tutorial --- docs/content/tutorial/step_12.ngdoc | 419 ++++++++++++++++++++++++++++++++++++ docs/src/templates/js/docs.js | 2 +- 2 files changed, 420 insertions(+), 1 deletion(-) create mode 100644 docs/content/tutorial/step_12.ngdoc diff --git a/docs/content/tutorial/step_12.ngdoc b/docs/content/tutorial/step_12.ngdoc new file mode 100644 index 00000000..af6c3faa --- /dev/null +++ b/docs/content/tutorial/step_12.ngdoc @@ -0,0 +1,419 @@ +@ngdoc overview +@name Tutorial: 12 - Applying Animations +@description + +
+... + + + + + + + + + + + +... ++ +Animations can now be created within the CSS code (`animations.css`) as well as the JavaScript code (`animations.js`). +But before we start, let's create a new module which uses the ngAnimate module as a dependency just like we did before +with `ngResource`. + +## Module & Animations + +__`app/js/animations.js`.__ +
+angular.module('phonecatAnimations', ['ngAnimate']).
+ // ...
+ // this module will later be used to define animations
+ // ...
+
+
+And now let's attach this module to our application module...
+
+__`app/js/app.js`.__
+
+// ...
+angular.module('phonecat', [
+ 'ngRoute',
+
+ 'phonecatAnimations',
+ 'phonecatControllers',
+ 'phonecatFilters',
+ 'phonecatServices',
+]).
+// ...
+
+
+Now, the phonecat module is animation aware. Let's make some animations!
+
+
+## Animating ngRepeat with CSS Transition Animations
+
+We'll start off by adding CSS transition animations to our `ngRepeat` directive present on the `phone-list.html` page.
+First let's add an extra CSS class to our repeated element so that we can hook into it with our CSS animation code.
+
+__`app/partials/phone-list.html`.__
++ +
{{phone.snippet}}
+
+.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 our `phone-listing` CSS class is combined together with the animation hooks that occur when items are
+inserted info and removed from the list:
+
+ * The `ng-enter` class is applied to the element when a new phone is added to the list and rendered on the page.
+ * The `ng-move` class is applied when items are moved around in the list.
+ * The `ng-leave` class is applied when they're removed from the list.
+
+The phone listing items are added and removed depending on the data passed to the `ng-repeat` attribute.
+For example, if the filter data changes the items will be animated in and out of the repeat list.
+
+Something important to note is that when an animation occurs, two sets of CSS classes
+are added to the element:
+
+ 1. a "starting" class that represents the style at the beginning of the animation
+ 2. an "active" class that represents the style at the end of the animation
+
+The name of the starting class is the name of event that is fired (like `enter`, `move` or `leave`) prefixed with
+`ng-`. So an `enter` event will result in a class called `ng-enter`.
+
+The active class name is the same as the starting class's but with an `-active` suffix.
+This two-class CSS naming convention allows the developer to craft an animation, beginning to end.
+
+In our example above, elements expand from a height of **0** to **120 pixels** when items are added or moved,
+around and collapsing the items before removing them from the list.
+There's also a nice fade-in and fade-out effect that also occurs at the same time. All of this is handled
+by the CSS transition declarations at the top of the example code above.
+
+Although most modern browsers have good support for {@link http://caniuse.com/#feat=css-transitions CSS transitions}
+and {@link http://caniuse.com/#feat=css-animation CSS animations}, IE9 and earlier do not.
+If you want animations that are backwards-compatible with older browsers, consider using JavaScript-based animations,
+which are described in detail below.
+
+
+## Animating `ngView` with CSS Keyframe Animations
+
+Next let's add an animation for transitions between route changes in `ngView`.
+
+To start, let's add a new CSS class to our HTML like we did in the example above.
+This time, instead of the `ng-repeat` element, let's add it to the element containing the ng-view directive.
+In order to do this, we'll have to make some small changes to the HTML code so that we can have more control over our
+animations between view changes.
+
+__`app/partials/phone-list.html`.__
+++ +With this change, the `ng-view` directive is nested inside a parent element with +a `view-container` CSS class. This class adds a `position: relative` style so that the positioning of the `ng-view` +is relative to this parent as it animates transitions. + +With this in place, let's add the CSS for this transition animation to our `animations.css` file: + +__`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; }
+}
+
+/* don't forget about the vendor-prefixes! */
+
+
+Nothing crazy here! Just a simple fade in and fade out effect between pages. The only out of the ordinary thing
+here is that we're using absolute positioning to position the next page (identified via `ng-enter`) on top of the
+previous page (the one that has the `ng-leave` class) while performing a cross fade animation in between. So
+as the previous page is just about to be removed, it fades out while the new page fades in right on top of it.
+Once the leave animation is over then element is removed and once the enter animation is complete then the
+`ng-enter` and `ng-enter-active` CSS classes are removed from the element rendering it to be position itself
+with its default CSS code (so no more absolute positioning once the animation is over). This works fluidly so
+that pages flow naturally between route changes without anything jumping around.
+
+The CSS classes applied (the start and end classes) are much the same as with `ng-repeat`. Each time a new page is
+loaded the ng-view directive will create a copy of itself, download the template and append the contents. This
+ensures that all views are contained within a single HTML element which allows for easy animation control.
+
+For more on CSS animations, see the
+{@link http://docs.webplatform.org/wiki/css/properties/animations Web Platform documentation}.
+
+
+## Animating `ngClass` with JavaScript
+
+Let's add another animation to our application. Switching to our `phone-detail.html` page,
+we see that we have a nice thumbnail swapper. By clicking on the thumbnails listed on the page,
+the profile phone image changes. But how can we change this around to add animations?
+
+Lets think about it first,
+basically when you click on a thumbnail image, you're changing the state of the profile image to reflect the newly
+selected thumbnail image.
+The best way to specify state changes within HTML is to use classes.
+Much like before, how we used a CSS class to specify
+an animation, this time the animation will occur whenever the CSS class itself changes.
+
+Whenever a new phone thumbnail is selected, the state changes and the `.active` CSS class is added to the matching
+profile image and the animation plays.
+
+Let's get started and tweak our HTML code on the `phone-detail.html` page first:
+
+__`app/partials/phone-detail.html`.__
++ +++ ++
{{phone.name}}
+ +{{phone.description}}
+ +
+angular.module('phonecatAnimations', ['ngAnimate'])
+
+ .animation('.phone', function() {
+ return {
+ addClass : 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();
+ };
+ },
+ removeClass : 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();
+ };
+ }
+ };
+ });
+
+
+Note that we're using {@link http://jquery.com/ jQuery} to implement the animation. jQuery
+isn't required to do JavaScript animations with AngularJS, but we're going to use it because writing
+your own JavaScript animation library is beyond the scope of this tutorial. For more on
+`jQuery.animate`, see the {@link http://api.jquery.com/animate/ jQuery documentation}.
+
+