>  기사  >  웹 프론트엔드  >  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();
  }
}

한 단계만 남았습니다. 지시문을 가져와서 요소에 적용한 다음 템플릿 변수로 가져오고 버튼을 눌렀을 때 메서드를 호출해야 합니다!

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

이전에 importAs를 사용하여 지시문을 내보냈기 때문에 지시문의 인스턴스를 가져와 로컬 변수에 넣을 수 있습니다. 그게 핵심이에요!

이제 버튼을 클릭해 보세요. 요소가 올바르게 애니메이션될 것입니다!

운동은 끝났지만 이는 빙산의 일각에 불과합니다! 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.