Слайд-анимация Angular 4

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

<div class="wrapper">
  <button (click)="animated = !animated"></button>
  <div *ngIf="animated" [@slideInOutAnimation] class="animated-div">
  THIS DIV IS ANIMATED</div>

  <div class="content">THIS IS CONTENT DIV</div>

</div>

TYPESCRIPT:
animations: [
trigger('slideInOutAnimation', [

  state('*', style({

  })),
  transition(':enter', [
    style({
      transform: 'translateY(-10%)',
      opacity: 0
    }),
    animate('.5s ease-in-out', style({
      transform: 'translateY(0)',
      opacity: 1
    }))
  ]),
  transition(':leave', [
    animate('.5s ease-in-out', style({
      transform: 'translateY(-10%)',
      opacity: 0
    }))
  ])
])
]

Должен ли я создать какой-либо другой триггер, который будет перемещать мой контент div с анимированным?

Ответ 1

Сначала создайте файл, в котором вы определяете свои анимации и экспортируете их. Чтобы сделать это более ясным в вашем app.component.ts

В следующем примере я использовал максимальную высоту div, которая идет от 0px (когда она скрыта), до 500 пикселей, но вы измените ее в соответствии с тем, что вам нужно.

Эта анимация использует состояния (в и из), которые будут переключаться, когда мы нажимаем на кнопку, которая будет запускать анимацию.

animations.ts

import { trigger, state, style, transition,
    animate, group, query, stagger, keyframes
} from '@angular/animations';

export const SlideInOutAnimation = [
    trigger('slideInOut', [
        state('in', style({
            'max-height': '500px', 'opacity': '1', 'visibility': 'visible'
        })),
        state('out', style({
            'max-height': '0px', 'opacity': '0', 'visibility': 'hidden'
        })),
        transition('in => out', [group([
            animate('400ms ease-in-out', style({
                'opacity': '0'
            })),
            animate('600ms ease-in-out', style({
                'max-height': '0px'
            })),
            animate('700ms ease-in-out', style({
                'visibility': 'hidden'
            }))
        ]
        )]),
        transition('out => in', [group([
            animate('1ms ease-in-out', style({
                'visibility': 'visible'
            })),
            animate('600ms ease-in-out', style({
                'max-height': '500px'
            })),
            animate('800ms ease-in-out', style({
                'opacity': '1'
            }))
        ]
        )])
    ]),
]

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

app.component.ts

import { SlideInOutAnimation } from './animations';

@Component({
  ...
  animations: [SlideInOutAnimation]
})
export class AppComponent  {
  animationState = 'in';

  ...

  toggleShowDiv(divName: string) {
    if (divName === 'divA') {
      console.log(this.animationState);
      this.animationState = this.animationState === 'out' ? 'in' : 'out';
      console.log(this.animationState);
    }
  }
}

И вот как выглядит ваш app.component.html:

<div class="wrapper">
  <button (click)="toggleShowDiv('divA')">TOGGLE DIV</button>
  <div [@slideInOut]="animationState" style="height: 100px; background-color: red;">
  THIS DIV IS ANIMATED</div>
  <div class="content">THIS IS CONTENT DIV</div>
</div>

slideInOut относится к триггеру анимации, определенному в animations.ts

Вот пример StackBlitz, который я создал: https://stackblitz.com/edit/angular-muvaqu

Боковое примечание. Если при возникновении ошибки появляется запрос на добавление BrowserAnimationsModule, просто импортируйте его в свой app.module.ts:

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

@NgModule({
  imports: [ ..., BrowserAnimationsModule ],
  ...
})

Ответ 2

Я предпочитаю использовать подстановочный оператор при работе с переходами по высоте, чтобы обеспечить динамический контент по высоте.

// Bind to true/false states via 0 and 1 values

trigger('slideUpDown', [
  state('0', style({ 'max-height': '*', opacity: 1 })),
  state('1', style({ 'max-height': '0px', opacity: 0 })),
  transition(':enter', animate('400ms ease-in-out')),
  transition('* => *', animate('400ms ease-in-out')),
])

использование:

<div #someDiv [@slideUpDown]="someDiv.state"></div>

где-нибудь еще или в шаблоне вы можете переключать состояние.

<button (click)="someDiv.state = !someDiv.state"></button>