angular 2 ngIf 和 CSS 过渡/动画

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36417931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 11:51:14  来源:igfitidea点击:

angular 2 ngIf and CSS transition/animation

cssangularangular-animations

提问by Han Che

I want a div to slide in from the right in angular 2 using css.

我想要一个 div 使用 css 从 angular 2 的右侧滑入。

  <div class="note" [ngClass]="{'transition':show}" *ngIf="show">
    <p> Notes</p>
  </div>
  <button class="btn btn-default" (click)="toggle(show)">Toggle</button>

I works fine if i only use [ngClass] to toggle class and utilise opacity. But li don't want that element to be rendered from the beginning so I "hide" it with ngIf first, but then the transition wont't work.

如果我只使用 [ngClass] 来切换类并利用不透明度,我工作得很好。但是 li 不希望该元素从一开始就呈现,所以我首先用 ngIf “隐藏”它,但是转换将不起作用。

.transition{
  -webkit-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
  -moz-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
  -ms-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out ;
  -o-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
  transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
  margin-left: 1500px;
  width: 200px;
  opacity: 0;
}

.transition{
  opacity: 100;
  margin-left: 0;
}

回答by Günter Z?chbauer

update 4.1.0

更新 4.1.0

Plunker

普朗克

See also https://github.com/angular/angular/blob/master/CHANGELOG.md#400-rc1-2017-02-24

另见https://github.com/angular/angular/blob/master/CHANGELOG.md#400-rc1-2017-02-24

update 2.1.0

更新 2.1.0

Plunker

普朗克

For more details see Animations at angular.io

有关更多详细信息,请参阅angular.io 上的动画

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

@Component({
  selector: 'my-app',
  animations: [
    trigger(
      'enterAnimation', [
        transition(':enter', [
          style({transform: 'translateX(100%)', opacity: 0}),
          animate('500ms', style({transform: 'translateX(0)', opacity: 1}))
        ]),
        transition(':leave', [
          style({transform: 'translateX(0)', opacity: 1}),
          animate('500ms', style({transform: 'translateX(100%)', opacity: 0}))
        ])
      ]
    )
  ],
  template: `
    <button (click)="show = !show">toggle show ({{show}})</button>

    <div *ngIf="show" [@enterAnimation]>xxx</div>
  `
})
export class App {
  show:boolean = false;
}

original

原来的

*ngIfremoves the element from the DOM when the expression becomes false. You can't have a transition on a non-existing element.

*ngIf当表达式变为 时,从 DOM 中删除元素false。您不能对不存在的元素进行过渡。

Use instead hidden:

改用hidden

<div class="note" [ngClass]="{'transition':show}" [hidden]="!show">

回答by Asaf Hananel

According to the latest angular 2 documentationyou can animate "Entering and Leaving" elements(like in angular 1).

根据最新的angular 2 文档,您可以为“进入和离开”元素设置动画(如 angular 1)。

Example of simple fade animation:

简单的淡入淡出动画示例:

In relevant @Component add:

在相关的@Component 添加:

animations: [
  trigger('fadeInOut', [
    transition(':enter', [   // :enter is alias to 'void => *'
      style({opacity:0}),
      animate(500, style({opacity:1})) 
    ]),
    transition(':leave', [   // :leave is alias to '* => void'
      animate(500, style({opacity:0})) 
    ])
  ])
]

Do not forget to add imports

不要忘记添加导入

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

The relevant component's html's element should look like:

相关组件的 html 元素应如下所示:

<div *ngIf="toggle" [@fadeInOut]>element</div>

I built example of slide and fade animationhere.

在这里构建了幻灯片和淡入淡出动画的示例。

Explanationon 'void' and '*':

说明在“无效”和“*”:

  • voidis the state when ngIfis set to false (it applies when the element is not attached to a view).
  • *- There can be many animation states (read more in docs). The *state takes precedence over all of them as a "wildcard" (in my example this is the state when ngIfis set to true).
  • voidngIf设置为 false时的状态(当元素未附加到视图时适用)。
  • *- 可以有许多动画状态(在文档中阅读更多内容)。该*状态优先于所有的人都为“通配符”(在我的例子,这是当状态ngIf设置为true)。

Notice(taken from angular docs):

注意(取自 angular 文档):

Extradeclare inside the app module, import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

在 app 模块中额外声明, import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

Angular animations are built on top of the standard Web Animations API and run natively on browsers that support it. For other browsers, a polyfill is required. Grab web-animations.min.js from GitHub and add it to your page.

Angular 动画建立在标准的 Web Animations API 之上,并在支持它的浏览器上本地运行。对于其他浏览器,需要一个 polyfill。从 GitHub 获取 web-animations.min.js 并将其添加到您的页面。

回答by kravits88

    trigger('slideIn', [
      state('*', style({ 'overflow-y': 'hidden' })),
      state('void', style({ 'overflow-y': 'hidden' })),
      transition('* => void', [
        style({ height: '*' }),
        animate(250, style({ height: 0 }))
      ]),
      transition('void => *', [
        style({ height: '0' }),
        animate(250, style({ height: '*' }))
      ])
    ])

回答by Mike

CSS only solution for modern browsers

现代浏览器的 CSS 唯一解决方案

@keyframes slidein {
    0%   {margin-left:1500px;}
    100% {margin-left:0px;}
}
.note {
    animation-name: slidein;
    animation-duration: .9s;
    display: block;
}

回答by JayChase

One way is to use a setter for the ngIf property and set the state as part of updating the value.

一种方法是对 ngIf 属性使用 setter 并将状态设置为更新值的一部分。

StackBlitz example

StackBlitz 示例

fade.component.ts

淡入淡出.component.ts

 import {
    animate,
    AnimationEvent,
    state,
    style,
    transition,
    trigger
  } from '@angular/animations';
  import { ChangeDetectionStrategy, Component, Input } from '@angular/core';

  export type FadeState = 'visible' | 'hidden';

  @Component({
    selector: 'app-fade',
    templateUrl: './fade.component.html',
    styleUrls: ['./fade.component.scss'],
    animations: [
      trigger('state', [
        state(
          'visible',
          style({
            opacity: '1'
          })
        ),
        state(
          'hidden',
          style({
            opacity: '0'
          })
        ),
        transition('* => visible', [animate('500ms ease-out')]),
        transition('visible => hidden', [animate('500ms ease-out')])
      ])
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
  })
  export class FadeComponent {
    state: FadeState;
    // tslint:disable-next-line: variable-name
    private _show: boolean;
    get show() {
      return this._show;
    }
    @Input()
    set show(value: boolean) {
      if (value) {
        this._show = value;
        this.state = 'visible';
      } else {
        this.state = 'hidden';
      }
    }

    animationDone(event: AnimationEvent) {
      if (event.fromState === 'visible' && event.toState === 'hidden') {
        this._show = false;
      }
    }
  }

fade.component.html

淡入淡出.component.html

 <div
    *ngIf="show"
    class="fade"
    [@state]="state"
    (@state.done)="animationDone($event)"
  >
    <button mat-raised-button color="primary">test</button>
  </div>

example.component.css

例子.component.css

:host {
  display: block;
}
.fade {
  opacity: 0;
}

回答by ramon22

Am using angular 5 and for an ngif to work for me that is in a ngfor, I had to use animateChild and in the user-detail component I used the *ngIf="user.expanded" to show hide user and it worked for entering a leaving

我正在使用 angular 5 并且对于在 ngfor 中为我工作的 ngif,我必须使用 animateChild 并且在用户详细信息组件中我使用了 *ngIf="user.expanded" 来显示隐藏用户并且它可以用于输入离开

 <div *ngFor="let user of users" @flyInParent>
  <ly-user-detail [user]= "user" @flyIn></user-detail>
</div>

//the animation file


export const FLIP_TRANSITION = [ 
trigger('flyInParent', [
    transition(':enter, :leave', [
      query('@*', animateChild())
    ])
  ]),
  trigger('flyIn', [
    state('void', style({width: '100%', height: '100%'})),
    state('*', style({width: '100%', height: '100%'})),
    transition(':enter', [
      style({
        transform: 'translateY(100%)',
        position: 'fixed'
      }),
      animate('0.5s cubic-bezier(0.35, 0, 0.25, 1)', style({transform: 'translateY(0%)'}))
    ]),
    transition(':leave', [
      style({
        transform: 'translateY(0%)',
        position: 'fixed'
      }),
      animate('0.5s cubic-bezier(0.35, 0, 0.25, 1)', style({transform: 'translateY(100%)'}))
    ])
  ])
];

回答by Anonymoose

In my case I declared the animation on the wrong component by mistake.

就我而言,我错误地在错误的组件上声明了动画。

app.component.html

应用程序组件.html

  <app-order-details *ngIf="orderDetails" [@fadeInOut] [orderDetails]="orderDetails">
  </app-order-details>

The animation needs to be declared on the component where the element is used in (appComponent.ts). I was declaring the animation on OrderDetailsComponent.tsinstead.

动画需要在 ( appComponent.ts) 中使用元素的组件上声明。我正在声明动画OrderDetailsComponent.ts

Hopefully it will help someone making the same mistake

希望它能帮助犯同样错误的人