【问题标题】:Smoothly animating container's height in crossfade animation在交叉淡入淡出动画中平滑地动画容器的高度
【发布时间】:2019-01-09 02:41:09
【问题描述】:

在 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

【问题讨论】:

    标签: angular angular-animations


    【解决方案1】:

    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();
    }
    

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

    【讨论】:

    • 太棒了,非常感谢!看到动画 API 是多么容易实现的东西,我不会认为交叉淡入淡出需要特殊的方法。吸取了教训!
    猜你喜欢
    • 2016-05-12
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 2014-01-20
    相关资源
    最近更新 更多