Ionic 4 Скрыть панель инструментов при прокрутке - PullRequest
0 голосов
/ 10 октября 2018

Я пытаюсь реализовать директиву, чтобы скрыть панель инструментов при прокрутке.Я пытался использовать этот учебник: https://medium.com/@gregor.srdic/ionic3-hidding-header-on-footer-on-content-scroll-15ab95b05dc5

Это работало с Ionic 3, но не работает с Ionic 4.

В следующем коде я получаю сообщение об ошибке:

private adjustElementOnScroll(ev) {
    if (ev) {
        console.log(ev);
        ev.domWrite(() => {
            let scrollTop: number = ev.scrollTop > 0 ? ev.scrollTop : 0;
            let scrolldiff: number = scrollTop - this.lastScrollPosition;
            this.lastScrollPosition = scrollTop;
            let newValue = this.lastValue + scrolldiff;
            newValue = Math.max(0, Math.min(newValue, this.config.maxValue));
            this.renderer.setStyle(this.element.nativeElement, this.config.cssProperty, `-${newValue}px`);
            this.lastValue = newValue;
        });
    }
}

Ошибка:

ev.domWrite is not a function

Я проверил, и ev в Ionic 4 - это CustomEvent, а не ScrollEvent.

Есть предложения?

Ответы [ 4 ]

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

Над решениями больше не работает.API бета-версии Ionic 4 сильно изменились за последние месяцы.

вы должны импортировать IonContent вместо Content.

//scroll-hide.directive.ts
import { IonContent, DomController } from '@ionic/angular';
import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';

импортировать директиву, где вы хотите ее использовать, вместо app.module.ts

дляНапример, в соответствующем модуле

//ex: home.module.ts
import { ScrollHideDirective } from '../../directives/scroll-hide.directive';

@NgModule({
    ...
  declarations: [...,ScrollHideDirective],
    ...
})


then in the ts file,


//ex: home.page.ts
import { ScrollHideConfig } from '../../directives/scroll-hide.directive';


export class HomePage implements OnInit {

...
    footerScrollConfig: ScrollHideConfig = { cssProperty: 'margin-bottom', maxValue: undefined };
    headerScrollConfig: ScrollHideConfig = { cssProperty: 'margin-top', maxValue: 54 };
...

}

обратная версия директивы

//ex: scroll-hide.directive.ts    

import { IonContent, DomController } from '@ionic/angular';
import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';

    @Directive({
      selector: '[scrollHide]'
      })
export class ScrollHideDirective {

  @Input('scrollHide') config: ScrollHideConfig;
  @Input('scrollContent') scrollContent: IonContent;

  contentHeight: number;
  scrollHeight: number;
  lastScrollPosition: number;
  lastValue: number = 0;

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

  ngOnChanges(changes: SimpleChanges) {
    if(this.scrollContent && this.config) {
      this.scrollContent.scrollEvents = true;

      let scrollStartFunc = async (ev) => {
        const el = await this.scrollContent.getScrollElement();
        this.contentHeight = el.offsetHeight;
        this.scrollHeight = el.scrollHeight;
        if (this.config.maxValue === undefined) {
          this.config.maxValue = this.element.nativeElement.offsetHeight;
        }
        this.lastScrollPosition = el.scrollTop;
      };

      if(this.scrollContent && this.scrollContent instanceof IonContent) {
        this.scrollContent.ionScrollStart.subscribe(scrollStartFunc);
        this.scrollContent.ionScroll.subscribe(async (ev) => this.adjustElementOnScroll(ev));
        this.scrollContent.ionScrollEnd.subscribe(async (ev) => this.adjustElementOnScroll(ev));

      } else if(this.scrollContent instanceof HTMLElement) {
        (this.scrollContent as HTMLElement).addEventListener('ionScrollStart', scrollStartFunc);
        (this.scrollContent as HTMLElement).addEventListener('ionScroll',async (ev) => this.adjustElementOnScroll(ev));
        (this.scrollContent as HTMLElement).addEventListener('ionScrollEnd',async (ev) => this.adjustElementOnScroll(ev));
      }
    }
  }

  private adjustElementOnScroll(ev) {
    if (ev) {
      this.domCtrl.write(async () => {
        const el = await this.scrollContent.getScrollElement();
        let scrollTop: number = el.scrollTop > 0 ? el.scrollTop : 0;
        let scrolldiff: number = scrollTop - this.lastScrollPosition;
        this.lastScrollPosition = scrollTop;
        let newValue = this.lastValue + scrolldiff;
        newValue = Math.max(0, Math.min(newValue, this.config.maxValue));
        this.renderer.setStyle(this.element.nativeElement, this.config.cssProperty, `-${newValue}px`);
        this.lastValue = newValue;
      });
    }
  }
}

export interface ScrollHideConfig {
  cssProperty: string;
  maxValue: number;
}

html ex: page.html (без изменений)

<ion-header [scrollHide]="headerScrollConfig" [scrollContent]="pageContent">
  ...
</ion-header>

<ion-content #pageContent fullscreen>
  ...
</ion-content>

<ion-footer [scrollHide]="footerScrollConfig" [scrollContent]="pageContent">
...
</ion-footer>

надеюсь, что это поможет.

0 голосов
/ 15 декабря 2018

Модифицированная директива для Ionic 4.

import { Content, DomController } from '@ionic/angular';
import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';

@Directive({
    selector: '[scrollHide]'
})
export class ScrollHideDirective {

    @Input('scrollHide') config: ScrollHideConfig;
    @Input('scrollContent') scrollContent: Content;

    contentHeight: number;
    scrollHeight: number;
    lastScrollPosition: number;
    lastValue: number = 0;

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

    ngOnChanges(changes: SimpleChanges) {
        if (this.scrollContent && this.config) {
            this.scrollContent.ionScrollStart.subscribe(async (ev) => {
                const el = await this.scrollContent.getScrollElement();
                this.contentHeight = el.offsetHeight;
                this.scrollHeight = el.scrollHeight;    
                if (this.config.maxValue === undefined) {
                    this.config.maxValue = this.element.nativeElement.offsetHeight;
                }
                this.lastScrollPosition = el.scrollTop;
            });
            this.scrollContent.ionScroll.subscribe((ev) => this.adjustElementOnScroll(ev));
            this.scrollContent.ionScrollEnd.subscribe((ev) => this.adjustElementOnScroll(ev));
        }
    }

    private adjustElementOnScroll(ev) {
        if (ev) {
            this.domCtrl.write(async () => {
                const el = await this.scrollContent.getScrollElement();
                let scrollTop: number = el.scrollTop > 0 ? el.scrollTop : 0;
                let scrolldiff: number = scrollTop - this.lastScrollPosition;
                this.lastScrollPosition = scrollTop;
                let newValue = this.lastValue + scrolldiff;
                newValue = Math.max(0, Math.min(newValue, this.config.maxValue));
                this.renderer.setStyle(this.element.nativeElement, this.config.cssProperty, `-${newValue}px`);
                this.lastValue = newValue;
            });
        }
    }
}
export interface ScrollHideConfig {
    cssProperty: string;
    maxValue: number;
}
0 голосов
/ 19 декабря 2018

Приведенный ниже код работал для меня, с небольшими исправлениями сверху кода

import { Content, DomController } from '@ionic/angular';
import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';

@Directive({
  selector: '[scrollHide]'
  })
export class ScrollHideDirective {

  @Input('scrollHide') config: ScrollHideConfig;
  @Input('scrollContent') scrollContent: Content;

  contentHeight: number;
  scrollHeight: number;
  lastScrollPosition: number;
  lastValue: number = 0;

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

  ngOnChanges(changes: SimpleChanges) {
    if(this.scrollContent && this.config) {
      this.scrollContent.scrollEvents = true;

      let scrollStartFunc = async (ev) => {
        const el = await this.scrollContent.getScrollElement();
        this.contentHeight = el.offsetHeight;
        this.scrollHeight = el.scrollHeight;
        if (this.config.maxValue === undefined) {
          this.config.maxValue = this.element.nativeElement.offsetHeight;
        }
        this.lastScrollPosition = el.scrollTop;
      };

      if(this.scrollContent && this.scrollContent instanceof Content) {
        this.scrollContent.ionScrollStart.subscribe(scrollStartFunc);
        this.scrollContent.ionScroll.subscribe(async (ev) => this.adjustElementOnScroll(ev));
        this.scrollContent.ionScrollEnd.subscribe(async (ev) => this.adjustElementOnScroll(ev));

      } else if(this.scrollContent instanceof HTMLElement) {
        (this.scrollContent as HTMLElement).addEventListener('ionScrollStart', scrollStartFunc);
        (this.scrollContent as HTMLElement).addEventListener('ionScroll',async (ev) => this.adjustElementOnScroll(ev));
        (this.scrollContent as HTMLElement).addEventListener('ionScrollEnd',async (ev) => this.adjustElementOnScroll(ev));
      }
    }
  }

  private adjustElementOnScroll(ev) {
    if (ev) {
      this.domCtrl.write(async () => {
        const el = await this.scrollContent.getScrollElement();
        let scrollTop: number = el.scrollTop > 0 ? el.scrollTop : 0;
        let scrolldiff: number = scrollTop - this.lastScrollPosition;
        this.lastScrollPosition = scrollTop;
        let newValue = this.lastValue + scrolldiff;
        newValue = Math.max(0, Math.min(newValue, this.config.maxValue));
        this.renderer.setStyle(this.element.nativeElement, this.config.cssProperty, `-${newValue}px`);
        this.lastValue = newValue;
      });
    }
  }
}
export interface ScrollHideConfig {
  cssProperty: string;
  maxValue: number;
}
0 голосов
/ 20 октября 2018

Событие могло измениться в Ionic 4, но вы все равно можете импортировать DomController из @ionic/angular

import {..., DomController } from "@ionic/angular";

и вставить его в конструктор

constructor(
    // ...
    private domCtrl: DomController
) { }

Изатем используйте метод write() следующим образом:

private adjustElementOnScroll(ev) {
    if (ev) {
        this.domCtrl.write(() => {
            // ...
        });
    }
}

DomController - это просто способ для Ionic создать очередь для обратных вызовов, которая будет писать или читать DOM для использования window.requestAnimationFrame()метод за кадром.

Для получения дополнительной информации, пожалуйста, посетите:

  1. DomController исходный код
  2. requestAnimationFrame MDN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...