MOBILE-3814 collapsible: Use ionScrollEnd to finish animations
parent
44ba6878a1
commit
4bd9f7f431
|
@ -42,9 +42,10 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
||||||
protected initialPaddingBottom = '0px';
|
protected initialPaddingBottom = '0px';
|
||||||
protected previousTop = 0;
|
protected previousTop = 0;
|
||||||
protected previousHeight = 0;
|
protected previousHeight = 0;
|
||||||
protected endAnimationTimeout?: number;
|
|
||||||
protected content?: HTMLIonContentElement | null;
|
protected content?: HTMLIonContentElement | null;
|
||||||
protected loadingChangedListener?: CoreEventObserver;
|
protected loadingChangedListener?: CoreEventObserver;
|
||||||
|
protected contentScrollListener?: EventListener;
|
||||||
|
protected endContentScrollListener?: EventListener;
|
||||||
|
|
||||||
constructor(el: ElementRef, protected ionContent: IonContent) {
|
constructor(el: ElementRef, protected ionContent: IonContent) {
|
||||||
this.element = el.nativeElement;
|
this.element = el.nativeElement;
|
||||||
|
@ -105,7 +106,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
||||||
const scroll = await this.content.getScrollElement();
|
const scroll = await this.content.getScrollElement();
|
||||||
this.content.scrollEvents = true;
|
this.content.scrollEvents = true;
|
||||||
|
|
||||||
this.content.addEventListener('ionScroll', (e: CustomEvent<ScrollDetail>): void => {
|
this.content.addEventListener('ionScroll', this.contentScrollListener = (e: CustomEvent<ScrollDetail>): void => {
|
||||||
if (!this.content) {
|
if (!this.content) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +114,23 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
||||||
this.onScroll(e.detail, scroll);
|
this.onScroll(e.detail, scroll);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.content.addEventListener('ionScrollEnd', this.endContentScrollListener = (): void => {
|
||||||
|
if (!this.content) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const height = this.previousHeight;
|
||||||
|
const collapsed = height <= this.finalHeight;
|
||||||
|
const expanded = height >= this.initialHeight;
|
||||||
|
|
||||||
|
if (!collapsed && !expanded) {
|
||||||
|
// Finish opening or closing the bar.
|
||||||
|
const newHeight = (height - this.finalHeight) < (this.initialHeight - this.finalHeight) / 2
|
||||||
|
? this.finalHeight
|
||||||
|
: this.initialHeight;
|
||||||
|
|
||||||
|
this.setBarHeight(newHeight); }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,34 +172,12 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
||||||
* @param height The new bar height.
|
* @param height The new bar height.
|
||||||
*/
|
*/
|
||||||
protected setBarHeight(height: number): void {
|
protected setBarHeight(height: number): void {
|
||||||
if (this.endAnimationTimeout) {
|
|
||||||
clearTimeout(this.endAnimationTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
const collapsed = height <= this.finalHeight;
|
const collapsed = height <= this.finalHeight;
|
||||||
const expanded = height >= this.initialHeight;
|
const expanded = height >= this.initialHeight;
|
||||||
this.element.classList.toggle('footer-collapsed', collapsed);
|
this.element.classList.toggle('footer-collapsed', collapsed);
|
||||||
this.element.classList.toggle('footer-expanded', expanded);
|
this.element.classList.toggle('footer-expanded', expanded);
|
||||||
this.content?.style.setProperty('--core-collapsible-footer-height', height + 'px');
|
this.content?.style.setProperty('--core-collapsible-footer-height', height + 'px');
|
||||||
this.previousHeight = height;
|
this.previousHeight = height;
|
||||||
|
|
||||||
if (!collapsed && !expanded) {
|
|
||||||
// Finish opening or closing the bar.
|
|
||||||
this.endAnimationTimeout = window.setTimeout(() => this.endAnimation(height), 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End of animation when not scrolling.
|
|
||||||
*
|
|
||||||
* @param height Last height used.
|
|
||||||
*/
|
|
||||||
protected endAnimation(height: number): void {
|
|
||||||
const newHeight = (height - this.finalHeight) < (this.initialHeight - this.finalHeight) / 2
|
|
||||||
? this.finalHeight
|
|
||||||
: this.initialHeight;
|
|
||||||
|
|
||||||
this.setBarHeight(newHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,6 +209,13 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
async ngOnDestroy(): Promise<void> {
|
async ngOnDestroy(): Promise<void> {
|
||||||
this.content?.style.setProperty('--padding-bottom', this.initialPaddingBottom);
|
this.content?.style.setProperty('--padding-bottom', this.initialPaddingBottom);
|
||||||
|
|
||||||
|
if (this.content && this.contentScrollListener) {
|
||||||
|
this.content.removeEventListener('ionScroll', this.contentScrollListener);
|
||||||
|
}
|
||||||
|
if (this.content && this.endContentScrollListener) {
|
||||||
|
this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,11 +62,11 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
||||||
protected expandedFontStyles?: Partial<CSSStyleDeclaration>;
|
protected expandedFontStyles?: Partial<CSSStyleDeclaration>;
|
||||||
protected content?: HTMLIonContentElement;
|
protected content?: HTMLIonContentElement;
|
||||||
protected contentScrollListener?: EventListener;
|
protected contentScrollListener?: EventListener;
|
||||||
|
protected endContentScrollListener?: EventListener;
|
||||||
protected floatingTitle?: HTMLElement;
|
protected floatingTitle?: HTMLElement;
|
||||||
protected scrollingHeight?: number;
|
protected scrollingHeight?: number;
|
||||||
protected subscriptions: Subscription[] = [];
|
protected subscriptions: Subscription[] = [];
|
||||||
protected enabled = true;
|
protected enabled = true;
|
||||||
protected endAnimationTimeout?: number;
|
|
||||||
protected isWithinContent = false;
|
protected isWithinContent = false;
|
||||||
|
|
||||||
constructor(protected el: ElementRef) {}
|
constructor(protected el: ElementRef) {}
|
||||||
|
@ -108,6 +108,9 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
||||||
if (this.content && this.contentScrollListener) {
|
if (this.content && this.contentScrollListener) {
|
||||||
this.content.removeEventListener('ionScroll', this.contentScrollListener);
|
this.content.removeEventListener('ionScroll', this.contentScrollListener);
|
||||||
}
|
}
|
||||||
|
if (this.content && this.endContentScrollListener) {
|
||||||
|
this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -281,11 +284,17 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
||||||
* @param content Content element.
|
* @param content Content element.
|
||||||
*/
|
*/
|
||||||
protected updateContent(content?: HTMLIonContentElement | null): void {
|
protected updateContent(content?: HTMLIonContentElement | null): void {
|
||||||
if (this.content && this.contentScrollListener) {
|
if (this.content) {
|
||||||
this.content.removeEventListener('ionScroll', this.contentScrollListener);
|
if (this.contentScrollListener) {
|
||||||
|
this.content.removeEventListener('ionScroll', this.contentScrollListener);
|
||||||
|
delete this.contentScrollListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.endContentScrollListener) {
|
||||||
|
this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener);
|
||||||
|
delete this.endContentScrollListener;
|
||||||
|
}
|
||||||
delete this.content;
|
delete this.content;
|
||||||
delete this.contentScrollListener;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content && this.trackContentScroll(content);
|
content && this.trackContentScroll(content);
|
||||||
|
@ -355,15 +364,12 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
||||||
.entries(expandedFontStyles)
|
.entries(expandedFontStyles)
|
||||||
.forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string));
|
.forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string));
|
||||||
|
|
||||||
|
this.content.scrollEvents = true;
|
||||||
this.content.addEventListener('ionScroll', this.contentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => {
|
this.content.addEventListener('ionScroll', this.contentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => {
|
||||||
if (target !== this.content || !this.enabled) {
|
if (target !== this.content || !this.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.endAnimationTimeout) {
|
|
||||||
clearTimeout(this.endAnimationTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
const scrollableHeight = contentScroll.scrollHeight - contentScroll.clientHeight;
|
const scrollableHeight = contentScroll.scrollHeight - contentScroll.clientHeight;
|
||||||
|
|
||||||
let frozen = false;
|
let frozen = false;
|
||||||
|
@ -384,37 +390,31 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
||||||
Object
|
Object
|
||||||
.entries(progress > .5 ? collapsedFontStyles : expandedFontStyles)
|
.entries(progress > .5 ? collapsedFontStyles : expandedFontStyles)
|
||||||
.forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string));
|
.forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string));
|
||||||
|
|
||||||
if (progress > 0 && progress < 1) {
|
|
||||||
// Finish opening or closing the bar.
|
|
||||||
this.endAnimationTimeout = window.setTimeout(() => this.endAnimation(progress, contentScroll.scrollTop), 500);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.content.addEventListener(
|
||||||
* End of animation when stop scrolling.
|
'ionScrollEnd',
|
||||||
*
|
this.endContentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => {
|
||||||
* @param progress Progress.
|
if (target !== this.content || !this.enabled) {
|
||||||
* @param scrollTop Current ScrollTop position.
|
return;
|
||||||
*/
|
}
|
||||||
protected endAnimation(progress: number, scrollTop: number): void {
|
|
||||||
if(!this.page) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const collapse = progress > 0.5;
|
const progress = parseFloat(page.style.getPropertyValue('--collapsible-header-progress'));
|
||||||
|
const scrollTop = contentScroll.scrollTop;
|
||||||
|
const collapse = progress > 0.5;
|
||||||
|
|
||||||
this.page.style.setProperty('--collapsible-header-progress', collapse ? '1' : '0');
|
page.style.setProperty('--collapsible-header-progress', collapse ? '1' : '0');
|
||||||
this.page.classList.toggle('is-collapsed', collapse);
|
page.classList.toggle('is-collapsed', collapse);
|
||||||
|
|
||||||
if (collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop < this.scrollingHeight) {
|
if (collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop < this.scrollingHeight) {
|
||||||
this.content?.scrollToPoint(null, this.scrollingHeight);
|
this.content?.scrollToPoint(null, this.scrollingHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop > 0) {
|
if (!collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop > 0) {
|
||||||
this.content?.scrollToPoint(null, 0);
|
this.content?.scrollToPoint(null, 0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue