Angular 动画向上滑动内容菜单

Angular animation slide up content menu

我正在努力了解 angular 动画。 我找到了一篇关于如何创建动画菜单的文章,所以我实现了它。这就是我目前所拥有的(我已经删除了与这个问题无关的代码)

import { Component, AfterViewInit, HostBinding, HostListener, ElementRef, Renderer2, OnInit } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { distinctUntilChanged, filter, map, pairwise, share, throttleTime } from 'rxjs/operators';
import { fromEvent } from 'rxjs';

enum VisibilityState {
  Visible = 'visible',
  Hidden = 'hidden'
}

enum Direction {
  Up = 'Up',
  Down = 'Down'
}

@Component({
  selector: 'pyb-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
  animations: [
    trigger('toggle', [
      state(
        VisibilityState.Hidden,
        style({ height: '10px' })
      ),
      state(
        VisibilityState.Visible,
        style("*")
      ),
      transition('* => *', animate('200ms ease-in'))
    ])
  ]
})
export class HeaderComponent implements AfterViewInit, OnInit {
  private isVisible: boolean = true;

  constructor(
    private renderer: Renderer2,
    private element: ElementRef
  ) { }

  @HostBinding('@toggle')
  get toggle(): VisibilityState {
    if (this.isVisible) {
      this.renderer.removeClass(this.element.nativeElement, 'collapsed');
    }
    else {
      this.renderer.addClass(this.element.nativeElement, 'collapsed');
    }
    return this.isVisible ? VisibilityState.Visible : VisibilityState.Hidden;
  }

  @HostListener('mouseenter')
  mouseEnter() {
    this.isVisible = true;
  }

  @HostListener('mouseleave')
  mouseLeave() {
    this.isVisible = false;
  }

  ngOnInit() {
  }

  ngAfterViewInit() {
    const scroll$ = fromEvent(window, 'scroll').pipe(
      throttleTime(10),
      map(() => window.pageYOffset),
      pairwise(),
      map(([y1, y2]): Direction => (y2 < y1 ? Direction.Up : Direction.Down)),
      distinctUntilChanged(),
      share()
    );

    const scrollUp$ = scroll$.pipe(
      filter(direction => direction === Direction.Up)
    );

    const scrollDown = scroll$.pipe(
      filter(direction => direction === Direction.Down)
    );

    scrollUp$.subscribe(() => {
      this.isVisible = true
    });
    scrollDown.subscribe(() => {
      this.isVisible = false;
    });
  }
}

现在,如果模板是这样的:

<div class="header" #header>
</div>

CSS 是这样的:

:host {
    height: $header-height;
    background-color: $clouds;
    color: $midnight;
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 1000;
}

似乎一切正常。 但是,一旦我添加内容,它就无法正常工作。 我的模板实际上是这样的:

<div class="header" #header>
  <div class="container">
    <div class="row">
      <div class="col" *ngIf="retailers && count && !displayMatches">
        <p class="float-left"><b>{{ count }}</b> {{ category }} available at </p>
        <pyb-text-slider [textArray]="retailers"></pyb-text-slider>
      </div>
      <div class="col" *ngIf="matches && displayMatches">
        <span [ngSwitch]="matches.length">
          <p *ngSwitchCase="0"><b>{{ matches.length }}</b> {{ category }}</p>
          <p *ngSwitchDefault><b>{{ matches.length }}</b> {{ category }} from <b>{{ matches[0].price }}</b></p>
        </span>
        <pyb-matches></pyb-matches>
      </div>
    </div>
  </div>
</div>

问题是,内容不会随菜单一起折叠。 我不得不添加一些 CSS:

.header {
    visibility: visible;
    opacity: 1;
    transition: visibility .2s, opacity .2s linear;
    padding: 12px 0;
}
&.collapsed .header {
    visibility: hidden;
    opacity: 0;
}

它隐藏了内容,但这并不是很好。 有没有人以前遇到过这个问题并且知道如何解决它?

我通过首先使我的 CSS 像这样解决了这个问题:

:host {
    height: $header-height;
    background-color: $clouds;
    color: $midnight;
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 1000;

    transform-origin: top;

    .header {
        transition: visibility .2s, opacity .2s linear;
        visibility: visible;
        opacity: 1;
        padding: 12px 0;
    }

    &.collapsed .header {
        visibility: hidden;
        opacity: 0;
    }
}

然后将我的动画更改为:

animations: [
  trigger('toggle', [
    state(
      VisibilityState.Hidden,
      style({ transform: 'scaleY(0.2)' })
    ),
    state(
      VisibilityState.Visible,
      style({ transform: 'scaleY(1)' })
    ),
    transition('* => *', animate('200ms ease-in'))
  ])
]

这很好地折叠了菜单,同时隐藏了内容。我不确定这将如何影响性能(将 CSS 与 angular 动画混合)但它有效。