Ваше решение отображает заголовок-2 только тогда, когда пользователь прокручивает дальше заданного значения, но не будет отображать заголовок-1 снова, как только пользователь прокручивает вверх, как на демонстрационной странице, которую вы разместили. Заголовок-1 появляется снова, только если пользователь прокручивает страницу вверх.
Чтобы вставить заголовок-1 обратно, как только пользователь выполнит прокрутку, вы должны определить текущее направление прокрутки при каждом запуске события прокрутки. Для этого вы можете создать наблюдаемый поток позиций прокрутки, сопоставить их с направлениями ВВЕРХ / ВНИЗ и соответствующим образом установить состояние заголовка. Затем используйте анимацию для перемещения заголовков в зависимости от наблюдаемого состояния заголовка.
https://stackblitz.com/edit/angular-pj5rjj-8asowc
import { Component, HostListener, AfterViewInit, OnDestroy } from '@angular/core';
import { fromEvent, Subject } from 'rxjs';
import { distinctUntilChanged, map, pairwise, takeUntil, throttleTime } from 'rxjs/operators';
import { animate, state, style, transition, trigger } from '@angular/animations';
export enum VisibilityState { Visible = 'visible', Hidden = 'hidden' }
export enum Direction { None = 'None', Up = 'Up', Down = 'Down' }
@Component({
selector: 'sidenav-position-example',
templateUrl: 'sidenav-position-example.html',
styleUrls: ['sidenav-position-example.css'],
animations: [
trigger('scrollAnimation', [
state(VisibilityState.Visible, style({ transform: 'translateY(0)' })),
state(VisibilityState.Hidden, style({ transform: 'translateY(-64px)' })), // adjust this to the height of your header
transition(`${VisibilityState.Visible} => ${VisibilityState.Hidden}`, animate('250ms')),
transition(`${VisibilityState.Hidden} => ${VisibilityState.Visible}`, animate('250ms'))
])
]
})
export class SidenavPositionExample implements AfterViewInit, OnDestroy {
private destroy$: Subject<boolean> = new Subject<boolean>();
isHeader1Visible = VisibilityState.Visible;
isHeader2Visible = VisibilityState.Hidden;
slideHeader2InAtPosition = 30;
ngAfterViewInit() {
// create an observable stream of scroll positions and map them to UP / DOWN directions
const content = document.querySelector('.scrollWrapper');
// if the scroll events happen on your window you could use 'window' instead of
// 'content' here
const scroll$ = fromEvent(content, 'scroll').pipe(
throttleTime(10),
// if you used 'window' above replace 'content.scrollTop' with 'window.pageYOffset'
map(() => content.scrollTop),
pairwise(),
map(([y1, y2]): Direction => (y2 < y1 ? Direction.Up : (y2 > this.slideHeader2InAtPosition ? Direction.Down : Direction.None))),
distinctUntilChanged(),
takeUntil(this.destroy$)
);
// subscribe to the UP / DOWN scroll direction stream and set the header state accordingly
scroll$.subscribe(dir => {
if (dir === Direction.Down) { // scrolling down
this.isHeader1Visible = VisibilityState.Hidden;
this.isHeader2Visible = VisibilityState.Visible;
} else { // scrolling up
this.isHeader1Visible = VisibilityState.Visible;
this.isHeader2Visible = VisibilityState.Hidden;
}
});
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}
}
Я немного изменил HTML, но вы также можете использовать другую настройку и затем установить соответствующий элемент прокрутки в приведенном выше коде или просто прослушать события прокрутки на window
.
<div class="headerWrapper">
<mat-toolbar class="header" color="primary" [@scrollAnimation]="isHeader1Visible">
<mat-toolbar-row>
<span>Header 1</span>
</mat-toolbar-row>
</mat-toolbar>
<mat-toolbar class="header" color="secondary" [@scrollAnimation]="isHeader2Visible">
<mat-toolbar-row>
<span>Header 2</span>
</mat-toolbar-row>
</mat-toolbar>
</div>
<div class="scrollWrapper">
<div class="scrollContent">
...
</div>
</div>