问题
I am creating a paging component that slides to next or previous fullscreen page. Because issues with different browsers and devices I have abandoned just using CSS transitions for now. I have a working angular animate solution but the new problem is that it doesn't scale.
import { Component } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
trigger('slideTransition', [
state('firstPage', style({ transform: 'translateX(0)' })),
state('secondPage', style({ transform: 'translateX(-100%)' })),
transition('firstPage=>secondPage', animate('0.6s ease')),
transition('secondPage=>firstPage', animate('0.6s ease'))
])]
})
export class AppComponent {
state = 'firstPage';
nextPage() {
this.state = 'secondPage';
}
previousPage() {
this.state = 'firstShowing';
}
}
The problem is, as you see, when I have for example 9 pages. I do not want to define 9 states and 18 transitions. How can I do reusable states or generate the states and transitions runtime based on the number of pages? Any ideas?
The template would look something like this
<div class="container">
<div [@slideTransition]="state" class="page">
<h1>Page 1</h1>
<div class="clicker" (click)="nextPage()">clickity</div>
</div>
<div [@slideTransition]="state" class="page">
<h1>Page 2</h1>
<div class="clicker" (click)="previousPage()">clackity</div>
</div>
</div>
回答1:
What you need is sending params
to the state. This is possible by adding a class member and keep updating it depending on your page number. Then wire that in your HTML.
Now the following is potential additions to your existing code:
animations: [
trigger('slideTransition', [
// ...
state('*',
style({ marginLeft: '{{pageMarginValue}}%' }),
{params: {pageMarginValue: 0}}),
transition('*=>*', animate('0.6s ease')),
// ...
])
]
Then add this to your class:
export class AppComponent {
// ...
private currentMargin = 0;
private step = 10; // replace with actual value
next(): void { this.currentMargin += this.step; }
previous(): void { this.currentMargin -= this.step; }
// ...
}
In your HTML, pass the currentMargin
like so:
<div [@slideTransition]="{value: state, params: { pageMarginValue: currentMargin }}"></div>
回答2:
I have now found a possible solution. Though because I am using margin-left for the transition the performance isn't as good as it should be.
import { Component } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
trigger('slideTransition', [
state('previous', style({ marginLeft: '-100%', display: 'none' })),
state('current', style({ marginLeft: '0' })),
state('next', style({ display: 'none' })),
transition('current=>previous', animate('0.6s ease')),
transition('current=>next', animate('0.6s ease')),
transition('next=>current', animate('0.6s ease')),
transition('previous=>current', animate('0.6s ease'))
])
]
})
export class AppComponent {
state = ['current', 'next', 'next'];
current = 0;
next() {
this.current = this.current + 1;
this.updateState();
}
previous() {
this.current = this.current - 1;
this.updateState();
}
private updateState() {
for (let i = 0; i < this.state.length; i++) {
if (i < this.current) {
this.state[i] = 'previous';
} else if (i === this.current) {
this.state[i] = 'current';
} else {
this.state[i] = 'next';
}
}
}
}
and the template
<div class="the-host">
<div [@slideTransition]="state[0]" class="fullscreen first">
<h1>Page 1</h1>
<div class="clicker" (click)="next()">next</div>
</div>
<div [@slideTransition]="state[1]" class="fullscreen second">
<h1>Page 2</h1>
<div class="clicker" (click)="previous()">previous</div>
<div class="clicker" (click)="next()">next</div>
</div>
<div [@slideTransition]="state[2]" class="fullscreen third">
<h1>Page 3</h1>
<div class="clicker" (click)="previous()">previous</div>
</div>
</div>
来源:https://stackoverflow.com/questions/44323258/dynamically-create-angular-animations