【问题标题】:How to detect when ripple has finished animating in Angular 4+?如何检测涟漪何时在 Angular 4+ 中完成动画?
【发布时间】:2019-01-04 05:30:05
【问题描述】:

所以我有一个待办事项列表,每个都有一个波纹,当您单击待办事项时,我想将页面路由到一个新的 URL,但我希望波纹动画在此之前完成。

在 Angular 4+ 中,我找不到轻松做到这一点的方法,到目前为止我想出的唯一解决方案是以下一个,在 Angular 中是否有“正确”的方法来做到这一点?

组件:

export class TodoListComponent {
  public todos = this.todoService.todos$;

  @ViewChildren(MatRipple) private ripples: QueryList<MatRipple>;

  constructor(private todoService: TodoService, private router: Router) {}

  public onGoTo(event: MouseEvent, index: number, todo: Todo): void {
    const enterDuration = 300;
    const exitDuration = 50;

    const rippleRef = this.ripples
      .toArray()
      [index].launch(event.clientX, event.clientY, {
        animation: {
          enterDuration,
          exitDuration,
        },
      });
    setTimeout(() => rippleRef.fadeOut, enterDuration);
    const animationDuration = enterDuration + exitDuration;
    setTimeout(() => this.router.navigate([todo.id]), animationDuration);
  }
}

模板:

<mat-list>
    <mat-list-item
      *ngFor="let todo of (todos | async); let index = index"
      mat-ripple
      [matRippleDisabled]="true"
    >
      <div class="Todo">
        <div class="Todo__Label" (click)="onGoTo($event, index, todo)">
          {{ todo.title }}
        </div>
      </div>
    </mat-list-item>
  </mat-list>

【问题讨论】:

    标签: angular angular-material angular-animations


    【解决方案1】:

    在 Angular 4+ 中,我找不到轻松做到这一点的方法,到目前为止我想出的唯一解决方案是以下一个,在 Angular 中是否有“正确”的方法来做到这一点?

    不,没有 Angular 方式,因为 MatRipple 组件不是以 Angular 方式完成的。波纹效果由 RippleRenderer 手动管理,看起来不像使用 Angular 动画。

    https://github.com/angular/material2/blob/master/src/lib/core/ripple/ripple-renderer.ts

    const rippleRef = this.ripples
      .toArray()
      [index].launch(event.clientX, event.clientY, {
        animation: {
          enterDuration,
          exitDuration,
        },
      });
    

    launch 返回的 RippleRef 对象会告诉你涟漪的当前状态是什么。有一个rippleRef.state 属性会随着 RippleRenderer 执行动画而改变。

    https://github.com/angular/material2/blob/master/src/lib/core/ripple/ripple-ref.ts

    您可以尝试将在波纹动画完成时发出的 observable 组合在一起,但您唯一的其他选择是使用setTimeout()

     interval(100)
        .pipe(
          map(()=>rippleRef.state),
          distinctUntilChanged(),
          filter(state=>state === RippleState.HIDDEN),
          first()
        ).subscribe(()=> {
             console.log('ripple animation finished');
        });
    

    我不确定上述是否可行,因为第一个状态是隐藏,然后又转换回隐藏。我假设interval(100) 将跳过第一个隐藏状态。

    【讨论】:

      【解决方案2】:

      Angular 支持 @animation.start@animation.done 来利用动画事件。

      例如,你可以使用

      (@routeAnimation.start)=onStart($event)(@routeAnimation.done)=onDone($event) 在您的组件中。

      您可以通过Angular animations了解更多信息

      希望对您有所帮助!

      示例代码:

      import { Component, OnInit } from '@angular/core';
      import { trigger, state, style, animate, transition } from '@angular/core';
      
      
      @Component({
        selector: 'app-first',
        template: `
          <div class="w9914420" [@routeAnimation]="show" 
              (@routeAnimation.start)="onStart($event)"
              (@routeAnimation.done)="onDone($event)">
              <h2>
                 first-component Works!
              </h2>
        </div>
        `,
        host: {
          '[@routeAnimation]': 'true',
          '[style.display]': "'block'",
          '[style.position]': "'absolute'"
        },
        animations: [
          trigger('routeAnimation', [
            state('*', style({transform: 'translateX(0)', opacity: 1})),
            transition('void => *', [style({transform: 'translateX(-100%)', opacity: 0}),animate(500)]),
            transition('* => void', animate(500, style({transform: 'translateX(100%)', opacity: 0})))
          ])
        ]
      })
      export class FirstComponent implements OnInit {
      
        constructor() { }
      
        ngOnInit() {
      
        }
      
        onStart($event) {
          // call this function at start of the animation.
          console.log('starting animation');
        }
        
        onDone($event) {
          // call this function at the end of the animation.
          console.log('the end of the animation');
        }
      
      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多