Анимация маршрутизатора Angular7 на выходе искажает и переставляет все элементы, создавая беспорядок

#angular #css-animations #angular7 #angular-router #angular-animations

#angular #css-анимации #angular7 #angular-маршрутизатор #angular-анимации

Вопрос:

Я опробовал около 5 реализаций анимации выхода маршрутизатора. Я просто хочу базовую анимацию постепенного включения / выключения при изменении маршрута, ничего особенного.

Вот запись экрана, показывающая, как все выглядит при переключении маршрута:https://streamable.com/tbkxt

Это, безусловно, лучший результат, который я получил, в других случаях у меня просто кнопки / текст исчезали с экрана один за другим. Я тестирую в Chrome.

У меня включена навигация sidenav, и мой код выглядит следующим образом:

 <mat-sidenav-content [@routerTransition]="getPageTransition(routerOutlet)">
      <button
        @menu-button
        *ngIf="!snav.opened"
        mat-button
        (click)="snav.toggle()"
        class="navigation-toggle"
      >
        <fa-icon icon="bars"></fa-icon>
      </button>

      <button
        @menu-button
        *ngIf="snav.opened"
        mat-button
        (click)="snav.toggle()"
        class="navigation-toggle"
      >
        <fa-icon icon="times"></fa-icon>
      </button>
      <router-outlet #routerOutlet="outlet"></router-outlet>
    </mat-sidenav-content>
  

Мои анимации определены:

 const query = (style, animate, optional = { optional: true }) =>
  q(style, animate, optional);

const fade = [
  query(':enter, :leave', style({ position: 'fixed', width: '100%' })),
  query(':enter', [style({ opacity: 0 })]),
  group([
    query(':leave', [animate('0.3s ease-out', style({ opacity: 0 }))]),
    query(':enter', [
      style({ opacity: 0 }),
      animate('0.3s ease-out', style({ opacity: 1 }))
    ])
  ])
];

export const routerTransition = trigger('routerTransition', [
  transition('void => *', [
    style({ top: '0px', opacity: 0 }),
    animate(2000, style({ top: '0px', opacity: 1 }))
  ]),
  transition('* => void', [
    style({ top: '0px', opacity: 1 }),
    animate(2000, style({ top: '0px', opacity: 0 }))
  ]),
  transition('* => forward', fade),
  transition('* => backward', fade)
]);
  

И в компоненте я проверяю выход маршрутизатора:

  getPageTransition(routerOutlet: RouterOutlet) {
    if (routerOutlet.isActivated) {
      let transitionName = 'section';

      const { path } = routerOutlet.activatedRoute.routeConfig;
      const isSame = this.previousPath === path;
      const isBackward = this.previousPath.startsWith(path);
      const isForward = path.startsWith(this.previousPath);

      if (isSame) {
        transitionName = 'none';
      } else if (isBackward amp;amp; isForward) {
        transitionName = 'initial';
      } else if (isBackward) {
        transitionName = 'backward';
      } else if (isForward) {
        transitionName = 'forward';
      }

      this.previousPath = path;

      return transitionName;
    }
  

Комментарии:

1. Привет, Себастьян, у меня также был неудачный опыт работы с анимацией маршрутизатора в прошлом. Одна всегда повторяющаяся ошибка была связана со следующим: github.com/angular/angular/issues/15477 . Есть несколько решений, и это может вам помочь. Насколько я понял, вам нужно удерживать компонент, анимируя маршрутизатор с непрозрачности 0,99999 до 1, чтобы сохранить все содержимое и, следовательно, анимацию живой, пока компонент не можно будет выбросить.

2. @JonathanStellwag спасибо — Я не на 100% уверен, что понимаю, что вы имеете в виду, анимируя маршрутизатор с 0.99999 до 1 — вы имеете в виду, что при входе я должен начинать с 0.99999 вместо 0? разве это не сохранит все это видимым? или анимировать его от 0 до 0,99999 — глядя на идею от 0,99999 до 1, он, скорее всего, просто исчезнет в мгновение ока без фактического исчезновения, но я думаю, что я неправильно понимаю. Спасибо!

3. Привет @SebastianG. Я напишу вам ответ, который, возможно, потребуется адаптировать к вашему случаю, и / или вам придется немного попробовать и ошибиться. Но код в разделе комментариев не очень приятный 🙂

Ответ №1:

Я выяснил, что события :enter и:leave, близкие к маршрутизации, могут вызвать несколько проблем с анимацией angular. Этот ответ не является тестовым для вашего случая и, возможно, нуждается в адаптации, поскольку следующий фрагмент зависит от структуры вашего приложения и вашего вложенного маршрутизатора. Я адаптирую этот ответ, если он не подходит или решит вашу проблему!

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

Следующий комментарий решил мою проблему, но мне пришлось адаптировать его для моей среды:

 let animation = [...]; // the metadata
transition('A => B', group([
  query(':self', animation),
  query('router-outlet ~ *', [style({}), animate(1, style({}))], { optional: true })
]))
  

На самом деле это означает, что вы не только анимируете свой элемент. Вы также применяете анимацию к самому маршрутизатору-выходу. Это может быть реализовано для вашего кода следующим образом:

 query('mat-sidenav-content > router-outlet ~ *', [
  style({
  opacity: .99999
}),
animate(yourAnimationDuration, style({
  opacity: 1
}))
], { optional: true });
  

Я не специалист по Css-селектору, возможно, вам потребуется адаптировать

 mat-sidenav-content > router-outlet ~ *
  

Я надеюсь, что этот ответ может вам помочь 🙂