Heim > Web-Frontend > js-Tutorial > Angular LAB: Listen animieren und AnimationBuilder für imperative Animationen verwenden

Angular LAB: Listen animieren und AnimationBuilder für imperative Animationen verwenden

Barbara Streisand
Freigeben: 2024-10-10 06:18:29
Original
859 Leute haben es durchsucht

Angular LAB: animating lists and using AnimationBuilder for imperative animations

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.

Erstellen einer Liste

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' }]);
  }
}
Nach dem Login kopieren

Beachten Sie, dass wir eine Schaltfläche eingefügt haben, die einen Benutzer zur Liste hinzufügt!

Animieren der Liste

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(),
  ]
});
Nach dem Login kopieren

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 })
    )
  ])
])
Nach dem Login kopieren

Mit diesen Helfern:

  • Einen Animationsauslöser namens fadeIn erstellt
  • Übergang hinzugefügt, wenn das Element den Bildschirm betritt
  • Anfangsstil angewendet
  • Die Animation wurde sofort gestartet, wodurch ein neuer Stil auf das Element angewendet wird

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]
}) 
Nach dem Login kopieren

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>
Nach dem Login kopieren
// A class method in your component:
trackByUserId(index, user: User) {
  return user.id;
}
Nach dem Login kopieren

Jetzt fügen wir unserer Liste eine weitere Art von Animation hinzu.

AnimationBuilder

Fügen wir jedem Element unserer Liste eine Schaltfläche hinzu:

<li @fadeIn>
  {{ user.name }}
  <button>Make me blink</button>
</li>
Nach dem Login kopieren

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);
}
Nach dem Login kopieren

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 }))
  ]);
}
Nach dem Login kopieren

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);
}
Nach dem Login kopieren

Und jetzt stellen wir eine Methode vor, die tatsächlich die Animation startet!

export class BlinkDirective {

  ...

  start() {
    this.player.play();
  }
}
Nach dem Login kopieren

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
  ]
})
Nach dem Login kopieren

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;
}
Nach dem Login kopieren

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()
  ]
});
Nach dem Login kopieren

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!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage