angular:传递数据给动画
angular: pass data to animation
我已经为 angular 创建了一个 bootstrap 模态组件,但我想选择模态从哪个方向进入 window。我也 created a StackBlitz 只有最低限度。
目前我的 EnterLeaveAnimation
看起来像这样:
export const EnterLeaveAnimation =
trigger('enterLeave', [
transition(
':enter', [
style({ top: '-50%' }), // <-- I should be able to change this dynamically, eg: left: '-50%'
animate('{{ duration }} ease-in-out', style({ top: 0 })),
], {
params: {
duration: '500ms'
}
}
),
transition(
':leave', [
animate('{{ duration }} ease-in-out', style({ top: '-50%' }))
], {
params: {
duration: '500ms'
}
}
),
]);
ATM 这个动画应用到 div 像这样:
<div class="modal d-block" [@fadeInOut] [@enterLeave] *ngIf="isOpen">
<!-- [fromDirection]="fromDirection" -->
...
</div>
<div [@fadeInOut] *ngIf="isOpen">
<div class="modal-backdrop fade" [class.show]="isOpen"></div>
</div>
但最终会寻找 like this:
<div class="modal d-block" [@fadeInOut] [@enterLeave]="{ value: isOpen ? ':enter' : ':leave', params: { fromDirection: fromDirection } }" *ngIf="isOpen">
...
</div>
<div [@fadeInOut] *ngIf="isOpen">
<div class="modal-backdrop fade" [class.show]="isOpen"></div>
</div>
我现在遇到的问题是,我不知道如何在 fromDirection
上将我的 EnterLeaveAnimation
修改为 switch
并相应地应用不同的样式规则:
style({ top: '-50%' })
OR
style({ bottom: '-50%' })
OR
style({ left: '-50%' })
OR
style({ right: '-50%' })
如您所见,我已经将我的 duration
参数传递给动画,但我如何 switch
参数并相应地使用 style
函数?
恐怕你应该“手动”制作动画
别担心,这很简单,看这个 一个简单的例子
有了这个想法,我们可以在你的主机组件中定义一些像
animate(element: any, state: string, background: boolean) {
if (element) {
let customstyle =
state == 'enter'
? background
? { opacity: 0 }
: { top: '-50%', left: '0', opacity: 0 }
: background
? { opacity: 1 }
: { top: '-100%', left: '0', opacity: 1 };
if (!background) {
switch (this.fromDirection) {
case 'bottom':
customstyle =
state == 'enter'
? { top: '50%', left: '0', opacity: 0 }
: { top: '100%', left: '0', opacity: 0 };
break;
case 'left':
customstyle =
state == 'enter'
? { top: '0', left: '-100%', opacity: 0 }
: { top: '0', left: '-100%', opacity: 0 };
break;
case 'right':
customstyle =
state == 'enter'
? { top: '0', left: '100%', opacity: 0 }
: { top: '0', left: '100%', opacity: 0 };
break;
}
}
const myAnimation =
state == 'enter'
? this.builder.build([
style(customstyle),
animate(this.timing, style({ top: 0, left: 0, opacity: 1 })),
])
: this.builder.build([animate(this.timing, style(customstyle))]);
this.player = myAnimation.create(element);
if (state == 'leave') {
this.player.onDone(() => {
this.componentInstance.instance.isOpen = false;
});
}
this.player.play();
}
}
您还在宿主组件中定义了一个函数 close
close() {
this.isOpen = false;
this.animate(
(this.componentInstance.instance as any).modal.nativeElement,
'leave',
false
);
this.animate(
(this.componentInstance.instance as any).modalBackground.nativeElement,
'leave',
true
);
}
并使用getter调用动画
@Input() set isOpen(value: boolean) {
this._isOpen = value;
if (this.componentInstance) {
if (value) {
this.componentInstance.instance.isOpen = value;
this.animate(
(this.componentInstance.instance as any).modal.nativeElement,
'enter',
false
);
this.animate(
(this.componentInstance.instance as any).modalBackground
.nativeElement,
'enter',
true
);
} else {
this.animate(
(this.componentInstance.instance as any).template.nativeElement,
'leave',
false
);
this.animate(
(this.componentInstance.instance as any).modalBackground
.nativeElement,
'leave',
true
);
}
}
this.isOpenChange.emit(value);
}
如您所见,动画“重新放置”您的动画,但我们可以不使用*ngIf
到show/hide其他模式[ngClass]
在路上
<!---modal.component.html-->
<div #modal [ngClass]="isOpen?'modal d-block':'modal d-none'" class='modal d-block'>
<div class="modal-dialog">
<div class="modal-content">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
</div>
</div>
<div #modalBackground [ngClass]="isOpen?'d-block':'d-none'">
<div class="modal-backdrop fade" [class.show]="isOpen"></div>
</div>
看你怎么用模板引用变量来获取背景和内容,所以我们需要用到ViewChild
@ViewChild('modal') modal:ElementRef
@ViewChild('modalBackground') modalBackground:ElementRef
注意:在 stackblitz 我对“时间”进行了硬编码,您可以使用 @Input 或其他方式。
我已经为 angular 创建了一个 bootstrap 模态组件,但我想选择模态从哪个方向进入 window。我也 created a StackBlitz 只有最低限度。
目前我的 EnterLeaveAnimation
看起来像这样:
export const EnterLeaveAnimation =
trigger('enterLeave', [
transition(
':enter', [
style({ top: '-50%' }), // <-- I should be able to change this dynamically, eg: left: '-50%'
animate('{{ duration }} ease-in-out', style({ top: 0 })),
], {
params: {
duration: '500ms'
}
}
),
transition(
':leave', [
animate('{{ duration }} ease-in-out', style({ top: '-50%' }))
], {
params: {
duration: '500ms'
}
}
),
]);
ATM 这个动画应用到 div 像这样:
<div class="modal d-block" [@fadeInOut] [@enterLeave] *ngIf="isOpen">
<!-- [fromDirection]="fromDirection" -->
...
</div>
<div [@fadeInOut] *ngIf="isOpen">
<div class="modal-backdrop fade" [class.show]="isOpen"></div>
</div>
但最终会寻找 like this:
<div class="modal d-block" [@fadeInOut] [@enterLeave]="{ value: isOpen ? ':enter' : ':leave', params: { fromDirection: fromDirection } }" *ngIf="isOpen">
...
</div>
<div [@fadeInOut] *ngIf="isOpen">
<div class="modal-backdrop fade" [class.show]="isOpen"></div>
</div>
我现在遇到的问题是,我不知道如何在 fromDirection
上将我的 EnterLeaveAnimation
修改为 switch
并相应地应用不同的样式规则:
style({ top: '-50%' })
OR
style({ bottom: '-50%' })
OR
style({ left: '-50%' })
OR
style({ right: '-50%' })
如您所见,我已经将我的 duration
参数传递给动画,但我如何 switch
参数并相应地使用 style
函数?
恐怕你应该“手动”制作动画
别担心,这很简单,看这个
有了这个想法,我们可以在你的主机组件中定义一些像
animate(element: any, state: string, background: boolean) {
if (element) {
let customstyle =
state == 'enter'
? background
? { opacity: 0 }
: { top: '-50%', left: '0', opacity: 0 }
: background
? { opacity: 1 }
: { top: '-100%', left: '0', opacity: 1 };
if (!background) {
switch (this.fromDirection) {
case 'bottom':
customstyle =
state == 'enter'
? { top: '50%', left: '0', opacity: 0 }
: { top: '100%', left: '0', opacity: 0 };
break;
case 'left':
customstyle =
state == 'enter'
? { top: '0', left: '-100%', opacity: 0 }
: { top: '0', left: '-100%', opacity: 0 };
break;
case 'right':
customstyle =
state == 'enter'
? { top: '0', left: '100%', opacity: 0 }
: { top: '0', left: '100%', opacity: 0 };
break;
}
}
const myAnimation =
state == 'enter'
? this.builder.build([
style(customstyle),
animate(this.timing, style({ top: 0, left: 0, opacity: 1 })),
])
: this.builder.build([animate(this.timing, style(customstyle))]);
this.player = myAnimation.create(element);
if (state == 'leave') {
this.player.onDone(() => {
this.componentInstance.instance.isOpen = false;
});
}
this.player.play();
}
}
您还在宿主组件中定义了一个函数 close
close() {
this.isOpen = false;
this.animate(
(this.componentInstance.instance as any).modal.nativeElement,
'leave',
false
);
this.animate(
(this.componentInstance.instance as any).modalBackground.nativeElement,
'leave',
true
);
}
并使用getter调用动画
@Input() set isOpen(value: boolean) {
this._isOpen = value;
if (this.componentInstance) {
if (value) {
this.componentInstance.instance.isOpen = value;
this.animate(
(this.componentInstance.instance as any).modal.nativeElement,
'enter',
false
);
this.animate(
(this.componentInstance.instance as any).modalBackground
.nativeElement,
'enter',
true
);
} else {
this.animate(
(this.componentInstance.instance as any).template.nativeElement,
'leave',
false
);
this.animate(
(this.componentInstance.instance as any).modalBackground
.nativeElement,
'leave',
true
);
}
}
this.isOpenChange.emit(value);
}
如您所见,动画“重新放置”您的动画,但我们可以不使用*ngIf
到show/hide其他模式[ngClass]
在路上
<!---modal.component.html-->
<div #modal [ngClass]="isOpen?'modal d-block':'modal d-none'" class='modal d-block'>
<div class="modal-dialog">
<div class="modal-content">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
</div>
</div>
<div #modalBackground [ngClass]="isOpen?'d-block':'d-none'">
<div class="modal-backdrop fade" [class.show]="isOpen"></div>
</div>
看你怎么用模板引用变量来获取背景和内容,所以我们需要用到ViewChild
@ViewChild('modal') modal:ElementRef
@ViewChild('modalBackground') modalBackground:ElementRef
注意:在 stackblitz 我对“时间”进行了硬编码,您可以使用 @Input 或其他方式。