我成功获得了一个面板,可以在进入和离开DOM时动画扩展和关闭。问题是我现在在显示详细信息之前在面板内有一个忙碌指示器,并且仅在打开忙指示符时发生动画,并在显示详细内容时捕捉。
如何让Angular动画在任何高度变化时设置动画?
我在这里有一个例子:https://plnkr.co/edit/Bs0rwp4ElidR75zN3ulR
trigger('expandCollapseDetails', [
state('void', style({
'height': '0px',
overflow: 'hidden'
})),
//element being added into DOM.
transition(':enter', [
animate('500ms ease-in-out', style({
'height': '*',
overflow: 'hidden'
}))
]),
//element being removed from DOM.
transition(':leave', [
animate('500ms ease-in-out', style({
'height': '0px',
overflow: 'hidden'
}))
])
])
答案 0 :(得分:13)
如果内容发生变化,我已经编写了一个可以平滑地动画投影内容高度的组件。 它的使用方式如下:
<smooth-height [trigger]="content">
{{content}}
</smooth-height>
这是一个stackblitz:https://stackblitz.com/edit/angular4-kugxw7
这是组件:
import {ElementRef, HostBinding, Component, Input, OnChanges} from '@angular/core';
import {animate, style, transition, trigger} from "@angular/animations";
@Component({
selector: 'smooth-height',
template: `
<ng-content></ng-content>
`,
styles: [`
:host {
display: block;
overflow: hidden;
}
`],
animations: [
trigger('grow', [
transition('void <=> *', []),
transition('* <=> *', [
style({height: '{{startHeight}}px', opacity: 0}),
animate('.5s ease'),
], {params: {startHeight: 0}})
])
]
})
export class SmoothHeightComponent implements OnChanges {
@Input()
trigger: string;
startHeight: number;
constructor(private element: ElementRef) {}
@HostBinding('@grow') get grow() {
return {value: this.trigger, params: {startHeight: this.startHeight}};
}
setStartHeight(){
this.startHeight = this.element.nativeElement.clientHeight;
}
ngOnChanges(){
this.setStartHeight();
}
}
答案 1 :(得分:6)
我根据@MartinCremer答案做出了指令。我认为使用指令更有意义,因为这样做,您还应该将动画添加到父组件中(这与添加动画的标准方法很接近)。
因此,在我的animations.ts
文件中。我添加了动画:
export const smoothHeight = trigger('grow', [
transition('void <=> *', []),
transition('* <=> *', [style({ height: '{{startHeight}}px', opacity: 0 }), animate('.5s ease')], {
params: { startHeight: 0 }
})
]);
然后,您应该将此动画添加到父组件(要在其中使用动画的组件):
import { smoothHeight } from '@app/animations';
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.scss'],
animations: [smoothHeight]
})
这是与@MartinCremer的组件非常接近的指令:
import { Directive, OnChanges, Input, HostBinding, ElementRef } from '@angular/core';
@Directive({
selector: '[smoothHeight]',
host: { '[style.display]': '"block"', '[style.overflow]': '"hidden"' }
})
export class SmoothHeightAnimDirective implements OnChanges {
@Input()
smoothHeight;
pulse: boolean;
startHeight: number;
constructor(private element: ElementRef) {}
@HostBinding('@grow')
get grow() {
return { value: this.pulse, params: { startHeight: this.startHeight } };
}
setStartHeight() {
this.startHeight = this.element.nativeElement.clientHeight;
}
ngOnChanges(changes) {
this.setStartHeight();
this.pulse = !this.pulse;
}
}
最后在parent.component.html
中使用指令:
<div [smoothHeight]="yourAnimationIndicator">
// any html content goes here
</div>
只需将yourAnimationIndicator
替换为动画在其值更改时应触发的变量。
答案 2 :(得分:2)
转换和不确定的大小(适合内容,最大内容等)不能很好地沟通。
以下是此情况下的 hack 示例:
animations: [
trigger('openCloseAnimation', [
state('open', style({ maxHeight: '100px', overflow: 'auto' })),
state('closed', style({ maxHeight: '60px' })),
transition('* => closed', animate('0.2s')),
transition('* => open', animate('0.5s')),
]),
],
使用MaxHeight,您的div /容器不会超过“最大内容”,但会表现为“适合内容”。
答案 3 :(得分:1)
你可以通过一些css和js实现类似的东西:
import { Component, OnChanges, ViewChild, Input } from '@angular/core';
@Component({
selector: 'app-exandable',
templateUrl: './exandable.component.html',
styleUrls: ['./exandable.component.css']
})
export class ExandableComponent implements OnChanges {
@Input()
src;
@ViewChild('expandable')
expandable;
ngOnChanges() {
this.updateHeight();
}
updateHeight(delay = 0) {
const el = this.expandable.nativeElement;
setTimeout(() => {
const prevHeight = el.style.height;
el.style.height = 'auto';
const newHeight = el.scrollHeight + 'px';
el.style.height = prevHeight;
setTimeout(() => {
el.style.height = newHeight;
}, 50);
}, delay);
}
}
.expandable {
transition: height 0.2s ease-in-out;
overflow: auto;
}