在淡入淡出动画中平滑设置容器的高度动画

时间:2019-01-08 16:20:00

标签: angular angular-animations

我无法在Angular动画中获得所需的效果。典型的淡入淡出效果,而混浊效果可以很好地进行淡入淡出,但是高度却没有变化。

我在做什么错了?

  animations: [
    trigger('fadeInOut', [
      transition('* => *', [
        style({ height: '*' }),
        group([
          query(':leave',
            [
              style({ opacity: 1, position: 'absolute', height: '*' }),
              animate('1s', style({ opacity: 0, height: '*' })),
            ],
            { optional: true },
          ),

          query(':enter',
            [
              style({ opacity: 0 }),
              animate('1s', style({ opacity: 1, height: '*' })),
            ],
            { optional: true },
          ),
        ]),
      ]),
    ]),
  ],

实时演示:https://angular-crossfade.stackblitz.io

1 个答案:

答案 0 :(得分:3)

Demo + Code

恕我直言,这是一个非常复杂的动画,我使用了许多我通常不会使用的技巧,它们可能是一个更简单的解决方案。

我认为项目的高度是动态的,这是最大的挑战,但它使动画非常灵活。

由于我们具有动态值,因此我们将使用Angular的AnimationBuilder。

使用AnimationBuilder时,我们无权访问:enter:leave查询,因此这两个元素都需要不断渲染。

让我们从简单的CSS开始,它变得更加简单:

#holder {
  position: relative;
  overflow: hidden;
}
#show {
  background-color: darkcyan;
}
#edit {
  background-color: cornflowerblue;

  visibility: hidden; <-- we start with the 'edit' panel hidden
  position: absolute; <-- we start with the 'edit' panel hidden
}

模板:

<div #refHolder id="holder">
  <div #refShow id="show">
    <div>show</div>
    <div>show</div>
    <div>show</div>
  </div>
  <div #refEdit id="edit">
    <div>edit</div>
    <div>edit</div>
    <div>edit</div>
    <div>edit</div>
    <div>edit</div>
    <div>edit</div>
  </div>
</div>

<button (click)="toggleState()">Toggle</button>

在这里,请注意对3个元素引用(#refHolder,#refShow,#refEdit)的引用,在制作动画时我们将使用它们来访问它们的属性。

还请注意ID,它们既用于样式设置,又用于在动画过程中进行查询。

TS:

我们需要定义一组属性

state = true;

@ViewChild('refHolder') refHolder: ElementRef;
@ViewChild('refShow') refShow: ElementRef;
@ViewChild('refEdit') refEdit: ElementRef;

private animationFactory: AnimationFactory;

将AnimationBuilder服务注入到构造函数中:

constructor(
  private animationBuilder: AnimationBuilder,
) { }

让我们对切换功能进行编码,它将首先翻转状态,然后构建并播放动画。

toggleState() {
  this.state = !this.state;
  this.buildAndPlayAnimation();
}

现在,让我们做一个难的部分,制作动画:

private buildAndPlayAnimation() {
  let animationFactory: AnimationFactory;

  animationFactory = this.animationBuilder.build([
    group([
      query(this.state ? '#edit' : '#show', [
        style({
          position: 'absolute',
          opacity: 1,
          top: 0,
          right: 0,
          left: 0,
          height: Math.max(this.state ? this.refShow.nativeElement.clientHeight : this.refEdit.nativeElement.clientHeight, this.refHolder.nativeElement.clientHeight),
        }),
        animate('.5s', style({ 
          opacity: 0,
          visibility: 'hidden',
        })),
        style({
          top: 'auto',
          bottom: 'auto',
          right: 'auto',
          height: '*',
        })
      ]),
      query(this.state ? '#show' : '#edit', [
        style({
          position: 'static',
          opacity: 0,
          height: this.refHolder.nativeElement.clientHeight,
          visibility: 'visible',
        }),
        animate('.5s', style({
          opacity: 1,
          height: '*',
        })),
      ])
    ])
  ]);

  animationFactory.create(this.refHolder.nativeElement).play();
}

基本上,我使用三元运算符是为了不必两次创建动画,因为它需要以两种方式工作。将项目设置为不可见且位置绝对,以防止用户与可见面板进行交互。