如何用Animations系统制作reinitialize/retrigger个动画?
How to reinitialize/retrigger animations made with Animations system?
我是 @angular/animations
的新手,现在我遇到了一些事情。我有一个简单的列表,当你 select 一个项目时它显示一个子列表,两个列表有相同的动画,但是如果 select 第一个列表中的不同项目第二个列表不会再次动画.我已经尝试将第二个列表分配给 null
然后给出新值,认为这足以让动画再次触发。
我正在使用的解决方法是 setTimeout
在分配新值之前等待 100 毫秒,它工作正常,但屏幕闪烁,这是我的代码:
我的 COMPONENT.HTML:
<ion-list>
<!-- FIRST LIST -->
<ion-item-group>
<ion-item-divider color="light">By Animal</ion-item-divider>
<ion-item [@listAnimation]="services.length" class="scrollable-x">
<ion-avatar *ngFor="let serv of services" item-start (tap)="setSelectedType(serv)">
<img src="/path/to/image.png">
<p>{{serv.type}}</p>
</ion-avatar>
</ion-item>
</ion-item-group>
<!-- SECOND LIST: DYNAMIC LIST -->
<ion-item-group *ngIf="selectedType">
<ion-item-divider color="light">Services: {{selectedType}}</ion-item-divider>
<ion-item [@listAnimation]="selectedTypeServices.length" class="scrollable-x">
<ion-avatar *ngFor="let serv of selectedTypeServices" item-start>
<img src="/path/to/image.png">
<p>{{serv.name}}</p>
</ion-avatar>
</ion-item>
</ion-item-group>
</ion-list>
我的 COMPONENT.TS:
import { IonicPage, NavController, NavParams } from "ionic-angular";
import { trigger, style, transition, animate, keyframes, query, stagger } from "@angular/animations";
@IonicPage()
@Component({
selector: "page-agendar",
templateUrl: "agendar.html",
animations: [
trigger("listAnimation", [
transition("* => *", [
query(":enter", style({ opacity: 0 }), { optional: true }),
query(
":enter",
stagger("300ms", [
animate(
".7s ease-in",
keyframes([
style({ opacity: 0, transform: "translateX(-75%)", offset: 0 }),
style({
opacity: 0.5,
transform: "translateX(25px)",
offset: 0.3
}),
style({ opacity: 1, transform: "translateY(0)", offset: 1.0 })
])
)
]),
{ optional: true }
)
])
])
]
})
export class AgendarPage {
public services: Array<{ type: string; services: Array<{ name: string }>}> = [];
public selectedType: string;
public selectedTypeServices: any[];
constructor(){}
setSelectedType = service => {
this.selectedType = null;
setTimeout(() => {
this.selectedTypeServices = service.services;
this.selectedType = service.type;
}, 100);
};
}
那么有没有办法重新初始化或重新触发动画呢?也许我缺少某些选项,trigger()
以外的其他功能或类似的功能?
我认为您的动画不是 "retriggering" 的主要原因是您对 angular 动画的状态配置。 angular中有两种处理动画的方法:
1.) 状态方法
trigger('cube', [
state('front', style({
transform: 'rotateX(0deg)',
})))
2.) 过渡方法
trigger(
'myAnimation',
[
transition(
':enter', [
style({transform: 'translateY(-100%)', opacity: 0}),
animate('500ms', style({transform: 'translateY(0)', 'opacity': 1}))
]
))
您似乎将两者混为一谈,我相信这就是您的问题所在。
如果您为 html 使用 State 方法,您可以这样说:
HTML
<div [@cube]="state">
打字稿
trigger('cube', [
// States that can occur from viewing the front panel
state('front', style({
transform: 'rotateX(0deg)',
})),
state('bottom', style({
transform: 'rotateX(90deg) translateY(-50vh) translateZ(50vh)',
}))
// Front animations when landing on page
transition('front => bottom', animate('1500ms ease-in-out')),
transition('bottom => front', animate('1500ms ease-in-out'))
])
例如,您可以将 ngOnInit() 的状态初始化为底部或前面,然后打开点击或类似的东西。请注意,动画的发生是因为元素正在变化 "states" 并且该变量正在指示变化。
如果您选择转换方法,您将得到如下内容:
HTML
<div *ngIf="hasUpload=='yes'" [@myAnimation]>
打字稿
trigger(
'myAnimation',
[
transition(
':enter', [
style({transform: 'translateY(-100%)', opacity: 0}),
animate('500ms', style({transform: 'translateY(0)', 'opacity': 1}))
]
),
transition(
':leave', [
style({transform: 'translateY(0)', 'opacity': 1}),
animate('500ms', style({transform: 'translateY(-100%)', 'opacity': 0})),
]
)]
)
请注意,这里的区别在于动画是根据元素是否显示而发生的。所以 ngIf 语句中的变量决定了动画是否会发生。
当您使用 [@listAnimation]="services.length"
时,据我所知,services.length 是无用的,因为您使用的是过渡方法而不是状态。我相信你想做的事情可以通过使用状态方法来完成,并根据你列表中的服务被点击来改变状态。然后切换状态,动画就会出现。你基本上已经在超时时这样做了,这就是它在某种程度上起作用的原因。因此,与其使用超时,不如使用三元运算来翻转状态,这样你就可以开始了。希望能消除一些歧义!祝你好运! :D
我是 @angular/animations
的新手,现在我遇到了一些事情。我有一个简单的列表,当你 select 一个项目时它显示一个子列表,两个列表有相同的动画,但是如果 select 第一个列表中的不同项目第二个列表不会再次动画.我已经尝试将第二个列表分配给 null
然后给出新值,认为这足以让动画再次触发。
我正在使用的解决方法是 setTimeout
在分配新值之前等待 100 毫秒,它工作正常,但屏幕闪烁,这是我的代码:
我的 COMPONENT.HTML:
<ion-list>
<!-- FIRST LIST -->
<ion-item-group>
<ion-item-divider color="light">By Animal</ion-item-divider>
<ion-item [@listAnimation]="services.length" class="scrollable-x">
<ion-avatar *ngFor="let serv of services" item-start (tap)="setSelectedType(serv)">
<img src="/path/to/image.png">
<p>{{serv.type}}</p>
</ion-avatar>
</ion-item>
</ion-item-group>
<!-- SECOND LIST: DYNAMIC LIST -->
<ion-item-group *ngIf="selectedType">
<ion-item-divider color="light">Services: {{selectedType}}</ion-item-divider>
<ion-item [@listAnimation]="selectedTypeServices.length" class="scrollable-x">
<ion-avatar *ngFor="let serv of selectedTypeServices" item-start>
<img src="/path/to/image.png">
<p>{{serv.name}}</p>
</ion-avatar>
</ion-item>
</ion-item-group>
</ion-list>
我的 COMPONENT.TS:
import { IonicPage, NavController, NavParams } from "ionic-angular";
import { trigger, style, transition, animate, keyframes, query, stagger } from "@angular/animations";
@IonicPage()
@Component({
selector: "page-agendar",
templateUrl: "agendar.html",
animations: [
trigger("listAnimation", [
transition("* => *", [
query(":enter", style({ opacity: 0 }), { optional: true }),
query(
":enter",
stagger("300ms", [
animate(
".7s ease-in",
keyframes([
style({ opacity: 0, transform: "translateX(-75%)", offset: 0 }),
style({
opacity: 0.5,
transform: "translateX(25px)",
offset: 0.3
}),
style({ opacity: 1, transform: "translateY(0)", offset: 1.0 })
])
)
]),
{ optional: true }
)
])
])
]
})
export class AgendarPage {
public services: Array<{ type: string; services: Array<{ name: string }>}> = [];
public selectedType: string;
public selectedTypeServices: any[];
constructor(){}
setSelectedType = service => {
this.selectedType = null;
setTimeout(() => {
this.selectedTypeServices = service.services;
this.selectedType = service.type;
}, 100);
};
}
那么有没有办法重新初始化或重新触发动画呢?也许我缺少某些选项,trigger()
以外的其他功能或类似的功能?
我认为您的动画不是 "retriggering" 的主要原因是您对 angular 动画的状态配置。 angular中有两种处理动画的方法:
1.) 状态方法
trigger('cube', [
state('front', style({
transform: 'rotateX(0deg)',
})))
2.) 过渡方法
trigger(
'myAnimation',
[
transition(
':enter', [
style({transform: 'translateY(-100%)', opacity: 0}),
animate('500ms', style({transform: 'translateY(0)', 'opacity': 1}))
]
))
您似乎将两者混为一谈,我相信这就是您的问题所在。
如果您为 html 使用 State 方法,您可以这样说:
HTML
<div [@cube]="state">
打字稿
trigger('cube', [
// States that can occur from viewing the front panel
state('front', style({
transform: 'rotateX(0deg)',
})),
state('bottom', style({
transform: 'rotateX(90deg) translateY(-50vh) translateZ(50vh)',
}))
// Front animations when landing on page
transition('front => bottom', animate('1500ms ease-in-out')),
transition('bottom => front', animate('1500ms ease-in-out'))
])
例如,您可以将 ngOnInit() 的状态初始化为底部或前面,然后打开点击或类似的东西。请注意,动画的发生是因为元素正在变化 "states" 并且该变量正在指示变化。
如果您选择转换方法,您将得到如下内容:
HTML
<div *ngIf="hasUpload=='yes'" [@myAnimation]>
打字稿
trigger(
'myAnimation',
[
transition(
':enter', [
style({transform: 'translateY(-100%)', opacity: 0}),
animate('500ms', style({transform: 'translateY(0)', 'opacity': 1}))
]
),
transition(
':leave', [
style({transform: 'translateY(0)', 'opacity': 1}),
animate('500ms', style({transform: 'translateY(-100%)', 'opacity': 0})),
]
)]
)
请注意,这里的区别在于动画是根据元素是否显示而发生的。所以 ngIf 语句中的变量决定了动画是否会发生。
当您使用 [@listAnimation]="services.length"
时,据我所知,services.length 是无用的,因为您使用的是过渡方法而不是状态。我相信你想做的事情可以通过使用状态方法来完成,并根据你列表中的服务被点击来改变状态。然后切换状态,动画就会出现。你基本上已经在超时时这样做了,这就是它在某种程度上起作用的原因。因此,与其使用超时,不如使用三元运算来翻转状态,这样你就可以开始了。希望能消除一些歧义!祝你好运! :D