ホームページ  >  記事  >  ウェブフロントエンド  >  Angular LAB: リストのアニメーション化と命令型アニメーション用のAnimationBuilderの使用

Angular LAB: リストのアニメーション化と命令型アニメーション用のAnimationBuilderの使用

Barbara Streisand
Barbara Streisandオリジナル
2024-10-10 06:18:29811ブラウズ

Angular LAB: animating lists and using AnimationBuilder for imperative animations

Angular には複雑なアニメーション システムが含まれていることをご存知ですか?要素が画面に入ったとき、または要素が破壊されたときにアニメーション化したい場合に特に便利です!

また、AnimationBuilder を使用して、一部のカスタム アニメーションを強制的に再生、一時停止、または停止することもできます。それがどのように行われるかを見てみましょう。

リストの作成

この演習では、次のようなリストを作成することから始めます:

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

リストにユーザーを追加するボタンが含まれていることに注意してください!

リストのアニメーション化

では、追加される新しいユーザーをアニメーション化したい場合はどうすればよいでしょうか?まず、メイン設定でアニメーション システムを提供することで、Angular にアニメーション システムを使用したいことを伝えます。

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

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

次に、アニメーションを作成します。

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

これらのヘルパーを使用して、次のことを行います。

  • fadeIn というアニメーション トリガーを作成しました
  • 要素が画面に入ったときのトランジションを追加しました
  • 初期スタイルを適用しました
  • アニメーションがすぐに開始され、要素に新しいスタイルが適用されます

アニメーションの書き方の詳細については、素晴らしい公式ガイドを参照してください。

次に、このアニメーションをリスト内の各要素に適用しましょう:

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

新しいアイテムが追加されると、アニメーションが表示されます。最初のステップは完了しました。

アニメーションが正しく動作するためには、Angular for 内の各要素を追跡する必要があることに注意してください。そうしないと、テンプレートの更新時に同じ要素が再作成されてしまい、望ましくない結果が生じる可能性があるためです。アニメーション。新しい制御フロー構文では、track プロパティが必須であるため、これは無料で提供されますが、*ngFor ディレクティブで古いバージョンの Angular を使用している場合は、次のように trackBy オプションを使用する必要があります。

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

次に、別のタイプのアニメーションをリストに追加しましょう。

アニメーションビルダー

リストの各要素にボタンを追加しましょう:

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

これを想像してください。ボタンを押したときに要素を点滅させたいと考えています。それはいいですね!ここで、AnimationBuilder サービスが登場します。

まず、すべての要素に適用されるディレクティブを作成しましょう。このディレクティブでは、ElementRef と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);
}

ディレクティブをエクスポートしたことに注目してください。理由は数秒でわかります。

次に、次のようなカスタム アニメーションを作成できます:

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

スタイルが異なるだけで、前のアニメーションで使用したのと同じ関数を使用しています。

次に、要素でアニメーションを実行する プレーヤー を作成します。

export class BlinkDirective {

  ...

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

それでは、実際にアニメーションを開始するメソッドを公開しましょう!

export class BlinkDirective {

  ...

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

残っているステップは 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
  ]
})

以前にexportAsを使用してディレクティブをエクスポートしたため、ディレクティブのインスタンスを取得してローカル変数に入れることができます。それが重要な部分です!

それでは、ボタンをクリックしてみてください。要素は正しくアニメーション化されるはずです!

演習は完了しましたが、これは氷山の一角にすぎません。 AnimationPlayer には、アニメーションを停止、一時停止、再開するために使用できるコマンドが多数あります。とてもクールです!

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

実際に試してみたい場合は、完全な例を次に示します。main.ts ファイルに入れて、実際の動作を確認してください。

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

以上がAngular LAB: リストのアニメーション化と命令型アニメーション用のAnimationBuilderの使用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。