Skip to content

Instantly share code, notes, and snippets.

@sean-perkins
Last active September 3, 2018 22:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sean-perkins/45ee94f02a72c9aa358a92dc944dc788 to your computer and use it in GitHub Desktop.
Save sean-perkins/45ee94f02a72c9aa358a92dc944dc788 to your computer and use it in GitHub Desktop.
Ionic 4 (beta.7+) Collapse Scroll Directive
import { Directive, OnDestroy, Input, Renderer2, ElementRef, AfterViewInit } from '@angular/core';
import { Content } from '@ionic/angular';
import { takeUntil, tap } from 'rxjs/operators';
import { Subject } from 'rxjs';
/**
* Usage:
* <example-component [collapseScroll]="content"></example-content>
* Where: content = ion-content reference binding
*/
@Directive({
selector: '[collapseScroll]'
})
export class CollapseScrollDirective implements AfterViewInit, OnDestroy {
@Input() scrollBuffer = 5;
private _content: Content;
get content() {
return this._content;
}
@Input('collapseScroll')
set content(content: Content) {
this._content = content;
if (content) {
this._content.scrollEvents = true;
this._bindScrollListener();
}
}
@Input('hidden')
set hidden(hidden: boolean) {
if (!hidden) {
this._calculateMaxHeight();
}
}
private maxHeight = '0px';
private destroy$ = new Subject();
constructor(
private renderer: Renderer2,
private elementRef: ElementRef) { }
ngAfterViewInit() {
this._calculateMaxHeight();
this._setupAnimation();
}
ngOnDestroy() {
this.destroy$.next(true);
}
private _calculateMaxHeight() {
setTimeout(() => {
this.maxHeight = `${this.elementRef.nativeElement.clientHeight}px`;
});
}
private _bindScrollListener() {
let position = 0;
if (this.content) {
this.content.ionScroll.pipe(
takeUntil(this.destroy$),
tap(ev => {
const scrollPos = ev.detail.scrollTop;
if (scrollPos > position + this.scrollBuffer) {
this._animateVisibility(false);
position = scrollPos;
} else if (scrollPos <= position - this.scrollBuffer) {
this._animateVisibility(true);
position = scrollPos;
}
})
).subscribe();
}
}
private _setupAnimation() {
const el = this.elementRef.nativeElement;
this.renderer.setStyle(el, 'will-change', 'max-height');
this.renderer.setStyle(el, 'transition', '.35s ease-in-out all');
this.renderer.setStyle(el, 'contain', 'content');
}
private _animateVisibility(value: boolean) {
this.renderer.setStyle(this.elementRef.nativeElement, 'max-height', value ? this.maxHeight : `0px`)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment