如何检测 Angular 4+ 中的波纹何时完成动画?
How to detect when ripple has finished animating in Angular 4+?
所以我有一个待办事项列表,每个都有一个涟漪,当你点击待办事项时,我想将页面路由到一个新的 URL 但我希望涟漪动画在此之前完成。
在 Angular 4+ 中,我找不到一种方法来轻松地做到这一点,到目前为止我想出的唯一解决方案是以下一个,有没有 "right" 方法来在 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 支持 @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');
}
}
In Angular 4+ I can't find a way to do this easily, the only solution I have come up with so far is the following one, is there a "right" way to do this in 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
您可以尝试组合一个在波纹动画完成时发出的可观察对象,但您唯一的其他选择是使用 setTimeout()
.
interval(100)
.pipe(
map(()=>rippleRef.state),
distinctUntilChanged(),
filter(state=>state === RippleState.HIDDEN),
first()
).subscribe(()=> {
console.log('ripple animation finished');
});
我不确定以上是否可行,因为第一个状态是隐藏,然后它转换回隐藏。我假设 interval(100)
将跳过第一个隐藏状态。
所以我有一个待办事项列表,每个都有一个涟漪,当你点击待办事项时,我想将页面路由到一个新的 URL 但我希望涟漪动画在此之前完成。
在 Angular 4+ 中,我找不到一种方法来轻松地做到这一点,到目前为止我想出的唯一解决方案是以下一个,有没有 "right" 方法来在 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 支持 @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');
}
}
In Angular 4+ I can't find a way to do this easily, the only solution I have come up with so far is the following one, is there a "right" way to do this in 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
您可以尝试组合一个在波纹动画完成时发出的可观察对象,但您唯一的其他选择是使用 setTimeout()
.
interval(100)
.pipe(
map(()=>rippleRef.state),
distinctUntilChanged(),
filter(state=>state === RippleState.HIDDEN),
first()
).subscribe(()=> {
console.log('ripple animation finished');
});
我不确定以上是否可行,因为第一个状态是隐藏,然后它转换回隐藏。我假设 interval(100)
将跳过第一个隐藏状态。