angular 2 ngIf y CSS transición / animación


Quiero que un div se deslice desde la derecha en angular 2 usando css.

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

Funciona bien si solo uso [ngClass] para alternar clase y utilizar opacidad. Pero li no quiere que ese elemento se renderice desde el principio, así que lo "escondo" con ngIf primero, pero luego la transición no funcionará.

.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;
}
Author: FRECIA, 2016-04-05

6 answers

Actualización 4.1.0

Plunker

Véase también https://github.com/angular/angular/blob/master/CHANGELOG.md#400-rc1-2017-02-24

Actualización 2.1.0

Plunker

Para más detalles, ver Animaciones en 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 elimina el elemento del DOM cuando la expresión se convierte en false. No se puede tener una transición en un no existente elemento.

Use en su lugar hidden:

<div class="note" [ngClass]="{'transition':show}" [hidden]="!show">
 143
Author: Günter Zöchbauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-26 15:49:35

Según la última documentación de angular 2 puede animar elementos" Entrando y saliendo " (como en angular 1).

Ejemplo de animación de fundido simple:

En el componente @relevante agrega:

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

No se olvide de añadir importaciones

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

El elemento html del componente relevante debería tener el siguiente aspecto:

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

Construí un ejemplo de animación de diapositivas y fundido aquí.

Explicación sobre 'void ' y'*':

  • void es el estado cuando ngIf se establece en false (se aplica cuando el elemento no se adjunta a una vista).
  • * - Puede haber muchos estados de animación (lea más en los documentos). El estado * tiene prioridad sobre todos ellos como un "comodín" (en mi ejemplo este es el estado cuando ngIf se establece en true).

Aviso (tomado de angular docs):

Las animaciones angulares se construyen sobre la API estándar de animaciones web y se ejecuta de forma nativa en navegadores que lo admiten. Para otros navegadores, un se requiere polyfill. Agarra animaciones web.min.js de GitHub y añadir a tu página.

 95
Author: Asaf Hananel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-28 13:07:28
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: '*' }))
])
 12
Author: kravits88,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-06 14:54:11

Solución única de CSS para navegadores modernos

@keyframes slidein {
    0%   {margin-left:1500px;}
    100% {margin-left:0px;}
}
.note {
    animation-name: slidein;
    animation-duration: .9s;
    display: block;
}
 5
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-07 08:49:45

Estoy usando angular 5 y para que un ngif funcione para mí que está en un ngfor, tuve que usar animateChild y en el componente user-detail utilicé el *ngIf="user.expanded " para mostrar ocultar el usuario y funcionó para ingresar una salida

 <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%)'}))
    ])
  ])
];
 2
Author: ramon22,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-03 18:37:45

Una forma es usar un setter para la propiedad ngIf y establecer el estado como parte de la actualización del valor. Cuando se establece la propiedad a true DetectChanges () necesita ser llamado para asegurarse de que el elemento se añade de nuevo al dom antes de que el estado de la animación se cambia.

Ejemplo de StackBlitz

Ejemplo.componente.ts

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

@Component({
  selector: 'example',
  templateUrl: `./example.component.html`,
  styleUrls: [`./example.component.css`],
  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')
      ])
    ])
  ]
})
export class ExampleComponent implements OnInit  {
  state: string;

    private _showButton: boolean;
    get showButton() {
      return this._showButton;
    }
    set showButton(val: boolean) {
      if (val) {
        this._showButton = true;
        this.state = 'visible';
      } else {
        this.state = 'hidden';
      }
    }

    constructor() {
    }

    ngOnInit() {
      this.showButton = true;
    }

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

    log() {
      console.log('clicked');
    }
}

Ejemplo.componente.html

<div>
  <p>animation state: {{state}}</p>
  <p>showButton: {{showButton}}</p>
  <button (click)="showButton = !showButton">toggle</button>
</div>
<button class="animation-target" *ngIf="showButton" [@state]="state" (@state.done)="animationDone($event)" (click)="log()" >animation target</button>

Ejemplo.componente.css

.animation-target {
    background: orange;
    height: 150px;
    width: 150px;
    cursor: pointer;
    opacity: 0;
}
 2
Author: JayChase,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 12:52:01