@angular/animations: v4.4.6
我的目标是使用AnimationBuilder
创建一个简单的水平打开和关闭动画。除了动画元素的宽度变得固定之外,我大部分时间都在工作。使用触发器实现相同的动画效果如预期,并且宽度对不同的视口(viewport)尺寸保持响应。
我有一个运行示例 here .
如您所见,如果您调整视口(viewport)的宽度,由 AnimationBuilder
设置动画的 div 的宽度不会相应调整。但是使用动画触发器的 div 的宽度会。
如何使用 AnimationBuilder
才能获得与使用触发器完全相同的结果?
您可以在上面的链接中查看和编辑代码,但我将其复制在下面以供引用:
应用程序组件.ts
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { trigger, state, style, transition, animate, AnimationBuilder, AnimationPlayer } from '@angular/animations';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
animations: [
trigger('collapse', [
state('open', style({ width: '*' })),
state('close', style({ width: 0 })),
transition('open => close', [
style({ width: '*' }),
animate(200, style({ width: 0 }))
]),
transition('close => open', [
style({ width: 0 }),
animate(200, style({ width: '*' }))
])
])
]
})
export class AppComponent implements AfterViewInit {
isOpen = true;
get collapseState() {
return this.isOpen ? 'open' : 'close';
}
@ViewChild('withBuilder') elementRef: ElementRef;
private openPlayer: AnimationPlayer;
private closePlayer: AnimationPlayer;
constructor(private animationBuilder: AnimationBuilder) { }
ngAfterViewInit() {
this.openPlayer = this.animationBuilder
.build([
style({ width: 0 }),
animate(200, style({ width: '*' }))
])
.create(this.elementRef.nativeElement);
this.closePlayer = this.animationBuilder
.build([
style({ width: '*' }),
animate(200, style({ width: 0 }))
])
.create(this.elementRef.nativeElement);
if (this.isOpen) {
this.openPlayer.finish();
} else {
this.closePlayer.finish();
}
}
toggle() {
if (this.isOpen) {
this.closePlayer.play();
this.openPlayer.reset();
} else {
this.openPlayer.play();
this.closePlayer.reset();
}
this.isOpen = !this.isOpen;
}
}
app.component.html
<button (click)="toggle()">Toggle</button>
<h2>Without AnimationBuilder:</h2>
<div class="container" [@collapse]="collapseState"></div>
<h2>With AnimationBuilder:</h2>
<div class="container" #withBuilder></div>
应用程序组件.css
.container {
border: 2px solid red;
height: 200px;
}
最佳答案
AnimationBuilder
使用不处理元素状态的 TimelineAnimationEngine
。全宽大小由仍在工作的动画播放器固定。
如您所见,注释中的折叠触发器删除了动画播放器并添加了 style="width: 0px"。
这是一个直接处理元素状态的可行解决方案。但它看起来很脏。并且它不处理改变方向的情况(当上一个动画还在播放时)
@ViewChild('withBuilder') elementRef: ElementRef;
isOpen = true;
private closeAnimation: AnimationFactory;
private openAnimation: AnimationFactory;
constructor(private styler: StylerComponent,
private animationBuilder: AnimationBuilder,
private renderer: Renderer2) {
this.openAnimation = this.animationBuilder
.build([
style({width: 0}),
animate(200, style({width: '*'})),
]);
this.closeAnimation = this.animationBuilder
.build([
style({width: '*'}),
animate(200, style({width: 0})),
]);
}
toggle() {
console.log('toggle', this.isOpen);
const el = this.elementRef.nativeElement;
let player: AnimationPlayer;
if (this.isOpen) {
player = this.closeAnimation.create(el);
player.onDone(() => {
this.renderer.setStyle(el, 'width', 0);
});
} else {
this.renderer.removeStyle(el, 'width');
player = this.openAnimation.create(el);
}
player.onDone(() => {
player.destroy();
});
player.play();
this.isOpen = !this.isOpen;
}
关于javascript - 使用 Angular (v4) AnimationBuilder 使宽度无响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46943225/