Как изменить раздел Заголовок при прокрутке в Angular? - PullRequest
0 голосов
/ 07 января 2019

Я хочу изменить заголовок, прокручивая горизонтальную боковую панель в угловую. Используя hostlister, я реализовал это, но он работает не так, как задумано.

код в файле example.ts

import {Component,HostListener} from '@angular/core';

/** @title Implicit main content with two sidenavs */
@Component({
  selector: 'sidenav-position-example',
  templateUrl: 'sidenav-position-example.html',
  styleUrls: ['sidenav-position-example.css'],
})
@HostListener('window:scroll', [])
export class SidenavPositionExample {
scrolled : boolean =  true;
onWindowScroll() {
    this.scrolled = window.pageYOffset >48;
    }
}

HTML-код

<div style="min-height: 150vh;"> <!-- Set minimum height to force a scrollbar -->
    <mat-toolbar color="primary">
        <mat-toolbar-row>
            <span>Header 1</span>
        </mat-toolbar-row>
    </mat-toolbar>

    <mat-toolbar color="secondary" style="position: fixed; top: 0;" *ngIf="scrolled">
        <mat-toolbar-row>
            <span>Header 2</span>
        </mat-toolbar-row>
    </mat-toolbar>
</div>

Stackblitz того, что я пытался

Демонстрация того, что я хочу

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Ваше решение отображает заголовок-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>
0 голосов
/ 07 января 2019

HostListener не следует помещать в класс компонента, он должен быть внутри методов класса

Эта часть неверна

@HostListener('window:scroll', [])
export class SidenavPositionExample {

Ваш класс компонента должен быть таким

import { Component, HostListener } from '@angular/core';

/** @title Implicit main content with two sidenavs */
@Component({
  selector: 'sidenav-position-example',
  templateUrl: 'sidenav-position-example.html',
  styleUrls: ['sidenav-position-example.css'],
})
export class SidenavPositionExample {
  scrolled: boolean = false;

  // for initialization
  constructor() {
    this.scrolled = window.pageYOffset > 48;
  }


  @HostListener('window:scroll', [])
  onWindowScroll() {
    this.scrolled = window.pageYOffset > 48;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...