Five Practical Examples Of Animations In Angular
Published: 2024-04-30 14:23:54

by [Daniel Onyebuchi](https://blog.openreplay.com/authors/daniel-onyebuchi)





<blockquote><em>
[Angular](https://angular.io/docs) animations have become integral to modern web development, enriching user experiences with dynamic transitions and engaging visual effects. This article is a practical guide to mastering Angular animations, offering hands-on examples and insights into creating fluid and responsive UIs. 
</em></blockquote>






<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>





# Angular Animations: A Hands-On Guide with 5 Practical Examples
From setting up the
development environment to implement animation techniques, this guide equips developers with the knowledge and skills needed to leverage the full potential of Angular's animation capabilities.


## Setting Up the Development Environment
Initiate a new Angular project by executing this command in the terminal.
```bash  
ng new <filename>
```

Navigate to the Angular directory.
```bash
cd <filename>
```

Open the project in VS Code.
```bash
code .
```

Generate an Angular component named `toggleOver`.
```bash
ng generate component toggleOver
```

In the `main.ts` file, import the necessary Angular modules.
```typescript
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';
import { routes } from './app/app.routes';
```

Within the `bootstrapApplication` function, update the configuration to include the required providers.
```typescript
bootstrapApplication(AppComponent, {
  // Configure providers for the application
  providers: [
    provideRouter(routes),     // Provide routing functionality using defined routes
    provideAnimations()        // Provide animation support for components
  ]
})
  .catch((err) => console.error(err));
```

In the `app.routes.ts` file, import `ToggleOverComponent`.
```typescript
import { ToggleOverComponent } from './toggle-over/toggle-over.component';
```

Define an empty path for `ToggleOverComponent` to render the component in the DOM.
```typescript
export const routes: Routes = [
  { path: '', component: ToggleOverComponent },
];
```

Navigate to the `app.component.html` file and replace the existing code with the one below.
```html
<router-outlet />
```


## Two-Way Animation
Two-way animation refers to animations triggered by an event and subsequently reversed or undone when the event is reversed. A classic illustration is a toggle button that displays additional information when clicked and conceals it upon a second click. Now, let's create such a button.

Navigate to the `toggle-over.component.ts` file and import the required modules and functionalities.
```typescript
import { CommonModule } from '@angular/common';
import { trigger, state, style, animate, transition } from '@angular/animations';
```

Add `CommonModule` to the imports array within the `@Component` decorator.
```typescript
@Component({  
  imports: [CommonModule],
  // other properties
})
```

In the `ToggleOverComponent` class, initialize a property `show` with a boolean `false`, representing the initial state where the `toggleOver` is hidden. This property serves as a flag indicating whether the `toggleOver` is visible (`true`) or hidden (`false`).

Implement a getter function named `presentState`. This function returns `show` if it's `true`; otherwise, it returns `hide`.

Define a method called `popOver`, which switches the value of the `show` property between `true` and `false`, effectively toggling the visibility of the `toggleOver` component.
```typescript
export class ToggleOverComponent {
  // Boolean flag to track whether the component is shown or hidden
  show = false;

  // Getter method to determine the current state ('show' or 'hide') based on the 'show' flag
  get presentState() {
    return this.show ? 'show' : 'hide';
  }

  // Method to toggle the visibility of the component
  popOver() {
    this.show = !this.show; // Toggle the value of 'show' to show or hide the component
  }
}
```

In the `@Component` decorator, specify an `animation` property that accepts an array. Within this array, include a `trigger` named `toggleOverState`. This trigger consists of definitions encapsulated in an object, which comprises an array of `state()` and `transition()` declarations.

Within the `state()` declaration, define `styles` corresponding to the element's state. The element should be visible with an opacity of 1 when in the `show` state and hidden with an opacity of 0 when in the `hide` state.

To enable animation, include a transition that sets the duration and easing for the animation. The duration can be specified in either seconds or milliseconds as a string.
```typescript
@Component({
  // Other properties
    
  animations: [
    // Define animation trigger named 'toggleOverState'
    trigger('toggleOverState', [
      // Define state 'show' with opacity 1 (fully visible)
      state('show', style({
        opacity: 1
      })),
      // Define state 'hide' with opacity 0 (fully transparent)
      state('hide', style({
        opacity: 0
      })),
      // Define transition from 'show' to 'hide' with a specified duration and easing
      transition('show => hide', animate('0.6s ease-out')),
      // Define transition from 'hide' to 'show' with a specified duration and easing
      transition('hide => show', animate('1s ease-out'))
    ])
  ]
})
```

In the `toggle-over.component.html` file, we define a `<div>` element and apply an animation by prefixing its name `toggleOverState` with the `@` symbol and passing the current state as `presentState`. 

Additionally, we include a button to toggle the visibility of the variable, linking it to a `popOver` method through a click event.
```html
<div [@toggleOverState]="presentState">
  <p>
    <img
      src="https://www.finsmes.com/wp-content/uploads/2022/06/openreplay.png"
    />
  </p>
  <p>OpenReplay logo toggle</p>
</div>
<button (click)="popOver()">Toggle Popover</button>
```

Here's a preview of the toggle animation. When the button is clicked, it reveals the OpenReplay log and accompanying text and hides the information when clicked again.
![two way](https://blog.openreplay.com/images/five-practical-examples-of-animations-in-angular/images/image1.gif)


## Multistate Animation
These animations involve transitioning between multiple states or configurations of an element over time. These animations can include changes in position, rotation, scale, opacity, and other visual properties.

### Implementing translate, rotate, and scale animations
Generate a new component using the command line interface by running the code below.
```bash
ng generate component gallery-images
```

In the `gallery-images.component.ts` file, import all required modules and functionalities.
```typescript
import { animate, state, style, transition, trigger } from '@angular/animations';
import { CommonModule } from '@angular/common';
```

Include `CommonModule` in the `imports` array within the `@Component` decorator.
```typescript
@Component({  
  imports: [CommonModule],
  // other properties
})
```

In the `app.routes.ts` file, define an empty path for the `GalleryImagesComponent`.
```typescript
export const routes: Routes = [
  { path: '', component: GalleryImagesComponent },
];
```

In the `gallery-images.component.ts` file, we set up the `animation` property within the `@Component` decorator. This property expects an array containing a trigger that encompasses all animations. The `trigger` requires two parameters: the animation's name, `imgState`, and an array defining the animation states and transitions.
```typescript
@Component({    
    
  // other properties
    
  animations: [
    trigger('imgState', []),
  ]
})
```
Define three states in the array: `move`, `enlarge`, and `spin`, each corresponding to translate, scale, and rotate operations, respectively. Utilize the' transform' property to assign distinct styles to each state. 

For instance, the `move` state will employ `translateX(-100%)`, shifting the element leftwards by its width. In the `enlarge` state, the element is scaled up by a factor of 1.5, while in the `spin` state, rotation occurs along the Y and Z axes.

Establish a `transition` function specifying the animation behavior during state shifts to facilitate smooth transitions between these states. Utilize the wildcard `' * => * '` to account for all 16 possible state combinations. This wildcard ensures uniform animation across transitions, with the first `*` representing any initial state and the second `*` representing any final state.
```typescript
@Component({
  //other properties 
    
  animations: [
    trigger('imgState', [
      state('move', style({
        transform: 'translateX(-100%)',
      })),
      state('enlarge', style({
        transform: 'scale(1.5)',
      })),
      state('spin', style({
        transform: 'rotateY(180deg) rotateZ(90deg)',
      })),
      transition('* => *', animate('2s ease-out')),
    ])
  ],
})
```

In the `GalleryImagesComponent` class, create a property named `orientation` of type `string` and initialize it with `'null'`. 

Define a property named `photoUrl` initialized with a URL pointing to an image file. 

Implement a method named `changeOrientation` that accepts a `newOrientation` parameter of type `string`. Upon invocation, this method updates the `orientation` property with the provided `newOrientation` value.
```typescript
export class GalleryImagesComponent {
  // A property to store the orientation
  orientation: string = 'null';

  // A property to store the URL of the photo
  photoUrl = 'https://www.finsmes.com/wp-content/uploads/2022/06/openreplay.png';

  // <Method to change the orientation
  changeOrientation(newOrientation: string) {
    this.orientation = newOrientation;
  }
}
```

Open the `gallery-images.component.html` file and add an `img` element. Use Angular animation binding to implement animation effects on the image, driven by the `orientation` variable in the component.

Additionally, create four `buttons` with click events that trigger the `changeOrientation()` method. Pass the arguments `move`, `enlarge`, `spin`, and `null` respectively to this method. These arguments correspond to the state names in the animation array.
```html
<div class="photo-gallery">
  <img [src]="photoUrl" [@imgState]="orientation" class="photo" />

  <div class="button-container">
    <button (click)="changeOrientation('move')">Translate</button>
    <button (click)="changeOrientation('spin')">Rotate</button>
    <button (click)="changeOrientation('enlarge')">Scale</button>
    <button (click)="changeOrientation('null')">Reset</button>
  </div>
</div>
```

Preview of multistate animations involving translation, rotation, scaling, and resetting an image's orientation.
![multi (1) (1)](https://blog.openreplay.com/images/five-practical-examples-of-animations-in-angular/images/image2.gif)



<CTA_Middle_Frameworks />




## Keyframe Animation
This allows you to specify a sequence of styles at various points in time (`keyframes`) and apply them to an element using Angular's animation triggers.

### Implementing Keyframe Animations in Angular
Import the `keyframes` function from `@angular/animations` within the `gallery-images.component.ts` file.
```typescript    
import { animate, state, style, transition, trigger, keyframes } from '@angular/animations';
```

Modify the transition in the `trigger` array by adding `keyframes` as the second parameter.
```typescript    
animations: [
  trigger('photoState', [
      
    // previous animation states    
      
    transition('* => *', animate('2000ms', keyframes([]))),
  ])
]
```

In `keyframes`, create an array of `styles`, each style with a `transform` property that describes the movement of the element at specific times denoted by `offset`.

`Offset: 0` occurs at the beginning of the animation (0% progress).

`Offset: 0.33` occurs approximately one-third of the way through the animation (33% progress).

`Offset: 0.66` occurs approximately two-thirds of the way through the animation (66% progress).

`Offset: 1.0` occurs at the end of the animation (100% progress).
```typescript
keyframes([
  style({ transform: 'translateX(0) rotateY(0)', offset: 0 }),
  style({ transform: 'translateX(50%) rotateY(90deg)', offset: 0.33 }),
  style({ transform: 'translateY(-75%) rotateY(180deg)', offset: 0.66 }),
  style({ transform: 'translateX(-100%)', offset: 1.0 }),
]);
```

Preview of the image moving at different positions in time swiftly.
![keyframe (1)](https://blog.openreplay.com/images/five-practical-examples-of-animations-in-angular/images/image3.gif)


## Animation Callbacks
Animation callbacks in Angular provide a way to execute code at specific points during the lifecycle of an animation. These callbacks allow for greater control and customization of animations,  performing actions such as starting, completing, or canceling animations and reacting to animation events.

### Using animation start and end callbacks
Import the `AnimationEvent` function from `@angular/animations` in the `gallery-images.component.ts` file.
```typescript
import { animate, state, style, transition, trigger, keyframes, AnimationEvent } from '@angular/animations';
```

Create a method called `logAnimation`, which accepts an `AnimationEvent` object. The `AnimationEvent` is an Angular-specific class that represents an event occurring during an animation, such as when the animation starts, ends, or is canceled.

Inside the `logAnimation` method, log details about the animation to the console. This information comprises the animation's current position or state (`this.orientation`) and the phase of the animation event (`event.phaseName`), which could be `start`, `done`, or `void`.
```typescript
export class GalleryImagesComponent {
  // previous code from keyframes animation goes here

  logAnimation(event: AnimationEvent) {
    console.log(`${this.orientation} animation ${event.phaseName}`);
  }
}
```

In the `gallery-images.component.html` file, modify the `img` element by adding an event listener for animation initiation and completion triggered by the `imgState` animation `trigger`.
```html
<img
  [src]="photoUrl"
  [@imgState]="orientation"
  (@imgState.start)="logAnimation($event)"
  (@imgState.done)="logAnimation($event)"
/>
```

Here's a snapshot from the console log displaying the animation event, indicating both the start and completion of the animation.
![callback](https://blog.openreplay.com/images/five-practical-examples-of-animations-in-angular/images/image4.png)

## List Animation
In Angular, animation can be applied to a list using the `query` functionality, which selects nested elements within an animation based on their HTML tag. Additionally, the `stagger` function can introduce a delay between each animation of the elements, resulting in a shutter-like effect.

To utilize these features, import the `query` and `stagger` functionalities from `@angular/animations` in the `gallery-images.component.ts` file.
```typescript
import { animate, style, transition, trigger, query, stagger } from '@angular/animations';
```

In `@Component` decorator, include an `animation` property. Within the `transition` array, specify a `query` property with two parameters: the `HTML` tag name and the animation `style` that moves each image 100% to the right. 

Additionally, incorporate another `query` parameter to apply staggered animations to the `<img>` elements, introducing a delay between the start of each element's animation.
```typescript
@Component({
  //other properties go here
    
  animations: [
    trigger('imgAnimation', [
      transition('* => *', [
        query('img', style({ transform: 'translateX(100%)' })),
        query('img', stagger('1000ms', [
          animate('1500ms', style({ transform: 'translateX(0)' }))
        ]))
      ])
    ])
  ]
})
```

In the `GalleryImagesComponent` class, declare an array containing URLs of images, serving as the data source for our application.
```typescript
export class GalleryImagesComponent {
  images: string[] = [
    'https://img.freepik.com/free-vector/adorable-wideeyed-kitten-illustration_1308-162844.jpg?q=10&h=200',
    'https://img.freepik.com/free-photo/portrait-lion-ai-generated_268835-4278.jpg',
    'https://img.freepik.com/free-photo/eurasian-wolf-white-winter-habitat-beautiful-winter-forest_475641-702.jpg?size=626&ext=jpg&ga=GA1.1.735520172.1711411200&semt=ais'
  ];
}
```

In the `gallery-images.component.html` file, use the `*ngFor` directive to iterate through the images array, generating a `<div>` element for each image.
```html
<div [@imgAnimation]="images.length">
  <div *ngFor="let image of images">
    <img [src]="image" width="200px" alt="" />
  </div>
</div>
```

Here's a preview of the animation: each image slides in from the right with a staggered effect, and a delay is introduced between each image's animation.
![list (1)](https://blog.openreplay.com/images/five-practical-examples-of-animations-in-angular/images/image5.gif)

## Conclusion
Mastering Angular animations opens up a world of possibilities for developers to create captivating and dynamic user interfaces. Throughout this hands-on guide, we've explored various animation techniques, from simple toggle animations to more complex multistate animations and keyframe animations. By following the practical examples and insights provided in this article, developers can leverage Angular's animation capabilities to enrich user experiences, whether it's through fluid transitions, engaging visual effects, or interactive list animations. 

## Additional Resource
[Angular Animation Guide](https://angular.io/guide/animations)