Animacje odgrywają ważną rolę w obszarze user experience. Nie tylko usprawniają warstwę wizualną, ale posiadają także praktyczne zastosowania. Są one dość powszechne, więc każdy Angular Developer powinien być z nimi zaznajomiony.
W artykule wyjaśnię jak programistycznie kontrolować animacje w celu usprawnienia doświadczeń użytkownika.
Jaki jest cel korzystania z animacji?
Wiele firm wykorzystuje animacje aby wspomóc użytkownika w poruszaniu się po aplikacji, ułatwić proces przekazywania informacji oraz wyjaśnić proste procesy użytkownikowi.
Do najczęstszych przykładów wykorzystania animacji można zaliczyć hover oraz click. Oprócz zmiany kursora w pointera, dodanie animacji hover do klikalnych elementów jest szybką metodą zakomunikowania użytkownikowi, że dany element jest klikalny. Z drugiej strony, animacja kliknięcia (np. efekt ripple na buttonach Angular Materiala) zapewnia użytkownikowi natychmiastową informację o tym, że aplikacja zarejestrowała wykonaną przez niego akcję.
Jak dodać animację do aplikacji angularowej?
Jest wiele sposobów na to, aby dodać animację do aplikacji, łącznie z wbudowanym modułem animacji, który może być wykorzystany bez konieczności instalowania dodatkowych zależności.
Animacje w angularze są zazwyczaj używane z wykorzystaniem tablicy animations
w dekoratorze Component
. Animacje te są następnie uruchamiane są poprzez zastosowanie dyrektyw animacji (z prefiksem @
, takie jak @slideIn
czy @fadeOut
) na docelowym elemencie.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
```typescript import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { trigger, style, animate, transition } from '@angular/animations'; @Component({ standalone: true, imports: [CommonModule], selector: 'app-root, template: ` <div class="card-container"> <div *ngIf="cardIsDisplayed" @fadeSlideInOut class="demo-card"></div> </div> `, animations: [ trigger('fadeSlideInOut', [ transition(':enter', [ style({ opacity: 0, transform: 'translateY(10px)' }), animate('500ms', style({ opacity: 1, transform: 'translateY(0)' })), ]), transition(':leave', [ animate('500ms', style({ opacity: 0, transform: 'translateY(10px)' })), ]), ]), ], }) export class AppComponent { cardIsDisplayed = true; toggleCard(): void { this.cardIsDisplayed = !this.cardIsDisplayed; } } ``` |
To podejście pokrywa większość przypadków użycia oraz jest wygodnym sposobem na dodanie animacji do twojej aplikacji angularowej.
Jak edytować animacje w aplikacji angularowej?
Angular Animations zawiera klasę AnimationBuilder
, dzięki której można tworzyć animacje programistycznie.
Oprócz podstawowych funkcji Angular Animations, zaprogramowane animacje za pośrednictwem AnimationPlayer
zawierają dodatkowe funkcje do kontrolowania animacji, które nie są możliwe przy użyciu podejścia szablonowego. Funkcje te obejmują:
pause
– wstrzymuje animacjefinish
– kończy animacjerestart
– wznawia wstrzymaną animacjędestroy
– niszczy animacjereset
– resetuje animacje do stanu pierwotnego
Klasa AnimationPlayer
także dostarcza callbacki dla kluczowych eventów animacji, takich jak:
onStart
– wywołana podczas startu animacjionDone
– wywołana przy zakończeniu animacji (automatycznie bądź przez wywołanie funkcjifinish
na uruchomionej aplikacji)onDestroy
– wywołana po zniszczeniu animacji (kiedy wywoływana jest funkcjadestroy
)
Możesz również przekazać callback do funkcji beforeDestroy
jeżeli chcesz wykonać kod przed zniszczeniem animacji.
Podstawowe wykorzystanie
Spójrzmy na to, jak możemy wykorzystać AnimationBuilder
oraz AnimationPlayer
w celu uruchomienia animacji.
Zacznijmy od stworzenia docelowego elementu oraz kilku przycisków do kontrolowania animacji.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
```html <!-- app.component.html –> <div class="animation-demo-container"> <div class="card-container"> <div #demoCard class="demo-card"></div> </div> <div class="demo-controller-container"> <button class="demo-button" (click)="playAnimation()">Play</button> <button class="demo-button" (click)="pauseAnimation()">Pause</button> <button class="demo-button" (click)="stopAnimation()">Stop</button> <button class="demo-button" (click)="resetAnimation()">Reset</button> </div> </div> ``` |
Dodajmy kilka styli do naszego komponentu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
```scss // app.component.scss .animation-demo-container { border-radius: 0.5rem; border-width: 1px; border-color: rgb(14 116 144); background-color: rgb(30 41 59); display: flex; flex-direction: column; min-height: 350px; overflow: auto; .card-container { flex-grow: 1; padding: 1.25rem; .demo-card { width: 10rem; height: 10rem; border-radius: 0.5rem; background-color: rgb(125 211 252); } } .demo-controller-container { display: flex; flex-direction: row; padding: 1rem 1.25rem; border-radius: 0 0 0.5rem 0.5rem; gap: 0.75rem; .demo-button { background-color: rgb(255, 255, 255); color: rgb(15 23 42); border-radius: 0.25rem; padding: 0.5rem 0.75rem; font-weight: 500; } } } ``` |
Przejdźmy teraz do animacji. Najpierw będziemy musieli uzyskać referencję do animowanego elementu. W tym celu użyjemy dekoratora ViewChild
i przekażemy identyfikator elementu (#demoCard
), który zdefiniowaliśmy wcześniej, aby uzyskać do niego dostęp.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
```typescript // app.component.ts import { Component, ElementRef, ViewChild } from '@angular/core'; import { CommonModule } from '@angular/common'; @Component({ standalone: true, imports: [CommonModule], selector: 'app-root', templateUrl: './app.component.html', styleUrls: [‘./app.component.scss’] }) export class AppComponent { @ViewChild('demoCard') demoCard: ElementRef | undefined; } ``` |
Dodaj klasę AnimationBuilder
i utwórz prywatną funkcję, aby zbudować animację i utworzyć instancję AnimationPlayer
, której będziemy używać do uruchamiania naszych animacji.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
```typescript // app.component.ts import { Component, ElementRef, ViewChild, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { style, animate, AnimationBuilder, AnimationPlayer } from '@angular/animations'; @Component({ standalone: true, imports: [CommonModule], selector: 'app-root, templateUrl: './app.component.html', styleUrls: [‘./app.component.scss’] }) export class AppComponent { @ViewChild('demoCard') demoCard: ElementRef | undefined; private animationBuilder = inject(AnimationBuilder); private animationPlayer: AnimationPlayer | undefined; private getAnimationPlayer(): AnimationPlayer | undefined { if (!this.demoCard?.nativeElement) { return; } if (!this.animationPlayer) { const factory = this.animationBuilder.build( [ style({ transform: 'rotate(0deg)' }), animate('1000ms cubic-bezier(0.175, 0.885, 0.32, 1.275)', style({ transform: 'rotate(360deg)' })) ] ); this.animationPlayer = factory.create(this.demoCard.nativeElement); } return this.animationPlayer; } } ``` |
Na koniec stwórzmy funkcje play, stop, pause i reset. Funkcje te będa pobierać AnimationPlayer
poprzez wywołanie getAnimationPlayer()
, a następnie będą wykonywać odpowiednie metody.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
```typescript // app.component.ts import { Component, ElementRef, ViewChild, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { style, animate, AnimationBuilder, AnimationPlayer } from '@angular/animations'; @Component({ standalone: true, imports: [CommonModule], selector: 'app-root, templateUrl: './app.component.html', styleUrls: [‘./app.component.scss’] }) export class AppComponent { @ViewChild('demoCard') demoCard: ElementRef | undefined; private animationBuilder = inject(AnimationBuilder); private animationPlayer: AnimationPlayer | undefined; playAnimation(): void { const player = this.getAnimationPlayer(); if (!player) { return; } player.play(); } pauseAnimation(): void { const player = this.getAnimationPlayer(); if (!player || !player.hasStarted) { return; } player.pause(); } stopAnimation(): void { const player = this.getAnimationPlayer(); if (!player || !player.hasStarted) { return; } player.finish(); } resetAnimation(): void { const player = this.getAnimationPlayer(); if (!player || !player.hasStarted) { return; } player.reset(); } private getAnimationPlayer(): AnimationPlayer | undefined { if (!this.demoCard?.nativeElement) { return; } if (!this.animationPlayer) { const factory = this.animationBuilder.build( [ style({ transform: 'rotate(0deg)' }), animate('1000ms cubic-bezier(0.175, 0.885, 0.32, 1.275)', style({ transform: 'rotate(360deg)' })) ] ); this.animationPlayer = factory.create(this.demoCard.nativeElement); } return this.animationPlayer; } } ``` |
Jeżeli postępowałeś zgodnie z instrukcjami, powinieneś uzyskać następujące animacje:
Możesz odwiedzić Angular Animations Explorer aby zobaczyć live demo.
Podsumowując
Istnieje wiele sposobów na korzystanie z Angular Animations, z których każdy ma swoje idealne przypadki użycia. Jeżeli chcesz jedynie wywołać animacje, wybierz prostsze podejście szablonowe. Jeśli jednak potrzebujesz bardziej szczegółowej kontroli, użyj podejścia programistycznego, używając AnimationBuilder
oraz AnimationPlayer
. Możesz również sprawdzić Angular Animations Explorer, aby zobaczyć inne podejścia do dodawania animacji w Angularze.
Jeżeli interesują cie takie treści lub masz jakieś pytania, zostaw komentarz bądź skontaktuj się ze mną na Twitterze @williamjuan27.
Dodaj komentarz