Angular (4, 5, 6, 7) - простой пример слайд-анимации на ngIf

Каков минимум и родной способ Angular4 вставлять и выдвигать элемент контейнера?

например

<div ngIf="show">
    <!-- Content -->
</div>

Вставьте содержимое (сверху вниз, точно так же, как jQuery. SlideDown ()), когда показ превратится в true.

Выдвиньте содержимое (соответственно с эффектом замедления), когда показ превратится в false.

3 ответа

Решение

Сначала некоторый код, затем объяснение. Официальные документы, описывающие это, находятся здесь.

import { trigger, transition, animate, style } from '@angular/animations'

@Component({
  ...
  animations: [
    trigger('slideInOut', [
      transition(':enter', [
        style({transform: 'translateY(-100%)'}),
        animate('200ms ease-in', style({transform: 'translateY(0%)'}))
      ]),
      transition(':leave', [
        animate('200ms ease-in', style({transform: 'translateY(-100%)'}))
      ])
    ])
  ]
})

В вашем шаблоне:

<div *ngIf="visible" [@slideInOut]>This element will slide up and down when the value of 'visible' changes from true to false and vice versa.</div>

Я нашел угловой способ немного сложным для понимания, но как только вы его поймете, он будет довольно легким и мощным.

Часть анимации на человеческом языке:

  • Мы называем эту анимацию "slideInOut".
  • Когда элемент добавлен (:enter), мы делаем следующее:
  • -> Немедленно переместите элемент на 100% вверх (от себя), чтобы появиться за пределами экрана.
  • -> затем анимируйте значение translateY до тех пор, пока мы не достигнем 0%, где элемент, естественно, будет.

  • Когда элемент удален, анимируйте значение translateY (в настоящее время 0) до -100% (вне экрана).

Используемая нами функция замедления упрощена, и за 200 миллисекунд вы можете изменить ее по своему вкусу.

Надеюсь это поможет!

Я ответил на очень похожий вопрос, и вот способ сделать это:

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

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

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

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://angular-muvaqu.stackblitz.io/

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

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

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

На самом деле минимальное количество Angular, которое нужно использовать (как и требовалось в исходном вопросе), это просто добавление класса к элементу DOM, когда show переменная true, и выполнять анимацию / переход через CSS.

Итак, ваш минимальный угловой код:

<div class="box-opener" (click)="show = !show">
    Open/close the box
</div>

<div class="box" [class.opened]="show">
    <!-- Content -->
</div>

С этим решением вам нужно создать правила CSS для перехода, что-то вроде этого:

.box {
    background-color: #FFCC55;
    max-height: 0px;
    overflow-y: hidden;
    transition: ease-in-out 400ms max-height;
}

.box.opened {
    max-height: 500px;
    transition: ease-in-out 600ms max-height;
}

Если у вас есть проблемы с ретро-браузерной совместимостью, просто не забудьте добавить префиксы поставщика в transitions.

Смотрите пример здесь

Самый популярный ответ - не реализовать реальное скольжение внутрь / наружу (или вниз / вверх), как:

  1. Он не выполняет плавный переход по атрибуту высоты. В нулевой момент времени элемент уже имеет 100% своей высоты, что вызывает внезапный сбой в элементах под ним.
  2. При выдвижении / подъеме элемент совершает translateY(-100%) а затем внезапно исчезает, вызывая еще один сбой в элементах под ним.

Вы можете вставить и выдвинуть слайд следующим образом:

мой-component.ts

import { animate, style, transition, trigger } from '@angular/animations';

@Component({
  ...
  animations: [
    trigger('slideDownUp', [
      transition(':enter', [style({ height: 0 }), animate(500)]),
      transition(':leave', [animate(500, style({ height: 0 }))]),
    ]),
  ],
})

мой-component.html

<div @slideDownUp *ngIf="isShowing" class="box">
  I am the content of the div!
</div>

мой-component.scss

.box {
  overflow: hidden;
}
Другие вопросы по тегам