angular - 以编程方式角度动画,如何在 ngOnDestroy 之前调用动画生成器以进行离开动画
问题描述
在 html 中,我有 ngIf 来控制显示或销毁抽屉组件。我想使用 AnimationBuilder 为抽屉动态调用我的动画。所以我在父组件(应用程序组件)中使用了动画生成器,它在将 slideIn 动画应用于抽屉时效果很好。但是当抽屉组件从 DOM 移开时,我想应用 slideOut 动画。它不起作用,因为在我的动画完成之前调用了 ngOnDestroy。
请注意,我知道:leave
:enter
可能会起作用,但我想知道这是否可以专门与 AnimationBuilder 一起使用。问题是我不知道如何在 ngOnDestroy 之前播放动画。
这是带有 ngIf 的 html 来控制显示或销毁抽屉
<app-drawer #drawer *ngIf="showDrawer"></app-drawer>
我的应用组件
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements OnInit, OnDestroy {
title = 'angular-test';
showDrawer = false;
// @ts-ignore
player: AnimationPlayer;
// @ts-ignore
@ViewChild('drawer', { read: ElementRef }) drawer: ElementRef;
constructor(
private animationBuilder: AnimationBuilder,
private cdr: ChangeDetectorRef
) {}
toggleDrawer(): void {
this.showDrawer = !this.showDrawer;
this.runSlideAnimation(this.showDrawer);
}
runSlideAnimation(showDrawer: boolean): void {
if (showDrawer) {
// to make sure element is on dom by ngIf change before I apply animation
this.cdr.detectChanges();
}
if (this.player) {
this.player.destroy();
}
const factory = this.animationBuilder.build(
showDrawer ? slideInAnimation : slideOutAnimation
);
this.player = factory.create(this.drawer.nativeElement);
this.player.play();
// My thoughts was manually update dom when slideout animation finish so angular will call
// ngOndestroy after my animation is done. it didn't work
this.player.onDone(() => {
this.cdr.detectChanges();
});
}
ngOnInit(): void {
console.log('init');
}
ngOnDestroy(): void {
if (this.player) {
this.player.destroy();
}
console.log('destroy');
}
get slideInAnimation() {
return [
style({ opacity: 0, transform: 'translateX(100%)' }),
animate('600ms', style({ opacity: 1, transform: 'translateX(0)' })),
];
}
get slideOutAnimation() {
return [
style({ opacity: 1, transform: 'translateX(0)' }),
animate('900ms', style({ opacity: 0, transform: 'translateX(100%)' })),
];
}
}
解决方案
我想你可以使用二传手
_showDrawer:boolean
get showDrawer(){
return this._showDrawer;
}
set showDrawer(value){
if (!value){
this.runSlideAnimation(value,true)
}
else
this._showDrawer=value
}
而你的函数 runSlideAnimation
runSlideAnimation(showDrawer: boolean,forceDestroy:boolean=false){
...
this.player.onDone(() => {
if (forceDestroy)
this._showDrawer=false
this.cdr.detectChanges();
});
}
推荐阅读
- swift - Coinbase API 解析为 Swift 应用程序返回不正确的格式
- css - 位于文本上方的无序列表项项目符号点
- jquery - woocommerce结帐选项下拉蓝色问题
- php - 声明和使用 PHP 命名空间
- authentication - GitLab/GitHub 身份验证如何与普通的 SSH 会话分开?
- sql - 子查询和多表
- angular - “从不”类型上不存在属性“id”
- java - 在测试中的 Kafka 侦听器中未使用 Spring @MockBean 注释存储库
- python - 嵌入矩阵中的权重是如何计算或更新的?
- python - 多元正态分布样本上的 Kmean