Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 4fed66d

Browse files
committed
docs(guide/animation): add info on various topics
- how to enable / disable animations Closes #8812 - how to handle conflicts with existing animations Closes #8033 Closes #11820 - what happens on boostrap / how to enable animations on bootstrap
1 parent 7de7059 commit 4fed66d

File tree

2 files changed

+136
-26
lines changed

2 files changed

+136
-26
lines changed

docs/content/guide/animations.ngdoc

+136-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# Animations
88

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
1010
via the `$animate` service. These animation hooks are set in place to trigger animations during the life cycle of various directives and when
1111
triggered, will attempt to perform a CSS Transition, CSS Keyframe Animation or a JavaScript callback Animation (depending on if an animation is
1212
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) {
274274
}]);
275275
```
276276

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+
277371
## Preventing flicker before an animation starts
278372

279373
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
305399
/* Other animation styles ... */
306400
```
307401

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+
308443
## More about animations
309444

310445
For a full breakdown of each method available on `$animate`, see the {@link ng.$animate API documentation}.

src/ngAnimate/module.js

-25
Original file line numberDiff line numberDiff line change
@@ -699,31 +699,6 @@
699699
* possible be sure to visit the {@link ng.$animate $animate service API page}.
700700
*
701701
*
702-
* ### Preventing Collisions With Third Party Libraries
703-
*
704-
* Some third-party frameworks place animation duration defaults across many element or className
705-
* selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which
706-
* is expecting actual animations on these elements and has to wait for their completion.
707-
*
708-
* You can prevent this unwanted behavior by using a prefix on all your animation classes:
709-
*
710-
* ```css
711-
* /* prefixed with animate- */
712-
* .animate-fade-add.animate-fade-add-active {
713-
* transition:1s linear all;
714-
* opacity:0;
715-
* }
716-
* ```
717-
*
718-
* You then configure `$animate` to enforce this prefix:
719-
*
720-
* ```js
721-
* $animateProvider.classNameFilter(/animate-/);
722-
* ```
723-
*
724-
* This also may provide your application with a speed boost since only specific elements containing CSS class prefix
725-
* will be evaluated for animation when any DOM changes occur in the application.
726-
*
727702
* ## Callbacks and Promises
728703
*
729704
* When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger

0 commit comments

Comments
 (0)