Guias Detalhados
Animations

Animando suas aplicações com animate.enter e animate.leave

Animações bem projetadas podem tornar sua aplicação mais divertida e simples de usar, mas elas não são apenas cosméticas. Animações podem melhorar sua aplicação e experiência do usuário de várias maneiras:

  • Sem animações, transições de páginas web podem parecer abruptas e desconfortáveis
  • Movimento melhora muito a experiência do usuário, então animações dão aos usuários a chance de detectar a resposta da aplicação às suas ações
  • Boas animações podem direcionar suavemente a atenção do usuário ao longo de um fluxo de trabalho

Angular fornece animate.enter e animate.leave para animar os elementos de sua aplicação. Esses dois recursos aplicam classes CSS de entrada e saída nos momentos apropriados ou chamam funções para aplicar animações de bibliotecas de terceiros. animate.enter e animate.leave não são directives. Eles são APIs especiais suportadas diretamente pelo compilador Angular. Eles podem ser usados em elementos diretamente e também podem ser usados como um host binding.

animate.enter

Você pode usar animate.enter para animar elementos à medida que eles entram no DOM. Você pode definir animações de entrada usando classes CSS com transitions ou animações de keyframe.

enter.ts

import {Component, signal} from '@angular/core';@Component({  selector: 'app-enter',  templateUrl: 'enter.html',  styleUrls: ['enter.css'],})export class Enter {  isShown = signal(false);  toggle() {    this.isShown.update((isShown) => !isShown);  }}

enter.html

<h2><code>animate.enter</code> Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) {  <div class="enter-container" animate.enter="enter-animation">    <p>The box is entering.</p>  </div>}

enter.css

:host {  display: block;  height: 200px;}.enter-container {  border: 1px solid #dddddd;  margin-top: 1em;  padding: 20px 20px 0px 20px;  font-weight: bold;  font-size: 20px;}.enter-animation {  animation: slide-fade 1s;}@keyframes slide-fade {  from {    opacity: 0;    transform: translateY(20px);  }  to {    opacity: 1;    transform: translateY(0);  }}

Quando a animação é concluída, Angular remove a classe ou classes que você especificou em animate.enter do DOM. Classes de animação estão presentes apenas enquanto a animação está ativa.

NOTA: Ao usar múltiplas animações de keyframe ou propriedades de transition em um elemento, Angular remove todas as classes apenas após a animação mais longa ter sido concluída.

Você pode usar animate.enter com quaisquer outros recursos do Angular, como control flow ou expressões dinâmicas. animate.enter aceita tanto uma única string de classe (com múltiplas classes separadas por espaços), quanto um array de strings de classe.

Uma nota rápida sobre o uso de transitions CSS: Se você escolher usar transitions em vez de animações de keyframe, as classes adicionadas ao elemento com animate.enter representam o estado para o qual a transition irá animar. Seu CSS base do elemento é como o elemento ficará quando nenhuma animação estiver rodando, que é provavelmente similar ao estado final da transition CSS. Então você ainda precisaria emparelhá-lo com @starting-style para ter um estado de origem apropriado para que sua transition funcione.

enter-binding.ts

import {Component, signal} from '@angular/core';@Component({  selector: 'app-enter-binding',  templateUrl: 'enter-binding.html',  styleUrls: ['enter-binding.css'],})export class EnterBinding {  isShown = signal(false);  toggle() {    this.isShown.update((isShown) => !isShown);  }  enterClass = signal('enter-animation');}

enter-binding.html

<h2><code>animate.enter</code> Binding Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) {  <div class="enter-container" [animate.enter]="enterClass()">    <p>The box is entering.</p>  </div>}

enter-binding.css

:host {  display: block;  height: 200px;}.enter-container {  border: 1px solid #dddddd;  margin-top: 1em;  padding: 20px 20px 0px 20px;  font-weight: bold;  font-size: 20px;}.enter-animation {  animation: slide-fade 1s;}@keyframes slide-fade {  from {    opacity: 0;    transform: translateY(20px);  }  to {    opacity: 1;    transform: translateY(0);  }}

animate.leave

Você pode usar animate.leave para animar elementos à medida que eles saem do DOM. Você pode definir animações de saída usando classes CSS com transforms ou animações de keyframe.

leave.ts

import {Component, signal} from '@angular/core';@Component({  selector: 'app-leave',  templateUrl: 'leave.html',  styleUrls: ['leave.css'],})export class Leave {  isShown = signal(false);  toggle() {    this.isShown.update((isShown) => !isShown);  }}

leave.html

<h2><code>animate.leave</code> Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) {  <div class="leave-container" animate.leave="leaving">    <p>Goodbye</p>  </div>}

leave.css

:host {  display: block;  height: 200px;}.leave-container {  border: 1px solid #dddddd;  margin-top: 1em;  padding: 20px 20px 0px 20px;  font-weight: bold;  font-size: 20px;  opacity: 1;  transition: opacity 200ms ease-in;  @starting-style {    opacity: 0;  }}.leaving {  opacity: 0;  transform: translateY(20px);  transition: opacity 500ms ease-out, transform 500ms ease-out;}

Quando a animação é concluída, Angular remove automaticamente o elemento animado do DOM.

NOTA: Ao usar múltiplas animações de keyframe ou propriedades de transition em um elemento, Angular aguarda para remover o elemento apenas após a mais longa dessas animações ter sido concluída.

animate.leave também pode ser usado com signals e outros bindings. Você pode usar animate.leave com uma única classe ou múltiplas classes. Especifique como uma string simples com espaços ou um array de strings.

leave-binding.ts

import {Component, signal} from '@angular/core';@Component({  selector: 'app-leave-binding',  templateUrl: 'leave-binding.html',  styleUrls: ['leave-binding.css'],})export class LeaveBinding {  isShown = signal(false);  toggle() {    this.isShown.update((isShown) => !isShown);  }  farewell = signal('leaving');}

leave-binding.html

<h2><code>animate.leave</code> Binding Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) {  <div class="leave-container" [animate.leave]="farewell()">    <p>Goodbye</p>  </div>}

leave-binding.css

:host {  display: block;  height: 200px;}.leave-container {  border: 1px solid #dddddd;  margin-top: 1em;  padding: 20px 20px 0px 20px;  font-weight: bold;  font-size: 20px;  opacity: 1;  transition: opacity 200ms ease-in;  @starting-style {    opacity: 0;  }}.leaving {  opacity: 0;  transform: translateY(20px);  transition: opacity 500ms ease-out, transform 500ms ease-out;}

Event Bindings, Funções e Bibliotecas de Terceiros

Tanto animate.enter quanto animate.leave suportam sintaxe de event binding que permite chamadas de função. Você pode usar essa sintaxe para chamar uma função no código do seu component ou utilizar bibliotecas de animação de terceiros, como GSAP, anime.js, ou qualquer outra biblioteca de animação 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();  }}

leave-event.html

<h2><code>animate.leave</code> Function Example</h2><button type="button" (click)="toggle()">Toggle Element</button>@if (isShown()) {  <div class="leave-container" (animate.leave)="leavingFn($event)">    <p>Goodbye</p>  </div>}

leave-event.css

:host {  display: block;  height: 200px;}.leave-container {  border: 1px solid #dddddd;  margin-top: 1em;  padding: 20px 20px 0px 20px;  font-weight: bold;  font-size: 20px;  opacity: 1;  transition: opacity 200ms ease-in;  @starting-style {    opacity: 0;  }}.leaving {  opacity: 0;  transform: translateY(20px);  transition: opacity 500ms ease-out, transform 500ms ease-out;}

O objeto $event tem o type AnimationCallbackEvent. Ele inclui o elemento como o target e fornece uma função animationComplete() para notificar o framework quando a animação termina.

IMPORTANTE: Você deve chamar a função animationComplete() ao usar animate.leave para que o Angular remova o elemento.

Se você não chamar animationComplete() ao usar animate.leave, Angular chama a função automaticamente após um delay de quatro segundos. Você pode configurar a duração do delay fornecendo o token MAX_ANIMATION_TIMEOUT em milissegundos.

  { provide: MAX_ANIMATION_TIMEOUT, useValue: 6000 }

Compatibilidade com Animações Angular Legadas

Você não pode usar animações legadas juntamente com animate.enter e animate.leave dentro do mesmo component. Fazer isso resultaria em classes de entrada permanecendo no elemento ou nós de saída não sendo removidos. Caso contrário, é perfeitamente adequado usar tanto animações legadas quanto as novas animações animate.enter e animate.leave dentro da mesma aplicação. A única ressalva é content projection. Se você está projetando conteúdo de um component com animações legadas para outro component com animate.enter ou animate.leave, ou vice-versa, isso resultará no mesmo comportamento como se fossem usados juntos no mesmo component. Isso não é suportado.

Testing

TestBed fornece suporte integrado para habilitar ou desabilitar animações no seu ambiente de teste. Animações CSS requerem um browser para rodar, e muitas das APIs não estão disponíveis em um ambiente de teste. Por padrão, TestBed desabilita animações para você em seus ambientes de teste.

Se você quiser testar que as animações estão animando em um teste de browser, por exemplo um teste end-to-end, você pode configurar o TestBed para habilitar animações especificando animationsEnabled: true na sua configuração de teste.

  TestBed.configureTestingModule({animationsEnabled: true});

Isso configurará animações no seu ambiente de teste para se comportarem normalmente.

NOTA: Alguns ambientes de teste não emitem eventos de animação como animationstart, animationend e seus equivalentes de eventos de transition.

Mais sobre animações Angular

Você também pode estar interessado no seguinte: