| <a href='http://github.com/angular/angular.js/edit/master/docs/content/guide/animations.ngdoc' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit"> </i>Improve this doc</a> |
| |
| |
| <h1 id="animations">Animations</h1> |
| <p>AngularJS 1.2 provides animation hooks for common directives such as <code>ngRepeat</code>, <code>ngSwitch</code>, and <code>ngView</code>, as well as custom directives |
| via the <code>$animate</code> service. These animation hooks are set in place to trigger animations during the life cycle of various directives and when |
| triggered, will attempt to perform a CSS Transition, CSS Keyframe Animation or a JavaScript callback Animation (depending on if an animation is |
| placed on the given directive). Animations can be placed using vanilla CSS by following the naming conventions set in place by AngularJS |
| or with JavaScript code when it's defined as a factory.</p> |
| <p>Animations are not available unless you include the <a href="api/ngAnimate"><code>ngAnimate</code> module</a> as a dependency within your application.</p> |
| <p>Below is a quick example of animations being enabled for <code>ngShow</code> and <code>ngHide</code>:</p> |
| <p> |
| |
| <div> |
| <a ng-href="http://plnkr.co/edit/ngdoc:example-example73@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank"> |
| <i class="glyphicon glyphicon-edit"> </i> |
| Edit in Plunker</a> |
| <div class="runnable-example" |
| path="examples/example-example73" |
| module="ngAnimate" |
| deps="angular-animate.js" |
| animations="true"> |
| |
| |
| <div class="runnable-example-file" |
| name="index.html" |
| language="html" |
| type="html"> |
| <pre><code><div ng-init="checked=true"> <label> <input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible... </label> <div class="check-element sample-show-hide" ng-show="checked" style="clear:both;"> Visible... </div> </div></code></pre> |
| </div> |
| |
| <div class="runnable-example-file" |
| name="animations.css" |
| language="css" |
| type="css"> |
| <pre><code>.sample-show-hide { padding:10px; border:1px solid black; background:white; } .sample-show-hide.ng-hide-add, .sample-show-hide.ng-hide-remove { -webkit-transition:all linear 0.5s; -moz-transition:all linear 0.5s; -o-transition:all linear 0.5s; transition:all linear 0.5s; display:block!important; } .sample-show-hide.ng-hide-add.ng-hide-add-active, .sample-show-hide.ng-hide-remove { opacity:0; } .sample-show-hide.ng-hide-add, .sample-show-hide.ng-hide-remove.ng-hide-remove-active { opacity:1; }</code></pre> |
| </div> |
| |
| |
| <iframe class="runnable-example-frame" src="examples/example-example73/index.html" name="example-example73"></iframe> |
| </div> |
| </div> |
| |
| </p> |
| <h2 id="installation">Installation</h2> |
| <p>See the <a href="api/ngAnimate">API docs for <code>ngAnimate</code></a> for instructions on installing the module.</p> |
| <p>You may also want to setup a separate CSS file for defining CSS-based animations.</p> |
| <h2 id="how-they-work">How they work</h2> |
| <p>Animations in AngularJS are completely based on CSS classes. As long as you have a CSS class attached to a HTML element within |
| your website, you can apply animations to it. Lets say for example that we have an HTML template with a repeater in it like so:</p> |
| <pre><code class="lang-html"><div ng-repeat="item in items" class="repeated-item"> |
| {{ item.id }} |
| </div></code></pre> |
| <p>As you can see, the <code>.repeated-item</code> class is present on the element that will be repeated and this class will be |
| used as a reference within our application's CSS and/or JavaScript animation code to tell AngularJS to perform an animation.</p> |
| <p>As ngRepeat does its thing, each time a new item is added into the list, ngRepeat will add |
| a <code>ng-enter</code> class name to the element that is being added. When removed it will apply a <code>ng-leave</code> class name and when moved around |
| it will apply a <code>ng-move</code> class name.</p> |
| <p>Taking a look at the following CSS code, we can see some transition and keyframe animation code set for each of those events that |
| occur when ngRepeat triggers them:</p> |
| <pre><code class="lang-css">/* |
| We're using CSS transitions for when |
| the enter and move events are triggered |
| for the element that has the .repeated-item |
| class |
| */ |
| .repeated-item.ng-enter, .repeated-item.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; |
| opacity:0; |
| } |
| |
| /* |
| The ng-enter-active and ng-move-active |
| are where the transition destination properties |
| are set so that the animation knows what to |
| animate. |
| */ |
| .repeated-item.ng-enter.ng-enter-active, |
| .repeated-item.ng-move.ng-move-active { |
| opacity:1; |
| } |
| |
| /* |
| We're using CSS keyframe animations for when |
| the leave event is triggered for the element |
| that has the .repeated-item class |
| */ |
| .repeated-item.ng-leave { |
| -webkit-animation:0.5s my_animation; |
| -moz-animation:0.5s my_animation; |
| -o-animation:0.5s my_animation; |
| animation:0.5s my_animation; |
| } |
| |
| @keyframes my_animation { |
| from { opacity:1; } |
| to { opacity:0; } |
| } |
| |
| /* |
| Unfortunately each browser vendor requires |
| its own definition of keyframe animation code... |
| */ |
| @-webkit-keyframes my_animation { |
| from { opacity:1; } |
| to { opacity:0; } |
| } |
| |
| @-moz-keyframes my_animation { |
| from { opacity:1; } |
| to { opacity:0; } |
| } |
| |
| @-o-keyframes my_animation { |
| from { opacity:1; } |
| to { opacity:0; } |
| }</code></pre> |
| <p>The same approach to animation can be used using JavaScript code (<strong>jQuery is used within to perform animations</strong>):</p> |
| <pre><code class="lang-js">myModule.animation('.repeated-item', function() { |
| return { |
| enter : function(element, done) { |
| element.css('opacity',0); |
| jQuery(element).animate({ |
| opacity: 1 |
| }, done); |
| |
| // optional onDone or onCancel callback |
| // function to handle any post-animation |
| // cleanup operations |
| return function(isCancelled) { |
| if(isCancelled) { |
| jQuery(element).stop(); |
| } |
| } |
| }, |
| leave : function(element, done) { |
| element.css('opacity', 1); |
| jQuery(element).animate({ |
| opacity: 0 |
| }, done); |
| |
| // optional onDone or onCancel callback |
| // function to handle any post-animation |
| // cleanup operations |
| return function(isCancelled) { |
| if(isCancelled) { |
| jQuery(element).stop(); |
| } |
| } |
| }, |
| move : function(element, done) { |
| element.css('opacity', 0); |
| jQuery(element).animate({ |
| opacity: 1 |
| }, done); |
| |
| // optional onDone or onCancel callback |
| // function to handle any post-animation |
| // cleanup operations |
| return function(isCancelled) { |
| if(isCancelled) { |
| jQuery(element).stop(); |
| } |
| } |
| }, |
| |
| // you can also capture these animation events |
| addClass : function(element, className, done) {}, |
| removeClass : function(element, className, done) {} |
| } |
| });</code></pre> |
| <p>With these generated CSS class names present on the element at the time, AngularJS automatically |
| figures out whether to perform a CSS and/or JavaScript animation. If both CSS and JavaScript animation |
| code is present, and match the CSS class name on the element, then AngularJS will run both animations at the same time.</p> |
| <h2 id="class-and-ngclass-animation-hooks">Class and ngClass animation hooks</h2> |
| <p>AngularJS also pays attention to CSS class changes on elements by triggering the <strong>add</strong> and <strong>remove</strong> hooks. |
| This means that if a CSS class is added to or removed from an element then an animation can be executed in between |
| before the CSS class addition or removal is finalized. (Keep in mind that AngularJS will only be |
| able to capture class changes if an <strong>expression</strong> or the <strong>ng-class</strong> directive is used on the element.)</p> |
| <p>The example below shows how to perform animations during class changes:</p> |
| <p> |
| |
| <div> |
| <a ng-href="http://plnkr.co/edit/ngdoc:example-example74@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank"> |
| <i class="glyphicon glyphicon-edit"> </i> |
| Edit in Plunker</a> |
| <div class="runnable-example" |
| path="examples/example-example74" |
| module="ngAnimate" |
| deps="angular-animate.js" |
| animations="true"> |
| |
| |
| <div class="runnable-example-file" |
| name="index.html" |
| language="html" |
| type="html"> |
| <pre><code><p> <input type="button" value="set" ng-click="myCssVar='css-class'"> <input type="button" value="clear" ng-click="myCssVar=''"> <br> <span ng-class="myCssVar">CSS-Animated Text</span> </p></code></pre> |
| </div> |
| |
| <div class="runnable-example-file" |
| name="style.css" |
| language="css" |
| type="css"> |
| <pre><code>.css-class-add, .css-class-remove { -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; } .css-class, .css-class-add.css-class-add-active { color: red; font-size:3em; } .css-class-remove.css-class-remove-active { font-size:1.0em; color:black; }</code></pre> |
| </div> |
| |
| |
| <iframe class="runnable-example-frame" src="examples/example-example74/index.html" name="example-example74"></iframe> |
| </div> |
| </div> |
| |
| </p> |
| <p>Although the CSS is a little different then what we saw before, the idea is the same.</p> |
| <h2 id="which-directives-support-animations-">Which directives support animations?</h2> |
| <p>A handful of common AngularJS directives support and trigger animation hooks whenever any major event occurs during its life cycle. |
| The table below explains in detail which animation events are triggered</p> |
| <table> |
| <thead> |
| <tr> |
| <th>Directive</th> |
| <th>Supported Animations</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td><a href="api/ng/directive/ngRepeat#usage_animations">ngRepeat</a></td> |
| <td>enter, leave, and move</td> |
| </tr> |
| <tr> |
| <td><a href="api/ngRoute/directive/ngView#usage_animations">ngView</a></td> |
| <td>enter and leave</td> |
| </tr> |
| <tr> |
| <td><a href="api/ng/directive/ngInclude#usage_animations">ngInclude</a></td> |
| <td>enter and leave</td> |
| </tr> |
| <tr> |
| <td><a href="api/ng/directive/ngSwitch#usage_animations">ngSwitch</a></td> |
| <td>enter and leave</td> |
| </tr> |
| <tr> |
| <td><a href="api/ng/directive/ngIf#usage_animations">ngIf</a></td> |
| <td>enter and leave</td> |
| </tr> |
| <tr> |
| <td><a href="api/ng/directive/ngClass#usage_animations">ngClass or {{class}}</a></td> |
| <td>add and remove</td> |
| </tr> |
| <tr> |
| <td><a href="api/ng/directive/ngShow#usage_animations">ngShow & ngHide</a></td> |
| <td>add and remove (the ng-hide class value)</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>For a full breakdown of the steps involved during each animation event, refer to the <a href="api/ngAnimate/service/$animate">API docs</a>.</p> |
| <h2 id="how-do-i-use-animations-in-my-own-directives-">How do I use animations in my own directives?</h2> |
| <p>Animations within custom directives can also be established by injecting <code>$animate</code> directly into your directive and |
| making calls to it when needed.</p> |
| <pre><code class="lang-js">myModule.directive('my-directive', ['$animate', function($animate) { |
| return function(element, scope, attrs) { |
| element.bind('click', function() { |
| if(element.hasClass('clicked')) { |
| $animate.removeClass(element, 'clicked'); |
| } else { |
| $animate.addClass(element, 'clicked'); |
| } |
| }); |
| }; |
| }]);</code></pre> |
| <h2 id="more-about-animations">More about animations</h2> |
| <p>For a full breakdown of each method available on <code>$animate</code>, see the <a href="api/ngAnimate/service/$animate">API documentation</a>.</p> |
| <p>To see a complete demo, see the <a href="tutorial/step_12">animation step within the AngularJS phonecat tutorial</a>.</p> |
| |
| |