Angular CDK:将动画应用到 Angular 步进变化的自定义步进器
Angular CDK: Apply animations to Angular custom stepper on step change
我坚持使用 CDK 为 Angular material 自定义步进器的步进动画设置动画。
我已经按照 tutorial 了解如何实现自定义步进器。
我有演示here
我的模板如下:
<section class="container">
<header>
<h2>Step {{selectedIndex + 1}}/{{steps.length}}</h2>
<div>
<button class="pure-button" cdkStepperPrevious>←</button>
<button
class="pure-button"
*ngFor="let step of steps; let i = index;"
[ngClass]="{'pure-button-primary': selectedIndex === i}"
(click)="onClick(i)"
>
Step {{i + 1}}
</button>
<button class="pure-button" cdkStepperNext>→</button>
</div>
</header>
<div [@stepTransition]="_getAnimationDirection(current)" *ngFor="let step of _steps; let i = index">
<div [ngTemplateOutlet]="selected.content"></div>
</div>
</section>
我的组件 TS 文件如下所示:
import { Component, OnInit } from '@angular/core';
import { CdkStepper } from '@angular/cdk/stepper';
import {
trigger,
state,
style,
animate,
transition,
} from '@angular/animations';
@Component({
selector: 'app-my-stepper',
templateUrl: './my-stepper.component.html',
styleUrls: ['./my-stepper.component.css'],
providers: [{ provide: CdkStepper, useExisting: MyStepperComponent }],
animations: [trigger('stepTransition', [
state('previous', style({transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden'})),
state('current', style({transform: 'none', visibility: 'visible'})),
state('next', style({transform: 'translate3d(100%, 0, 0)', visibility: 'hidden'})),
transition('* => *', animate('500ms cubic-bezier(0.35, 0, 0.25, 1)'))
])]
})
export class MyStepperComponent extends CdkStepper implements OnInit {
current = 0;
onClick(index: number): void {
this.current = index;
this.selectedIndex = index;
}
ngOnInit() {
console.log(this._getFocusIndex())
}
}
动画只对最后一步有效,原因是点击时动画状态(previous, current, next)value没有改变。
我怎样才能做到这一点?非常感谢任何想法,谢谢。
更新
检查 stackblitz 存储库以获取最新代码
在你的 stackblitz demo 中你有以下 html:
<div *ngFor="let step of _steps; let i = index"
[@stepTransition]="_getAnimationDirection(i)"
[attr.tabindex]="selectedIndex === i ? 0 : null"
[id]="_getStepContentId(i)"
(@stepTransition.done)="_animationDone.next($event)"
[attr.aria-labelledby]="_getStepLabelId(i)"
[attr.aria-expanded]="selectedIndex === i">
<ng-container [ngTemplateOutlet]="selected.content">
</ng-container>
</div>
我认为这里的主要问题在于这一行:<div [ngTemplateOutlet]="selected.content"></div>
您为每个 step
创建一个 div
,每个 div
将包含相同的 selected.content
。因此,所有应用于父 div
(transform
和 visibility
)的样式也将应用于 selected.content
,这将导致不明确的行为。
如果将其替换为 <div [ngTemplateOutlet]="step.content"></div>
,您将开始看到所有图像,但它们会一个接一个地放置。
发生这种情况是因为 css visibility 属性:
it shows or hides an element without changing the layout of a
document.
所以我建议您将 position: absolute;
添加到您的步骤中。
看看 stackblitz 的这些改进
我坚持使用 CDK 为 Angular material 自定义步进器的步进动画设置动画。 我已经按照 tutorial 了解如何实现自定义步进器。
我有演示here
我的模板如下:
<section class="container">
<header>
<h2>Step {{selectedIndex + 1}}/{{steps.length}}</h2>
<div>
<button class="pure-button" cdkStepperPrevious>←</button>
<button
class="pure-button"
*ngFor="let step of steps; let i = index;"
[ngClass]="{'pure-button-primary': selectedIndex === i}"
(click)="onClick(i)"
>
Step {{i + 1}}
</button>
<button class="pure-button" cdkStepperNext>→</button>
</div>
</header>
<div [@stepTransition]="_getAnimationDirection(current)" *ngFor="let step of _steps; let i = index">
<div [ngTemplateOutlet]="selected.content"></div>
</div>
</section>
我的组件 TS 文件如下所示:
import { Component, OnInit } from '@angular/core';
import { CdkStepper } from '@angular/cdk/stepper';
import {
trigger,
state,
style,
animate,
transition,
} from '@angular/animations';
@Component({
selector: 'app-my-stepper',
templateUrl: './my-stepper.component.html',
styleUrls: ['./my-stepper.component.css'],
providers: [{ provide: CdkStepper, useExisting: MyStepperComponent }],
animations: [trigger('stepTransition', [
state('previous', style({transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden'})),
state('current', style({transform: 'none', visibility: 'visible'})),
state('next', style({transform: 'translate3d(100%, 0, 0)', visibility: 'hidden'})),
transition('* => *', animate('500ms cubic-bezier(0.35, 0, 0.25, 1)'))
])]
})
export class MyStepperComponent extends CdkStepper implements OnInit {
current = 0;
onClick(index: number): void {
this.current = index;
this.selectedIndex = index;
}
ngOnInit() {
console.log(this._getFocusIndex())
}
}
动画只对最后一步有效,原因是点击时动画状态(previous, current, next)value没有改变。
我怎样才能做到这一点?非常感谢任何想法,谢谢。
更新 检查 stackblitz 存储库以获取最新代码
在你的 stackblitz demo 中你有以下 html:
<div *ngFor="let step of _steps; let i = index"
[@stepTransition]="_getAnimationDirection(i)"
[attr.tabindex]="selectedIndex === i ? 0 : null"
[id]="_getStepContentId(i)"
(@stepTransition.done)="_animationDone.next($event)"
[attr.aria-labelledby]="_getStepLabelId(i)"
[attr.aria-expanded]="selectedIndex === i">
<ng-container [ngTemplateOutlet]="selected.content">
</ng-container>
</div>
我认为这里的主要问题在于这一行:<div [ngTemplateOutlet]="selected.content"></div>
您为每个 step
创建一个 div
,每个 div
将包含相同的 selected.content
。因此,所有应用于父 div
(transform
和 visibility
)的样式也将应用于 selected.content
,这将导致不明确的行为。
如果将其替换为 <div [ngTemplateOutlet]="step.content"></div>
,您将开始看到所有图像,但它们会一个接一个地放置。
发生这种情况是因为 css visibility 属性:
it shows or hides an element without changing the layout of a document.
所以我建议您将 position: absolute;
添加到您的步骤中。
看看 stackblitz 的这些改进