Winkel 2 ngIf und CSS Übergang / Animation

121

Ich möchte, dass ein Div mit css von rechts in Winkel 2 hineingleitet.

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

Ich arbeite gut, wenn ich nur [ngClass] verwende, um die Klasse umzuschalten und die Deckkraft zu nutzen. Aber ich möchte nicht, dass dieses Element von Anfang an gerendert wird, also "verstecke" ich es zuerst mit ngIf, aber dann funktioniert der Übergang nicht.

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

Antworten:

195

Update 4.1.0

Plunker

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

Update 2.1.0

Plunker

Weitere Informationen finden Sie unter Animationen unter angle.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

*ngIfEntfernt das Element aus dem DOM, wenn der Ausdruck wird false. Sie können keinen Übergang für ein nicht vorhandenes Element vornehmen.

Verwenden Sie stattdessen hidden:

<div class="note" [ngClass]="{'transition':show}" [hidden]="!show">
Günter Zöchbauer
quelle
2
Ja, versteckt macht es nur unsichtbar, aber das Element existiert noch. *ngIfentfernt es vollständig aus dem DOM.
Günter Zöchbauer
1
Es ist wie display:none. Es gibt keine display:hiddenAFAIK.
Günter Zöchbauer
1
@ GünterZöchbauer ja, die Deckkraft ist Hardware beschleunigt, damit sie besser passt.
Ændri Domi
1
Keine Ursache. Durch die Deckkraft wird das Element nicht entfernt und die darunter liegenden Elemente werden weiterhin abgedeckt. Ich empfehle die Verwendung der Skala (0), die sich auf die Benutzeroberfläche auswirkt, z. B. Anzeige: keine; aber mit einem schönen Übergang. Um das OP zu beantworten, kann er die Winkelanimationen angular.io/docs/ts/latest/guide/animations.html mit transform: scale (0) im leeren Zustand verwenden
Ændri Domi
1
Die Trigger-, Style-, Animations- und Übergangselemente sollten jetzt in @ angle / animations enthalten sein. Also importieren{ trigger, style, animate, transition } from '@angular/animations';
Joel Hernandez
136

Gemäß der neuesten Dokumentation zu Winkel 2 können Sie Elemente "Eingeben und Verlassen" animieren (wie in Winkel 1).

Beispiel für eine einfache Überblendanimation:

In der relevanten @Component hinzufügen:

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

Vergessen Sie nicht, Importe hinzuzufügen

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

Das HTML-Element der relevanten Komponente sollte folgendermaßen aussehen:

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

Ich baute Beispiel Rutsche und verblassen Animation hier .

Erklärung zu 'void' und '*':

  • voidist der Status, wenn ngIffalse festgelegt ist (gilt, wenn das Element nicht an eine Ansicht angehängt ist).
  • *- Es kann viele Animationszustände geben (lesen Sie mehr in den Dokumenten). Der *Status hat Vorrang vor allen als "Platzhalter" (in meinem Beispiel ist dies der Status, auf den ngIfgesetzt ist true).

Hinweis (aus eckigen Dokumenten entnommen):

Extra im App-Modul deklarieren, import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

Winkelanimationen basieren auf der Standard-Webanimations-API und werden nativ in Browsern ausgeführt, die dies unterstützen. Für andere Browser ist eine Polyfüllung erforderlich. Holen Sie sich web-animations.min.js von GitHub und fügen Sie es Ihrer Seite hinzu.

Asaf Hananel
quelle
2
Sie müssen das BrowserAnimationsModule importieren, um eckige Animationen verwenden zu können. Wenn ich mich nicht irre, wurde das Animationsmodul im Kernmodul von Winkel 2 gefunden, bevor es in ein eigenes Modul verschoben wurde. Daher finden Sie viele Plunker-Beispiele ohne Import. Hier ist ein aktualisiertes plnkr mit dem Import: Link
snaplemouton
1
Bei Verwendung eines solchen Ansatzes findet die leaveAnimation nicht statt, da die Komponente zuvor aus dem DOM entfernt wurde *ngIf.
Slava Fomin II
4
Dies sollte die akzeptierte Antwort sein. Sie bietet tatsächlich die Lösung für diejenigen, die ngIf und keine anderen Problemumgehungen verwenden möchten.
Ovi Trif
17
    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: '*' }))
      ])
    ])
kravits88
quelle
11

Nur CSS-Lösung für moderne Browser

@keyframes slidein {
    0%   {margin-left:1500px;}
    100% {margin-left:0px;}
}
.note {
    animation-name: slidein;
    animation-duration: .9s;
    display: block;
}
Mike
quelle
Gute Alternative für die Eingabe eines Nur-CSS-Übergangs. Verwendet dies als zeitliche Lösung für die Migration von der ng-enterKlassenverwendung.
edmundo096
4

Eine Möglichkeit besteht darin, einen Setter für die ngIf-Eigenschaft zu verwenden und den Status als Teil der Aktualisierung des Werts festzulegen.

StackBlitz Beispiel

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;
}
JayChase
quelle
3

Ich verwende Angular 5 und damit ein Ngif für mich funktioniert, das sich in einem Ngfor befindet, musste ich animateChild verwenden. In der Benutzerdetailkomponente habe ich * ngIf = "user.expanded" verwendet, um den Benutzer hide anzuzeigen, und es funktionierte für die Eingabe ein Abschied

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

In meinem Fall habe ich versehentlich die Animation auf der falschen Komponente deklariert.

app.component.html

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

Die Animation muss für die Komponente deklariert werden, in der das Element in ( appComponent.ts) verwendet wird. Ich habe OrderDetailsComponent.tsstattdessen die Animation aktiviert.

Hoffentlich hilft es jemandem, der den gleichen Fehler macht

Anonymoose
quelle