I want to use this simple animation:
animations: [
trigger('flyInOut', [
state('in', style({ transform: 'translateX(0)' })),
transition('void => *', [
style({ transform: 'translateX(100)' }),
animate(1000)
]),
transition('* => void', [
animate(1000, style({ transform: 'translateX(-100)' }))
])
])
]
I try to setup it in a component which is rendered on the default route and the animation doesn't fire. Transition'void => *' doesn't work on the first load.
@flyInOut.start and @flyInOut.done events occur properly, but animation is not visible in the view. And animated element remains in transform: 'translateX(100)' state.
The problem occurs only on Android.
"dependencies": {
"@angular/animations": "~6.1.0",
"@angular/common": "~6.1.0",
"@angular/compiler": "~6.1.0",
"@angular/core": "~6.1.0",
"@angular/forms": "~6.1.0",
"@angular/http": "~6.1.0",
"@angular/platform-browser": "~6.1.0",
"@angular/platform-browser-dynamic": "~6.1.0",
"@angular/router": "~6.1.0",
"nativescript-angular": "^6.1.0",
"nativescript-theme-core": "~1.0.4",
"reflect-metadata": "~0.1.10",
"rxjs": "^6.0.0",
"tns-core-modules": "^4.2.0",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular/compiler-cli": "~6.1.0",
"@ngtools/webpack": "~6.2.0",
"@types/chai": "~4.1.3",
"@types/mocha": "~5.2.1",
"@types/node": "^7.0.5",
"babel-traverse": "6.25.0",
"babel-types": "6.25.0",
"babylon": "6.17.4",
"lazy": "1.0.11",
"nativescript-css-loader": "~0.26.0",
"nativescript-dev-appium": "next",
"nativescript-dev-typescript": "^0.7.3",
"nativescript-dev-webpack": "^0.16.0",
"typescript": "~2.7.2"
},
Launch playground app on android device.
possibly related to using wildcard issue
Is there a workaround to this?
I tried using an explicit state instead of * and still doesn't work:
animations: [
trigger('brandsflyIn', [
state("in", style({ transform: "translateX(0)" })),
transition('void => in', [
style({ transform: 'translateX(500)' }),
animate('500ms 500ms ease-in', style({ transform: 'translateX(0)' }))
]),
]),
]
<FlexboxLayout height="54" flexDirection="row" justifyContent="flex-start"
alignItems="stretch" flexWrap="nowrap">
<GridLayout [@brandsflyIn]="'in'" height="54" class="small-card round-border"
backgroundColor="#F2F2F2"
*ngFor="let brand of ['adidas','nike','newbalance','ua','fila','lacoste','sketchers','jordan','levis']; let i = index">
<Label text="{{brand}}"></Label>
</GridLayout>
</FlexboxLayout>
Full playground here
I have the same issue. It just doesn't work on the first page.
@rynop a simple solution is to set a *ngIf and make the element visible after a few milliseconds using setTimeout.
Thanks that worked, but man that is a bummer to have to manage state for every animation on page load.
@NickIliev is your gut feel that this is a hard fix? Or is this just low priority..
@vahidvdn actually I lied, I didn't get it working. It works on 2nd page load (like HMR refresh) but I can't get it to work on 1st page load (ex: when app 1st opens). Do you have a working example you can point me to?
Here is what I'm doing:
<ScrollView height="54" orientation="horizontal">
<FlexboxLayout *ngIf="startLoadAnimations" height="54" flexDirection="row" justifyContent="flex-start"
alignItems="stretch" flexWrap="nowrap">
<GridLayout [@brandsflyIn]="'in'" height="54" class="small-card round-border" backgroundColor="#F2F2F2"
*ngFor="let brand of ['adidas','nike','newbalance','ua','fila','lacoste','sketchers','jordan','levis']; let i = index">
<Image horizontalAlignment="center" verticalAlignment="center" src="~/images/brands/{{brand}}.png"></Image>
</GridLayout>
</FlexboxLayout>
</ScrollView>
...
animations: [
trigger('brandsflyIn', [
transition('void => *', [
style({ transform: 'translateX(500)' }),
animate('500ms 400ms ease-in', style({ transform: 'translateX(0)' }))
]),
]),
]
...
export class HomeComponent implements OnInit, AfterViewInit {
startLoadAnimations = false;
...
ngAfterViewInit(): void {
setTimeout(() => {
this.startLoadAnimations = true;
}, 10);
}
...
@rynop You are right. For me, it didn't work in some cases. I can't figure out what is going on.
While I'm not crazy about it, I "think" I have a workaround. Would be grateful if you could test on your side @vahidvdn and see if it works for you. In short I don't use void or *, manually set state and manually change state after a timeout in ngAfterViewInit().
<FlexboxLayout height="54" flexDirection="row" justifyContent="flex-start" alignItems="stretch"
flexWrap="nowrap">
<GridLayout [@test]="startLoadAnimations?'in':'init'" *ngFor="let club of byClub; let i = index"
height="54" class="small-card round-border" [background]="club.background">
<Image horizontalAlignment="center" verticalAlignment="center" [src]="club.src">
</Image>
</GridLayout>
</FlexboxLayout>
...
animations: [
trigger('test', [
state('init', style({
opacity: 0,
transform: 'translateX(500)'
})),
state('in', style({
opacity: 1,
transform: 'translateX(0)'
})),
transition('init => in', [
animate('1s ease-in')
]),
])
]
...
export class HomeComponent implements OnInit, AfterViewInit {
startLoadAnimations = false;
...
ngAfterViewInit(): void {
setTimeout(() => {
this.startLoadAnimations = true;
}, 500);
}
...
Def not ideal, but I think its working..