web-dev-qa-db-fra.com

angular 2 ngIf et transition / animation CSS

Je veux qu'une div glisse de la droite dans angular 2 en utilisant css.

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

Je fonctionne bien si je n’utilise que [ngClass] pour changer de classe et utiliser l’opacité. Mais comme je ne veux pas que cet élément soit rendu depuis le début, je le "cache" d'abord avec ngIf, mais ensuite la transition ne fonctionnera pas.

.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;
}
104
Han Che

mise à jour 4.1.0

Plunker

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

update 2.1.0

Plunker

Pour plus de détails, voir Animations at 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

*ngIf supprime l'élément du DOM lorsque l'expression devient false. Vous ne pouvez pas avoir de transition sur un élément non existant.

Utilisez à la place hidden:

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

Selon la dernière documentation angulaire 2, vous pouvez animer les éléments "Entrer et quitter" (comme dans angular 1).

Exemple d'animation de fondu simple:

Dans @Component pertinent, ajoutez:

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})) 
    ])
  ])
]

N'oubliez pas d'ajouter des importations

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

L'élément html du composant approprié devrait ressembler à ceci:

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

J'ai construit l'exemple de animation de diapositives et de fondus ici .

Explication sur 'void' et '*':

  • void est l'état où ngIf est défini sur false (il s'applique lorsque l'élément n'est pas attaché à une vue).
  • * - Il peut y avoir plusieurs états d'animation (pour en savoir plus, consultez la documentation). L'état * prime sur tous en tant que "caractère générique" (dans mon exemple, il s'agit de l'état où ngIf est défini sur true).

Remarque (extrait de angular docs):

Extra déclare dans le module d'application, import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

Les animations angulaires sont construites sur l'API Web Animations standard et s'exécutent en mode natif sur les navigateurs qui le prennent en charge. Pour les autres navigateurs, un polyfill est requis. Saisissez web-animations.min.js dans GitHub et ajoutez-le à votre page.

118
Asaf Hananel
    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: '*' }))
      ])
    ])
14
kravits88

Solution uniquement CSS pour les navigateurs modernes

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

J'utilise angular 5 et pour qu'un ngif fonctionne dans un ngfor, je devais utiliser animateChild et dans le composant user-detail, j'ai utilisé * ngIf = "user.expanded" pour afficher masquer utilisateur et cela a fonctionné pour entrer dans un départ

 <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%)'}))
    ])
  ])
];
3
ramon22

Une solution consiste à utiliser un séparateur pour la propriété ngIf et à définir l'état dans le cadre de la mise à jour de la valeur.

exemple de StackBlitz

fade.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

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

example.component.css

:Host {
  display: block;
}
.fade {
  opacity: 0;
}
2
JayChase