網站搜尋

typescript - Angular (4、5、6、7) - ngIf 上進出滑動動畫的簡單範例


用最基本的方法以及 Angular4 原生的方式,如何讓容器元素 滑入 和 滑出?

例如

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

當 show 變為 true 時,Slide In 內容(從上到下,就像 jQuery.slideDown() 一樣)。

當 show 變為 false 時,滑出 內容(適當地帶有 ease-out 效果)。

答案#1

先是一些程式碼,然後是說明。官方文件描述這個的在這裡。

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>

我覺得 Angular 的方式有點難以理解,但一旦你理解了,它就相當簡單且強大。

人類語言中的動畫部分:

  • 我們將這個動畫命名為『slideInOut』。

  • 當元素被添加時(:enter),我們執行以下操作:

  • ->立即將元素向上移動100%(相對於自身),以顯示在螢幕之外。

  • ->然後動畫化 translateY 值,直到到達 0%,此時元素將自然處於該位置。

  • 當元素被移除時,將 translateY 的值(目前為 0)動畫化至 -100%(螢幕之外)。

我們使用的緩動函數是 ease-in,時間為 200 毫秒,你可以根據自己的喜好更改它。

答案#2

我回答過一個非常相似的問題,這裡有一種做法:

首先,創建一個文件,在那裡定義你的動畫並導出它們。只是為了在你的 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 ],
  ...
})

答案#3

實際上,所需使用的最少 Angular(如原問題所要求的)只是當 show 變數為 true 時向 DOM 元素添加一個 class,並通過 CSS 執行動畫/過渡。

所以你的 最小 Angular 代碼是這樣的:

<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;
}

如果你有舊版瀏覽器相容性問題,只要記得在 transition 中加入廠商前綴即可。

在這裡查看範例