Animations in Angular

Home » Tutorials » JavaScript » Animations in Angular
In this video, we’ll explore how to use animations in Angular. Since Angular now recommends using native CSS animations, we’ll cover CSS transitions, transforms, and animations.

Angular has its own package, @angular/animations, which is based on the Web Animations API. However, it has been deprecated since Angular 20. That’s why Angular now recommends using native CSS animations instead.

app.ts

import {
  Component,
  computed,
  inject,
  Injector,
  linkedSignal,
  OnInit,
  Signal,
  signal,
  WritableSignal,
} from '@angular/core';
import { MatToolbar } from '@angular/material/toolbar';
import { UsersService } from './features/users/services/users-service';
import { UserDto } from './core/models/User';
import { AsyncPipe, JsonPipe } from '@angular/common';
import { toSignal } from '@angular/core/rxjs-interop';
import { UserCard } from './user-card/user-card';
import { MatButton } from '@angular/material/button';

@Component({
  selector: 'app-root',
  imports: [MatToolbar, JsonPipe, UserCard, MatButton],
  templateUrl: './app.html',
  styleUrl: './app.scss',
})
export class App implements OnInit {
  protected title = 'angular-material-app';

  protected myAge: WritableSignal<number> = signal(35);

  protected personalInfo: Signal<string> = computed(() => `My age is ${this.myAge()}`);

  private userService = inject(UsersService);

  shippingOptions = signal<any[]>([
    { id: 0, name: 'Ground' },
    { id: 1, name: 'Air' },
    { id: 2, name: 'Sea' },
  ]);
  selectedOption = linkedSignal<any[], any>({
    // `selectedOption` is set to the `computation` result whenever this `source` changes.
    source: this.shippingOptions,
    computation: (newOptions, previous) => {
      // If the newOptions contain the previously selected option, preserve that selection.
      // Otherwise, default to the first option.
      console.log(newOptions, previous);
      return newOptions.find((opt) => opt.id === previous?.value.id) ?? newOptions[0];
    },
  });
  protected users: Signal<UserDto[]> = signal([]);
  private injector = inject(Injector);

  protected showNotice: WritableSignal<boolean> = signal<boolean>(false);

  public ngOnInit() {
    this.users = toSignal(this.userService.getUsers(), {
      initialValue: [],
      injector: this.injector,
    });
  }

  protected changeData() {
    // this.myAge.set(36);
    this.myAge.update((age) => age + 1);

    this.selectedOption.set({ id: 1, name: 'Pidgin' });
  }

  protected toggleNotice() {
    this.showNotice.update((show) => !show);
  }
}

app.html

<header>
  <mat-toolbar color="primary">
    <span>My App</span>
  </mat-toolbar>
</header>

<!--<img src="https://placecats.com/300/300" alt="Angular logo" />-->

<button (click)="toggleNotice()" mat-raised-button color="tertiary">Click me</button>


@if(showNotice()) {
  <div class="notice">
    Notice text
  </div>
}

@if(showNotice()) {
  <div class="greeting" animate.enter="greeting-in" animate.leave="greeting-out">Greeting</div>
}

app.scss

// transitons
// animations


img {
  transition: all 0.3s ease-in-out;
  //transition-property: all;
  //transition-duration: .7s;
  //transition-timing-function: ease-in-out;
}

img:hover {
  //transition-property: all;
  //transition-duration: .3s;
  //transition-timing-function: ease-in-out;
  //transition-delay: 2s;
  border-radius: 50%;
  transform: rotate(360deg) scale(0.5);
}

.notice {
  border: 1px solid red;
  height: 100px;
  animation: notice .5s ease-in-out;
  // animation-name: notice;
  // animation-duration: .5s;
  // animation-timing-function: ease-in-out;
  // animation-delay: 2s;
  // animation-iteration-count: 3;
  // animation-direction: alternate;
  // animation-fill-mode: forwards;
  // animation-play-state: running;
}

@keyframes notice {
  0% {
    height: 0;
  }

  100% {
    height: 100px;
  }
}

// 1  2
// 4  3


.greeting {
  background: green;
  color: red;
  transition: all .5s ease-in-out;

  &-in {
    opacity: .5;
  }

  &-out {
    opacity: 1;
  }
}

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.

Pin It on Pinterest

Share This