Angular анимация перед маршрутизацией

В моем текущем проекте я пытаюсь избавиться от пропуска анимации Angular при маршрутизации. В моем шаблоне у меня есть разные «виджеты» с mat-card в макете css-сетки, которые я хочу, чтобы они появлялись и исчезали плавно.

Мои анимации в дочернем компоненте (на который указывает маршрут) выглядят как

animations: [
  trigger('cardAnimation', [
    state('void', style({ opacity: 0, transform: 'scale(0.5)' })),
    state('*', style({ opacity: 1, transform: 'scale(1)' })),
    transition('void => *', animate('500ms ease-in')),
    transition('* => void', animate('500ms ease-in'))
  ])
]

Упрощенный шаблон выглядит так

<mat-card @cardAnimation>
</mat-card>

<mat-card @cardAnimation>
</mat-card>

Карточки отображаются с анимацией, но при переходе к следующему маршруту происходит переход к следующему маршруту, не дожидаясь анимации. Я также тестировал использование animateChild() внутри query внутри перехода, но это не помогает. Как заставить роутер их ждать?

Спасибо и ура!


person Felix Lemke    schedule 09.08.2018    source источник


Ответы (1)


При изменении маршрута компонент разрушается и больше не может быть анимирован. Если вы хотите оживить компонент до того, как он будет уничтожен, вы можете использовать CanDeactivate охранник, который гарантирует, что компонент может быть деактивирован перед его уничтожением.

Вот пример реализации:

export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
  canDeactivate(component: CanComponentDeactivate) {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}

Затем в объявлении модуля маршрута:

RouterModule.forChild([
      { path: '', component: HelloComponent,
  canDeactivate: [CanDeactivateGuard] }
])

После этого вы можете использовать ngOnInit и canDeactivate для воспроизведения анимации начала и конца:

ngOnInit() {
  this.animation = this._builder.build(this.slideIn(this.ANIMATION_TIME));
  this.player = this.animation.create(this.el.nativeElement, {});
  this.player.play();
}

canDeactivate() {
  this.animation = this._builder.build(this.slideOut(this.ANIMATION_TIME));
  this.player = this.animation.create(this.el.nativeElement, {});
  this.player.play();
  return timer(this.ANIMATION_TIME).pipe(mapTo(true)).toPromise();
}

Вот рабочий пример этого предлагаемого решения.

Чтобы упростить использование, я создал абстрактный компонент, который обрабатывает анимацию, чтобы добавить поведение анимации к любому компоненту, просто расширив абстрактный компонент.

person ibenjelloun    schedule 10.08.2018
comment
@Jago исправлен, пример был старым и соответствовал старому дереву проекта angular. - person ibenjelloun; 30.11.2019