【问题标题】:angular 2 ngIf and CSS transition/animationangular 2 ngIf 和 CSS 过渡/动画
【发布时间】:2016-07-24 21:30:56
【问题描述】:

我希望一个 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>

如果我只使用 [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;
}

【问题讨论】:

    标签: css angular angular-animations


    【解决方案1】:

    更新 4.1.0

    Plunker

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

    更新 2.1.0

    Plunker

    更多详情见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;
    }
    

    原创

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

    改用hidden:

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

    【讨论】:

    • 是的,隐藏只会使它不可见,但元素仍然存在。 *ngIf 将其完全从 DOM 中删除。
    • 就像display:none。没有display:hiddenAFAIK。
    • @GünterZöchbauer 是的,不透明度是硬件加速的,所以它会更适合。
    • 没关系。 opacity 不会删除元素并且仍然会覆盖下面的元素,我建议使用 scale(0) 会影响 UI,例如 display:none;但有一个很好的过渡。为了回答 OP,他可以在 void 状态下使用带有 transform:scale(0) 的角度动画angular.io/docs/ts/latest/guide/animations.html
    • 触发器、样式、动画和过渡项目现在应该包含在 @angular/animations 中。所以导入{ trigger, style, animate, transition } from '@angular/animations';
    【解决方案2】:

    根据最新的angular 2 documentation 您可以为“进入和离开”元素制作动画(如角度 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>
    

    我构建了 滑动和淡入淡出动画的示例 here.

    解释关于“void”和“*”:

    • voidngIf 设置为 false 时的状态(它适用于 元素未附加到视图)。
    • * - 可以有许多动画状态(在文档中阅读更多内容)。 * 状态作为“通配符”优先于所有这些状态(在我的示例中,这是 ngIf 设置为 true 时的状态)。

    注意(取自 Angular 文档):

    Extra 在应用模块内声明, import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

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

    【讨论】:

    • 需要导入 BrowserAnimationsModule 才能使用角度动画。如果我没记错的话,动画模块是在 angular 2 的核心模块中找到的,然后才被移动到它自己的模块中,因此为什么你会发现很多没有导入的 plunker 示例。这是一个更新的 plnkr 导入:Link
    • 这应该是公认的答案,它实际上为那些想要使用 ngIf 而不是其他解决方法的人提供了解决方案。
    【解决方案3】:
        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: '*' }))
          ])
        ])
    

    【讨论】:

      【解决方案4】:

      适用于现代浏览器的纯 CSS 解决方案

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

      【讨论】:

      • enter 纯 CSS 过渡的好选择。将此用作从 ng-enter 类使用迁移的临时解决方案。
      【解决方案5】:

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

      StackBlitz example

      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;
      }
      

      【讨论】:

        【解决方案6】:

        我使用 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%)'}))
            ])
          ])
        ];
        

        【讨论】:

          【解决方案7】:

          在我的例子中,我错误地在错误的组件上声明了动画。

          app.component.html

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

          动画需要在元素所在的组件上声明(appComponent.ts)。我是在 OrderDetailsComponent.ts 上声明动画。

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

          【讨论】:

            猜你喜欢
            • 2017-06-28
            • 2018-04-20
            • 2018-02-06
            • 1970-01-01
            • 2018-07-13
            • 1970-01-01
            • 2020-03-20
            • 2017-01-03
            • 1970-01-01
            相关资源
            最近更新 更多