Heim >Web-Frontend >js-Tutorial >Angular LAB: Listen animieren und AnimationBuilder für imperative Animationen verwenden
Wussten Sie, dass Angular ein komplexes Animationssystem enthält? Ich finde es besonders nützlich, wenn ich Elemente animieren möchte, wenn sie auf den Bildschirm gelangen oder zerstört werden!
Außerdem können Sie AnimationBuilder verwenden, um einige benutzerdefinierte Animationen zwingend abzuspielen, anzuhalten oder zu stoppen! Mal sehen, wie es gemacht wird.
In dieser Übung erstellen wir zunächst eine Liste, etwa so:
@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li>{{ user.name }}</li> } </ul> `, }) export class AppComponent { users = signal<User[]>([ { id: Math.random(), name: 'Michele' } ]); addUser() { this.users.update(users => [...users, { id: Math.random(), name: 'New user' }]); } }
Beachten Sie, dass wir eine Schaltfläche eingefügt haben, die einen Benutzer zur Liste hinzufügt!
Was ist nun, wenn wir den neuen Benutzer animieren möchten, der hinzugefügt wird? Zuerst möchten wir Angular mitteilen, dass wir sein Animationssystem verwenden möchten, indem wir es in Ihrer Hauptkonfiguration bereitstellen:
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; bootstrapApplication(AppComponent, { providers: [ provideAnimationsAsync(), ] });
Dann können wir unsere Animation erstellen:
import { trigger, transition, style, animate } from '@angular/animations'; const fadeInAnimation = trigger('fadeIn', [ transition(':enter', [ style({ transform: 'scale(0.5)', opacity: 0 }), animate( '.3s cubic-bezier(.8, -0.6, 0.2, 1.5)', style({ transform: 'scale(1)', opacity: 1 }) ) ]) ])
Mit diesen Helfern:
Weitere Informationen zum Schreiben von Animationen finden Sie im offiziellen Leitfaden, der großartig ist!
Jetzt wenden wir diese Animation auf jedes unserer Elemente in der Liste an:
@Component({ ..., template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li @fadeIn>{{ user.name }}</li> <!-- Notice here --> } </ul> `, // Also, add the animation to the metadata of the component animations: [fadeInAnimation] })
Wenn jetzt ein neues Element hinzugefügt wird, wird es animiert! Unser erster Schritt ist getan.
Beachten Sie, dass Angular jedes Element in unserem for verfolgen muss, damit unsere Animation korrekt funktioniert, da andernfalls beim Aktualisieren der Vorlage möglicherweise dieselben Elemente neu erstellt werden, was zu unerwünschten Ergebnissen führt Animationen. Dies ist mit der neuen Control Flow-Syntax kostenlos, da die track-Eigenschaft obligatorisch ist. Wenn Sie jedoch alte Angular-Versionen mit der *ngFor-Direktive verwenden, müssen Sie die trackBy-Option wie folgt verwenden:
<li *ngFor="let user of users; trackBy: trackByUserId" @fadeIn >{{ user.name }}</li>
// A class method in your component: trackByUserId(index, user: User) { return user.id; }
Jetzt fügen wir unserer Liste eine weitere Art von Animation hinzu.
Fügen wir jedem Element unserer Liste eine Schaltfläche hinzu:
<li @fadeIn> {{ user.name }} <button>Make me blink</button> </li>
Stellen Sie sich Folgendes vor: Wir möchten, dass das Element blinkt, wenn wir die Taste drücken. Das wäre cool! Hier kommt der AnimationBuilder-Dienst ins Spiel.
Erstellen wir zunächst eine Direktive, die auf jedes Element angewendet wird. In dieser Direktive injizieren wir sowohl ElementRef als auch AnimationBuilder:
import { AnimationBuilder, style, animate } from '@angular/animations'; @Directive({ selector: '[blink]', exportAs: 'blink', // <--- Notice standalone: true }) export class BlinkDirective { private animationBuilder = inject(AnimationBuilder); private el = inject(ElementRef); }
Beachten Sie, dass wir die Anweisung exportiert haben: Wir werden in ein paar Sekunden zum Grund kommen.
Dann können wir eine benutzerdefinierte Animation wie diese erstellen:
export class BlinkDirective { ... private animation = this.animationBuilder.build([ style({ transform: 'scale(1)', opacity: 1 }), animate(150, style({ transform: 'scale(1.1)', opacity: .5 })), animate(150, style({ transform: 'scale(1)', opacity: 1 })) ]); }
Wir verwenden dieselben Funktionen wie in der vorherigen Animation, nur mit unterschiedlichen Stilen.
Jetzt wollen wir einen Player erstellen, der die Animation auf unserem Element ausführt:
export class BlinkDirective { ... private player = this.animation.create(this.el.nativeElement); }
Und jetzt stellen wir eine Methode vor, die tatsächlich die Animation startet!
export class BlinkDirective { ... start() { this.player.play(); } }
Es bleibt nur noch ein Schritt: Wir müssen die Direktive importieren, sie auf unsere Elemente anwenden, sie mit einer Vorlagenvariablen abrufen und die Methode aufrufen, wenn die Schaltfläche gedrückt wird!
@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li @fadeIn blink #blinkDir="blink"> {{ user.name }} <button (click)="blinkDir.start()">Make me blink</button> </li> } </ul> `, imports: [BlinkDirective], animations: [ fadeInAnimation ] })
Wir können die Instanz der Direktive abrufen und in eine lokale Variable einfügen, da wir die Direktive zuvor mit exportAs exportiert haben. Das ist der entscheidende Teil!
Jetzt versuchen Sie, auf die Schaltfläche zu klicken: Das Element würde korrekt animiert werden!
Die Übung ist abgeschlossen, aber das ist nur die Spitze des Eisbergs! Der AnimationPlayer verfügt über zahlreiche Befehle, mit denen Sie die Animation stoppen, anhalten und fortsetzen können. Sehr cool!
interface AnimationPlayer { onDone(fn: () => void): void; onStart(fn: () => void): void; onDestroy(fn: () => void): void; init(): void; hasStarted(): boolean; play(): void; pause(): void; restart(): void; finish(): void; destroy(): void; reset(): void; setPosition(position: number): void; getPosition(): number; parentPlayer: AnimationPlayer; readonly totalTime: number; beforeDestroy?: () => any; }
Hier ist unser vollständiges Beispiel, wenn Sie damit experimentieren möchten: Fügen Sie es einfach in Ihre main.ts-Datei ein und sehen Sie es in Aktion!
import { Component, signal, Directive, ElementRef, inject } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import { trigger, transition, style, animate, AnimationBuilder } from '@angular/animations'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; interface User { id: number; name: string; } @Directive({ selector: '[blink]', exportAs: 'blink', standalone: true }) export class BlinkDirective { private animationBuilder = inject(AnimationBuilder); private el = inject(ElementRef); private animation = this.animationBuilder.build([ style({ transform: 'scale(1)', opacity: 1 }), animate(150, style({ transform: 'scale(1.1)', opacity: .5 })), animate(150, style({ transform: 'scale(1)', opacity: 1 })) ]); private player = this.animation.create(this.el.nativeElement); start() { this.player.play(); } } const fadeInAnimation = trigger('fadeIn', [ transition(':enter', [ style({ transform: 'scale(0.5)', opacity: 0 }), animate( '.3s cubic-bezier(.8, -0.6, 0.2, 1.5)', style({ transform: 'scale(1)', opacity: 1 }) ) ]) ]) @Component({ selector: 'app-root', standalone: true, template: ` <button (click)="addUser()">Add user</button> <ul> @for (user of users(); track user.id) { <li @fadeIn blink #blinkDir="blink"> {{ user.name }} <button (click)="blinkDir.start()">Make me blink</button> </li> } </ul> `, imports: [BlinkDirective], animations: [ fadeInAnimation ] }) export class App { users = signal([ { id: Math.random(), name: 'Michele' } ]); addUser() { this.users.update(users => [...users, { id: Math.random(), name: 'New user' }]); } } bootstrapApplication(App, { providers: [ provideAnimationsAsync() ] });
Das obige ist der detaillierte Inhalt vonAngular LAB: Listen animieren und AnimationBuilder für imperative Animationen verwenden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!