|
6 | 6 |
|
7 | 7 | # Animations
|
8 | 8 |
|
9 |
| -AngularJS 1.3 provides animation hooks for common directives such as `ngRepeat`, `ngSwitch`, and `ngView`, as well as custom directives |
| 9 | +AngularJS provides animation hooks for common directives such as `ngRepeat`, `ngSwitch`, and `ngView`, as well as custom directives |
10 | 10 | via the `$animate` service. These animation hooks are set in place to trigger animations during the life cycle of various directives and when
|
11 | 11 | triggered, will attempt to perform a CSS Transition, CSS Keyframe Animation or a JavaScript callback Animation (depending on if an animation is
|
12 | 12 | placed on the given directive). Animations can be placed using vanilla CSS by following the naming conventions set in place by AngularJS
|
@@ -274,6 +274,100 @@ myModule.directive('my-directive', ['$animate', function($animate) {
|
274 | 274 | }]);
|
275 | 275 | ```
|
276 | 276 |
|
| 277 | +## Animations on app bootstrap / page load |
| 278 | + |
| 279 | +By default, animations are disabled when the Angular app {@link guide/bootstrap bootstraps}. If you are using the {@link ngApp} directive, |
| 280 | +this happens in the `DOMContentLoaded` event, so immediately after the page has been loaded. |
| 281 | +Animations are disabled, so that UI and content are instantly visible. Otherwise, with many animations on |
| 282 | +the page, the loading process may become too visually overwhelming, and the performance may suffer. |
| 283 | + |
| 284 | +Internally, `ngAnimate` waits until all template downloads that are started right after bootstrap have finished. |
| 285 | +Then, it waits for the currently running {@link ng.$rootScope.Scope#$digest} and the one after that to finish. |
| 286 | +This ensures that the whole app has been compiled fully before animations are attempted. |
| 287 | + |
| 288 | +If you do want your animations to play when the app bootstraps, you can enable animations globally in |
| 289 | +your main module's {@link angular.Module#run run} function: |
| 290 | + |
| 291 | +```js |
| 292 | +myModule.run(function($animate) { |
| 293 | + $animate.enabled(true); |
| 294 | +}); |
| 295 | +``` |
| 296 | + |
| 297 | +## How to (selectively) enable, disable and skip animations |
| 298 | + |
| 299 | +There are three different ways to disable animations, both globally and for specific animations. |
| 300 | +Disabling specific animations can help to speed up the render performance, for example for large `ngRepeat` |
| 301 | +lists that don't actually have animations. Because ngAnimate checks at runtime if animations are present, |
| 302 | +performance will take a hit even if an element has no animation. |
| 303 | + |
| 304 | +### In the config: {@link $animateProvider#classNameFilter $animateProvider.classNameFilter()} |
| 305 | + |
| 306 | +This function can be called in the {@link angular.Module#config config} phase of an app. It takes a regex as the only argument, |
| 307 | +which will then be matched against the classes of any element that is about to be animated. The regex |
| 308 | +allows a lot of flexibility - you can either allow animations only for specific classes (useful when |
| 309 | +you are working with 3rd party animations), or exclude specific classes from getting animated. |
| 310 | + |
| 311 | +```js |
| 312 | +app.cofig($animateProvider) { |
| 313 | + $animateProvider.classNameFilter(/animate-/); |
| 314 | +}); |
| 315 | +``` |
| 316 | + |
| 317 | +```css |
| 318 | +/* prefixed with animate- */ |
| 319 | +.animate-fade-add.animate-fade-add-active { |
| 320 | + transition:1s linear all; |
| 321 | + opacity:0; |
| 322 | +} |
| 323 | +``` |
| 324 | + |
| 325 | +The classNameFilter approach generally applies the biggest speed boost, because the matching is |
| 326 | +done before any other animation disabling strategies are checked. However, that also means it is not |
| 327 | +possible to override class name matching with the two following strategies. It's of course still possible |
| 328 | +to enable / disable animations by changing an element's class name at runtime. |
| 329 | + |
| 330 | +### At runtime: {@link ng.$animate#enabled $animate.enabled()} |
| 331 | + |
| 332 | +This function can be used to enable / disable animations in two different ways: |
| 333 | + |
| 334 | +With a single `boolean` argument, it enables / disables animations globally: `$animate.enabled(false)` |
| 335 | +disables all animations in your app. |
| 336 | + |
| 337 | +When the second argument is a native DOM or jQuery element, the function enables / disables |
| 338 | +animations on this element *and all its children*: `$animate.enabled(false, myElement)`. This is the |
| 339 | +most flexible way to change the animation state. For example, even if you have used it to disable |
| 340 | +animations on a parent element, you can still re-enable it for a child element. And compared to the |
| 341 | +`classNameFilter`, you can change the animation status at runtime instead of during the config phase. |
| 342 | + |
| 343 | +Note however that the `$animate.enabled()` state for individual elements does not overwrite disabling |
| 344 | +rules that have been set in the {@link $animateProvider#classNameFilter classNameFilter}. |
| 345 | + |
| 346 | +### Via CSS styles: overwriting styles in the `ng-animate` CSS class |
| 347 | +Whenever an animation is started, ngAnimate applies the `ng-animate` class to the element for the |
| 348 | +whole duration of the animation. By applying CSS transition / animation styling to the class, |
| 349 | +you can skip an animation: |
| 350 | + |
| 351 | +```css |
| 352 | + |
| 353 | +.my-class{ |
| 354 | + transition: transform 2s; |
| 355 | +} |
| 356 | + |
| 357 | +.my-class:hover { |
| 358 | + transform: translateX(50px); |
| 359 | +} |
| 360 | + |
| 361 | +my-class.ng-animate { |
| 362 | + transition: 0s; |
| 363 | +} |
| 364 | + |
| 365 | +``` |
| 366 | + |
| 367 | +By setting `transition: 0s`, ngAnimate will ignore the existing transition styles, and not try to animate them (Javascript |
| 368 | +animations will still execute, though). This can be used to prevent {@link guide/animations#preventing-collisions-with-existing-animations-and-third-party-libraries |
| 369 | +issues with existing animations interfering with ngAnimate}. |
| 370 | + |
277 | 371 | ## Preventing flicker before an animation starts
|
278 | 372 |
|
279 | 373 | When nesting elements with structural animations such as `ngIf` into elements that have class-based
|
@@ -305,6 +399,47 @@ In that case, you can add styles to the CSS that make sure the element stays hid
|
305 | 399 | /* Other animation styles ... */
|
306 | 400 | ```
|
307 | 401 |
|
| 402 | +## Preventing Collisions with Existing Animations and Third Party Libraries |
| 403 | +By default, any `ngAnimate` enabled directives will assume any transition / animation styles on the |
| 404 | +element are part of an `ngAnimate` animation. This can lead to problems when the styles are actually |
| 405 | +for animations that are independent of `ngAnimate`. |
| 406 | + |
| 407 | +For example, an element acts as a loading spinner. It has an inifinite css animation on it, and also an |
| 408 | +{@link ngIf `ngIf`} directive, for which no animations are defined: |
| 409 | + |
| 410 | +```css |
| 411 | +@keyframes rotating { |
| 412 | + from { transform: rotate(0deg); } |
| 413 | + to { transform: rotate(360deg); } |
| 414 | +} |
| 415 | + |
| 416 | +.spinner { |
| 417 | + animation: rotating 2s linear infinite; |
| 418 | +} |
| 419 | +``` |
| 420 | + |
| 421 | +Now, when the `ngIf` changes, `ngAnimate` will see the spinner animation and use |
| 422 | +it to animate the `enter`/`leave` event, which doesn't work because |
| 423 | +the animation is infinite. The element will still be added / removed after a timeout, but there will be a |
| 424 | +noticable delay. |
| 425 | + |
| 426 | +This might also happen because some third-party frameworks place animation duration defaults |
| 427 | +across many element or className selectors in order to make their code small and reuseable. |
| 428 | + |
| 429 | +You can prevent this unwanted behavior by adding CSS to the `.ng-animate` class that is added |
| 430 | +for the whole duration of an animation. Simply overwrite the transition / animation duration. In the |
| 431 | +case of the spinner, this would be: |
| 432 | + |
| 433 | +.spinner.ng-animate { |
| 434 | + transition: 0s none; |
| 435 | + animation: 0s none; |
| 436 | +} |
| 437 | + |
| 438 | +If you do have CSS transitions / animations defined for the animation events, make sure they have higher priority |
| 439 | +than any styles that are independent from ngAnimate. |
| 440 | + |
| 441 | +You can also use one of the two other {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations strategies to disable animations}. |
| 442 | + |
308 | 443 | ## More about animations
|
309 | 444 |
|
310 | 445 | For a full breakdown of each method available on `$animate`, see the {@link ng.$animate API documentation}.
|
|
0 commit comments