angular 2 ngIf และ CSS การเปลี่ยน / ภาพเคลื่อนไหว


121

ฉันต้องการให้ div เลื่อนเข้ามาจากด้านขวาในเชิงมุม 2 โดยใช้ css

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

ฉันจะทำงานได้ดีถ้าฉันใช้ [ngClass] เพื่อสลับคลาสและใช้ความทึบ แต่ฉันไม่ต้องการให้องค์ประกอบนั้นแสดงผลตั้งแต่ต้นดังนั้นฉันจึง "ซ่อน" ด้วย 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;
}

คำตอบ:


195

อัปเดต 4.1.0

Plunker

ดูเพิ่มเติมที่https://github.com/angular/angular/blob/master/CHANGELOG.md#400-rc1-2017-02-24

อัปเดต 2.1.0

Plunker

สำหรับรายละเอียดเพิ่มเติมโปรดดูภาพเคลื่อนไหวที่ 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;
}

เป็นต้นฉบับ

*ngIfเอาองค์ประกอบจาก DOM falseเมื่อการแสดงออกจะกลายเป็น คุณไม่สามารถเปลี่ยนองค์ประกอบที่ไม่มีอยู่ได้

ใช้แทนhidden:

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

2
ใช่ซ่อนไว้ทำให้มองไม่เห็นเท่านั้น แต่องค์ประกอบยังคงอยู่ *ngIfลบทั้งหมดออกจาก DOM
GünterZöchbauer

1
มันเหมือนกับdisplay:none. ไม่มีdisplay:hiddenAFAIK
GünterZöchbauer

1
@ GünterZöchbauerใช่ความทึบเป็นฮาร์ดแวร์ที่ได้รับการรับรองดังนั้นจึงเหมาะสมกว่า
Ændri Domi

1
ไม่เป็นไร. ความทึบจะไม่ลบองค์ประกอบและจะยังคงครอบคลุมองค์ประกอบด้านล่างฉันขอแนะนำให้ใช้มาตราส่วน (0) ซึ่งจะส่งผลต่อ UI เช่น display: none; แต่มีการเปลี่ยนแปลงที่ดี ในการตอบ OP เขาสามารถใช้แอนิเมชั่นเชิงมุมangular.io/docs/ts/latest/guide/animations.htmlพร้อมกับ transform: scale (0) ที่สถานะโมฆะ
Ændri Domi

1
ตอนนี้ควรรวมรายการทริกเกอร์สไตล์ภาพเคลื่อนไหวและการเปลี่ยนแปลงจาก @ angular / animations ดังนั้นนำเข้า{ trigger, style, animate, transition } from '@angular/animations';
Joel Hernandez

137

ตามเอกสารเชิงมุม 2 ล่าสุดคุณสามารถทำให้องค์ประกอบ "การเข้าและออก" เคลื่อนไหวได้ (เช่นในเชิงมุม 1)

ตัวอย่างแอนิเมชั่นเฟดง่ายๆ:

ใน @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})) 
    ])
  ])
]

อย่าลืมเพิ่มการนำเข้า

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

องค์ประกอบ html ของคอมโพเนนต์ที่เกี่ยวข้องควรมีลักษณะดังนี้:

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

ฉันสร้างตัวอย่างของภาพนิ่งและภาพเคลื่อนไหวจาง ที่นี่

คำอธิบายเกี่ยวกับ 'void' และ '*':

  • voidคือสถานะเมื่อngIfถูกตั้งค่าเป็นเท็จ (ใช้เมื่อองค์ประกอบไม่ได้แนบกับมุมมอง)
  • *- อาจมีสถานะภาพเคลื่อนไหวได้หลายแบบ (อ่านเพิ่มเติมในเอกสาร) *รัฐจะเหนือกว่าทั้งหมดของพวกเขาเป็น "สัญลักษณ์แทน" (ในตัวอย่างของฉันนี่คือสถานะที่เมื่อngIfมีการตั้งค่าtrue)

ข้อสังเกต (นำมาจากเอกสารเชิงมุม):

ประกาศพิเศษภายในโมดูลแอป import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

แอนิเมชั่นเชิงมุมสร้างขึ้นจาก Web Animations API มาตรฐานและรันบนเบราว์เซอร์ที่รองรับ สำหรับเบราว์เซอร์อื่นจำเป็นต้องมี polyfill หยิบ web-animations.min.js จาก GitHub แล้วเพิ่มลงในเพจของคุณ


2
จำเป็นต้องนำเข้า BrowserAnimationsModule เพื่อใช้ภาพเคลื่อนไหวเชิงมุม ถ้าฉันไม่ผิดโมดูลภาพเคลื่อนไหวจะพบในโมดูลหลักของ angular 2 ก่อนที่จะถูกย้ายไปยังโมดูลของตัวเองด้วยเหตุนี้คุณจึงพบตัวอย่างของ plunker มากมายโดยไม่ต้องนำเข้า นี่คือ plnkr ที่อัปเดตพร้อมการนำเข้า: Link
snaplemouton

1
เมื่อใช้วิธีการดังกล่าวleaveภาพเคลื่อนไหวจะไม่เกิดขึ้นเนื่องจากส่วนประกอบถูกลบออกจาก DOM *ngIfก่อนหน้านั้น
Slava Fomin II

4
นี่ควรเป็นคำตอบที่ได้รับการยอมรับซึ่งเป็นวิธีแก้ปัญหาสำหรับผู้ที่ต้องการใช้ ngIf ไม่ใช่วิธีแก้ปัญหาอื่น ๆ
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: '*' }))
      ])
    ])

11

โซลูชัน CSS สำหรับเบราว์เซอร์สมัยใหม่เท่านั้น

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

ทางเลือกที่ดีสำหรับป้อนการเปลี่ยน CSS เท่านั้น ใช้สิ่งนี้เป็นวิธีแก้ปัญหาชั่วคราวสำหรับการย้ายจากng-enterการใช้คลาส
edmundo096

4

วิธีหนึ่งคือใช้ setter สำหรับคุณสมบัติ ngIf และตั้งค่าสถานะเป็นส่วนหนึ่งของการอัพเดตค่า

ตัวอย่าง 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;
}

3

ฉันใช้ angular 5 และเพื่อให้ ngif ทำงานให้ฉันที่อยู่ใน ngfor ฉันต้องใช้ 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%)'}))
    ])
  ])
];

0

ในกรณีของฉันฉันบอกว่าแอนิเมชั่นผิดองค์ประกอบโดยไม่ได้ตั้งใจ

app.component.html

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

ต้องมีการประกาศภาพเคลื่อนไหวบนส่วนประกอบที่ใช้องค์ประกอบใน ( appComponent.ts) ฉันกำลังประกาศภาพเคลื่อนไหวOrderDetailsComponent.tsแทน

หวังว่าจะช่วยให้คนที่ทำผิดพลาดเหมือนกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.