{ "id": "guide/complex-animation-sequences", "title": "Complex animation sequences", "contents": "\n\n\n
\n mode_edit\n
\n\n\n
\n

Complex animation sequenceslink

\n

Prerequisiteslink

\n

A basic understanding of the following concepts:

\n\n
\n

So far, we've learned simple animations of single HTML elements. Angular also lets you animate coordinated sequences, such as an entire grid or list of elements as they enter and leave a page. You can choose to run multiple animations in parallel, or run discrete animations sequentially, one following another.

\n

Functions that control complex animation sequences are as follows:

\n\n\n

Animate multiple elements using query() and stagger() functionslink

\n

The query() function allows you to find inner elements within the element that is being animated. This function targets specific HTML elements within a parent component and applies animations to each element individually. Angular intelligently handles setup, teardown, and cleanup as it coordinates the elements across the page.

\n

The stagger() function allows you to define a timing gap between each queried item that is animated and thus animates elements with a delay between them.

\n

The Filter/Stagger tab in the live example shows a list of heroes with an introductory sequence. The entire list of heroes cascades in, with a slight delay from top to bottom.

\n

The following example demonstrates how to use query() and stagger() functions on the entry of an animated element.

\n\n\n animations: [\n trigger('pageAnimations', [\n transition(':enter', [\n query('.hero, form', [\n style({opacity: 0, transform: 'translateY(-100px)'}),\n stagger(-30, [\n animate('500ms cubic-bezier(0.35, 0, 0.25, 1)', style({ opacity: 1, transform: 'none' }))\n ])\n ])\n ])\n ]),\n ]\n})\nexport class HeroListPageComponent implements OnInit {\n @HostBinding('@pageAnimations')\n public animatePage = true;\n\n heroTotal = -1;\n get heroes() { return this._heroes; }\n private _heroes = [];\n\n ngOnInit() {\n this._heroes = HEROES;\n }\n\n updateCriteria(criteria: string) {\n criteria = criteria ? criteria.trim() : '';\n\n this._heroes = HEROES.filter(hero => hero.name.toLowerCase().includes(criteria.toLowerCase()));\n const newTotal = this.heroes.length;\n\n if (this.heroTotal !== newTotal) {\n this.heroTotal = newTotal;\n } else if (!criteria) {\n this.heroTotal = -1;\n }\n }\n}\n\n\n\n

Parallel animation using group() functionlink

\n

You've seen how to add a delay between each successive animation. But you may also want to configure animations that happen in parallel. For example, you may want to animate two CSS properties of the same element but use a different easing function for each one. For this, you can use the animation group() function.

\n
\n

Note: The group() function is used to group animation steps, rather than animated elements.

\n
\n

In the following example, using groups on both :enter and :leave allow for two different timing configurations. They're applied to the same element in parallel, but run independently.

\n\nanimations: [\n trigger('flyInOut', [\n state('in', style({\n width: 120,\n transform: 'translateX(0)', opacity: 1\n })),\n transition('void => *', [\n style({ width: 10, transform: 'translateX(50px)', opacity: 0 }),\n group([\n animate('0.3s 0.1s ease', style({\n transform: 'translateX(0)',\n width: 120\n })),\n animate('0.3s ease', style({\n opacity: 1\n }))\n ])\n ]),\n transition('* => void', [\n group([\n animate('0.3s ease', style({\n transform: 'translateX(50px)',\n width: 10\n })),\n animate('0.3s 0.2s ease', style({\n opacity: 0\n }))\n ])\n ])\n ])\n]\n\n\n

Sequential vs. parallel animationslink

\n

Complex animations can have many things happening at once. But what if you want to create an animation involving several animations happening one after the other? Earlier we used group() to run multiple animations all at the same time, in parallel.

\n

A second function called sequence() lets you run those same animations one after the other. Within sequence(), the animation steps consist of either style() or animate() function calls.

\n\n

Filter animation examplelink

\n

Let's take a look at another animation on the live example page. Under the Filter/Stagger tab, enter some text into the Search Heroes text box, such as Magnet or tornado.

\n

The filter works in real time as you type. Elements leave the page as you type each new letter and the filter gets progressively stricter. The heroes list gradually re-enters the page as you delete each letter in the filter box.

\n

The HTML template contains a trigger called filterAnimation.

\n\n<ul class=\"heroes\" [@filterAnimation]=\"heroTotal\">\n</ul>\n\n\n

The component file contains three transitions.

\n\n@Component({\n animations: [\n trigger('filterAnimation', [\n transition(':enter, * => 0, * => -1', []),\n transition(':increment', [\n query(':enter', [\n style({ opacity: 0, width: '0px' }),\n stagger(50, [\n animate('300ms ease-out', style({ opacity: 1, width: '*' })),\n ]),\n ], { optional: true })\n ]),\n transition(':decrement', [\n query(':leave', [\n stagger(50, [\n animate('300ms ease-out', style({ opacity: 0, width: '0px' })),\n ]),\n ])\n ]),\n ]),\n ]\n})\nexport class HeroListPageComponent implements OnInit {\n heroTotal = -1;\n}\n\n\n

The animation does the following:

\n\n

For each match:

\n\n

Animation sequence summarylink

\n

Angular functions for animating multiple elements start with query() to find inner elements, for example gathering all images within a <div>. The remaining functions, stagger(), group(), and sequence(), apply cascades or allow you to control how multiple animation steps are applied.

\n

More on Angular animationslink

\n

You may also be interested in the following:

\n\n\n \n
\n\n\n" }