Rumah  >  Artikel  >  hujung hadapan web  >  Angular LAB: menyenaraikan animasi dan menggunakan AnimationBuilder untuk animasi imperatif

Angular LAB: menyenaraikan animasi dan menggunakan AnimationBuilder untuk animasi imperatif

Barbara Streisand
Barbara Streisandasal
2024-10-10 06:18:29780semak imbas

Angular LAB: animating lists and using AnimationBuilder for imperative animations

Tahukah anda bahawa Angular termasuk sistem animasi yang kompleks? Saya mendapati ia amat berguna apabila saya ingin menghidupkan elemen apabila ia memasuki skrin atau apabila ia dimusnahkan!

Selain itu, anda boleh menggunakan AnimationBuilder untuk memainkan, menjeda atau menghentikan beberapa animasi tersuai secara mustahak! Mari lihat bagaimana ia dilakukan.

Mencipta senarai

Dalam latihan ini kita mulakan dengan mencipta senarai, seperti ini:

@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' }]);
  }
}

Perhatikan bahawa kami telah menyertakan butang yang menambahkan pengguna pada senarai!

Menghidupkan senarai

Sekarang, bagaimana jika kita mahu menghidupkan pengguna baharu yang akan ditambah? Pertama, kami ingin memberitahu Angular bahawa kami ingin menggunakan sistem animasinya dengan menyediakannya dalam konfigurasi utama anda:

import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';

bootstrapApplication(AppComponent, {
  providers: [
    provideAnimationsAsync(),
  ]
});

Kemudian, kami boleh mencipta animasi kami:

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 })
    )
  ])
])

Dengan pembantu ini kami:

  • Mencipta pencetus animasi yang dipanggil fadeIn
  • Menambahkan peralihan apabila elemen memasuki skrin
  • Menggunakan gaya awal
  • Segera memulakan animasi yang akan menghasilkan gaya baharu yang digunakan pada elemen

Untuk mendapatkan maklumat lanjut tentang cara menulis animasi, anda boleh merujuk kepada panduan rasmi yang hebat!

Sekarang mari gunakan animasi ini pada setiap elemen kami dalam senarai:

@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]
}) 

Kini, apabila item baharu ditambahkan, ia akan dianimasikan! Langkah pertama kami telah selesai.

Perhatikan bahawa agar animasi kami berfungsi dengan betul, Angular perlu menjejaki setiap elemen dalam untuk kami, kerana jika tidak, ia mungkin akan mencipta semula elemen yang sama apabila mengemas kini templat, mengakibatkan yang tidak diingini animasi. Ini datang secara percuma dengan sintaks Aliran Kawalan baharu kerana sifat trek adalah wajib, tetapi jika anda menggunakan versi lama Angular dengan arahan *ngFor, anda mesti menggunakan pilihan trackBy seperti ini:

<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;
}

Sekarang, mari tambah satu lagi jenis animasi pada senarai kami.

Pembina Animasi

Mari tambahkan butang pada setiap elemen senarai kami:

<li @fadeIn>
  {{ user.name }}
  <button>Make me blink</button>
</li>

Bayangkan ini: kita mahu membuat elemen berkelip apabila kita menekan butang. Itu pasti keren! Di sinilah perkhidmatan AnimationBuilder masuk.

Pertama, mari buat Arahan yang akan digunakan pada setiap elemen. Dalam arahan ini, kami akan menyuntik kedua-dua ElementRef dan 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);
}

Perhatikan bahawa kami mengeksport arahan: kami akan mengetahui sebabnya dalam beberapa saat.

Kemudian, kita boleh mencipta animasi tersuai seperti ini:

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 }))
  ]);
}

Kami menggunakan fungsi yang sama yang kami gunakan dalam animasi sebelumnya, hanya dengan gaya yang berbeza.

Sekarang kami ingin mencipta pemain yang akan melaksanakan animasi pada elemen kami:

export class BlinkDirective {

  ...

  private player = this.animation.create(this.el.nativeElement);
}

Dan sekarang mari kita dedahkan kaedah yang sebenarnya akan memulakan animasi!

export class BlinkDirective {

  ...

  start() {
    this.player.play();
  }
}

Hanya ada satu langkah lagi: kita mesti mengimport arahan, gunakannya pada elemen kita, ambil dengan pembolehubah templat dan panggil kaedah apabila butang ditekan!

@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
  ]
})

Kami boleh mengambil contoh arahan dan meletakkannya dalam pembolehubah tempatan kerana kami sebelum ini mengeksport arahan dengan exportAs. Itulah bahagian penting!

Sekarang, cuba klik pada butang: elemen yang akan dianimasikan dengan betul!

Senaman sudah selesai, tetapi ini hanyalah puncak gunung ais! AnimationPlayer mempunyai banyak arahan yang boleh anda gunakan untuk menghentikan, menjeda dan menyambung semula animasi. Sangat keren!

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;
}

Inilah contoh penuh kami jika anda mahu bermain dengannya: cuma masukkannya ke dalam fail main.ts anda dan lihat ia beraksi!

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()
  ]
});

Atas ialah kandungan terperinci Angular LAB: menyenaraikan animasi dan menggunakan AnimationBuilder untuk animasi imperatif. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn