スクロール中にツールバーを非表示にするディレクティブを実装しようとしています。私はこのチュートリアルを使用してみました: 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
私がチェックしたところ、Ionic 4のev
はCustomEvent
であり、ScrollEvent
ではありません。
助言がありますか?
上記のソリューションは機能しなくなります。 Ionic 4ベータ版APIは、ここ数ヶ月で大幅に変更されました。
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>
それが役に立てば幸い。
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;
}
イベントはIonic 4で変更された可能性がありますが、_@ionic/angular
_からDomController
をインポートできます
_import {..., DomController } from "@ionic/angular";
_
そしてそれをコンストラクタに注入します
_constructor(
// ...
private domCtrl: DomController
) { }
_
そして、次のようにwrite()
メソッドを使用します。
_private adjustElementOnScroll(ev) {
if (ev) {
this.domCtrl.write(() => {
// ...
});
}
}
_
DomController
は、バックグラウンドでwindow.requestAnimationFrame()
メソッドを使用するためにDOMの書き込みまたは読み取りを行うコールバックのキューを作成するIonicの単なる方法です。
詳細については、以下をご覧ください。
以下のコードは私のために働きました、上のコードからの小さな修正で
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;
}