Анимация приложений с animate.enter и animate.leave
Хорошо продуманные анимации делают приложение понятнее и привлекательнее — и это не только косметика.
Анимации улучшают приложение и пользовательский опыт несколькими способами:
Без анимаций переходы на веб-странице могут казаться резкими и неприятными
Движение сильно улучшает UX, поэтому анимации дают пользователям шанс заметить реакцию приложения на их действия
Хорошие анимации плавно направляют внимание пользователя по всему workflow
Angular предоставляет animate.enter и animate.leave для анимации элементов приложения. Эти две возможности в нужный момент применяют enter- и leave-CSS-классы или вызывают функции для анимаций из сторонних библиотек. animate.enter и animate.leave — не директивы. Это специальный API, поддерживаемый напрямую компилятором Angular. Их можно использовать прямо на элементах, а также как host binding.
Когда анимация завершается, Angular удаляет из DOM класс или классы, указанные в animate.enter. Классы анимации присутствуют только пока анимация активна.
ПРИМЕЧАНИЕ: При нескольких keyframe-анимациях или transition-свойствах на элементе Angular удаляет все классы только после завершения самой длинной анимации.
animate.enter можно использовать с любыми другими возможностями Angular — control flow, динамическими выражениями и т.д. animate.enter принимает как одну строку классов (несколько классов через пробел), так и массив строк классов.
Кратко о CSS transitions: если вы выбираете transitions вместо keyframe-анимаций, классы, добавленные к элементу через animate.enter, представляют состояние, к которому будет анимироваться transition. Базовый CSS элемента — это то, как элемент выглядит без анимаций, что обычно похоже на конечное состояние CSS transition. Поэтому его всё равно нужно сочетать с @starting-style, чтобы у transition было корректное состояние from.
Когда анимация завершается, Angular автоматически удаляет анимированный элемент из DOM.
ПРИМЕЧАНИЕ: При нескольких keyframe-анимациях или transition-свойствах на элементе Angular ждёт удаления элемента только после завершения самой длинной из этих анимаций.
animate.leave также можно использовать с сигналами и другими привязками. Можно указать один класс или несколько — простой строкой с пробелами или массивом строк.
В том, как запускаются анимации animate.leave и когда анимация произойдёт, есть нюансы. animate.leave работает, если размещён на удаляемом элементе; если animate.leave размещён на элементе, который является потомком удаляемого, дочерние анимации произойдут до удаления родительского узла из DOM. Так можно уверенно анимировать уход дочерних элементов, не давая родителю исчезнуть раньше времени.
<h2><code>animate.leave</code> Parent Sub-tree Animation Example</h2><button type="button" class="toggle-btn" (click)="toggle()">Toggle Element</button>@if (isShown()) { <div class="leave-parent"> <!-- the child node with `animate.leave` will animate first before the parent node is removed from the DOM. --> <div class="leave-container" animate.leave="leaving"> <p>Goodbye</p> </div> </div>}
И animate.enter, и animate.leave поддерживают синтаксис привязки событий с вызовами функций. Так можно вызвать функцию в коде компонента или использовать сторонние библиотеки анимаций — GSAP, anime.js или любую другую JavaScript-библиотеку анимаций.
leave-event.ts
import {AnimationCallbackEvent, Component, signal} from '@angular/core';@Component({ selector: 'app-leave-binding', templateUrl: 'leave-event.html', styleUrls: ['leave-event.css'],})export class LeaveEvent { isShown =signal(false); toggle() { this.isShown.update((isShown) => !isShown); } leavingFn(event:AnimationCallbackEvent) { // Example of calling GSAP // gsap.to(event.target, { // duration: 1, // x: 100, // // arrow functions are handy for concise callbacks // onComplete: () => event.animationComplete() // }); event.animationComplete(); }}
Объект $event имеет тип AnimationCallbackEvent. Он включает элемент как target и предоставляет функцию animationComplete(), чтобы уведомить фреймворк о завершении анимации.
ВАЖНО: При использовании animate.leave вы должны вызвать animationComplete(), чтобы Angular удалил элемент.
Если при animate.leave не вызвать animationComplete(), Angular вызовет функцию автоматически через четыре секунды. Длительность задержки можно настроить, предоставив токен MAX_ANIMATION_TIMEOUT в миллисекундах.
Нельзя использовать legacy-анимации вместе с animate.enter и animate.leave в одном компоненте. Это приведёт к тому, что enter-классы останутся на элементе или уходящие узлы не будут удалены. В остальном можно использовать и legacy-анимации, и новые animate.enter / animate.leave в одном приложении. Единственная оговорка — проекция контента. Если проецировать контент из компонента с legacy-анимациями в компонент с animate.enter или animate.leave (или наоборот), поведение будет таким же, как при совместном использовании в одном компоненте. Это не поддерживается.
TestBed предоставляет встроенную поддержку включения и отключения анимаций в тестовом окружении. CSS-анимации требуют браузера, и многие API в тестовом окружении недоступны. По умолчанию TestBed отключает анимации в тестах.
Если нужно проверить, что анимации работают в браузерном тесте (например, end-to-end), можно настроить TestBed на включение анимаций, указав animationsEnabled: true в конфигурации теста.