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 previousTop = 0;
|
||||
protected previousHeight = 0;
|
||||
protected endAnimationTimeout?: number;
|
||||
protected content?: HTMLIonContentElement | null;
|
||||
protected loadingChangedListener?: CoreEventObserver;
|
||||
protected contentScrollListener?: EventListener;
|
||||
protected endContentScrollListener?: EventListener;
|
||||
|
||||
constructor(el: ElementRef, protected ionContent: IonContent) {
|
||||
this.element = el.nativeElement;
|
||||
|
@ -105,7 +106,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
const scroll = await this.content.getScrollElement();
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
@ -113,6 +114,23 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
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.
|
||||
*/
|
||||
protected setBarHeight(height: number): void {
|
||||
if (this.endAnimationTimeout) {
|
||||
clearTimeout(this.endAnimationTimeout);
|
||||
}
|
||||
|
||||
const collapsed = height <= this.finalHeight;
|
||||
const expanded = height >= this.initialHeight;
|
||||
this.element.classList.toggle('footer-collapsed', collapsed);
|
||||
this.element.classList.toggle('footer-expanded', expanded);
|
||||
this.content?.style.setProperty('--core-collapsible-footer-height', height + 'px');
|
||||
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> {
|
||||
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 content?: HTMLIonContentElement;
|
||||
protected contentScrollListener?: EventListener;
|
||||
protected endContentScrollListener?: EventListener;
|
||||
protected floatingTitle?: HTMLElement;
|
||||
protected scrollingHeight?: number;
|
||||
protected subscriptions: Subscription[] = [];
|
||||
protected enabled = true;
|
||||
protected endAnimationTimeout?: number;
|
||||
protected isWithinContent = false;
|
||||
|
||||
constructor(protected el: ElementRef) {}
|
||||
|
@ -108,6 +108,9 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
if (this.content && 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.
|
||||
*/
|
||||
protected updateContent(content?: HTMLIonContentElement | null): void {
|
||||
if (this.content && this.contentScrollListener) {
|
||||
this.content.removeEventListener('ionScroll', this.contentScrollListener);
|
||||
if (this.content) {
|
||||
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.contentScrollListener;
|
||||
}
|
||||
|
||||
content && this.trackContentScroll(content);
|
||||
|
@ -355,15 +364,12 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
.entries(expandedFontStyles)
|
||||
.forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string));
|
||||
|
||||
this.content.scrollEvents = true;
|
||||
this.content.addEventListener('ionScroll', this.contentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => {
|
||||
if (target !== this.content || !this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.endAnimationTimeout) {
|
||||
clearTimeout(this.endAnimationTimeout);
|
||||
}
|
||||
|
||||
const scrollableHeight = contentScroll.scrollHeight - contentScroll.clientHeight;
|
||||
|
||||
let frozen = false;
|
||||
|
@ -384,37 +390,31 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
Object
|
||||
.entries(progress > .5 ? collapsedFontStyles : expandedFontStyles)
|
||||
.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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* End of animation when stop scrolling.
|
||||
*
|
||||
* @param progress Progress.
|
||||
* @param scrollTop Current ScrollTop position.
|
||||
*/
|
||||
protected endAnimation(progress: number, scrollTop: number): void {
|
||||
if(!this.page) {
|
||||
return;
|
||||
}
|
||||
this.content.addEventListener(
|
||||
'ionScrollEnd',
|
||||
this.endContentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => {
|
||||
if (target !== this.content || !this.enabled) {
|
||||
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');
|
||||
this.page.classList.toggle('is-collapsed', collapse);
|
||||
page.style.setProperty('--collapsible-header-progress', collapse ? '1' : '0');
|
||||
page.classList.toggle('is-collapsed', collapse);
|
||||
|
||||
if (collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop < this.scrollingHeight) {
|
||||
this.content?.scrollToPoint(null, this.scrollingHeight);
|
||||
}
|
||||
if (collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop < this.scrollingHeight) {
|
||||
this.content?.scrollToPoint(null, this.scrollingHeight);
|
||||
}
|
||||
|
||||
if (!collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop > 0) {
|
||||
this.content?.scrollToPoint(null, 0);
|
||||
}
|
||||
if (!collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop > 0) {
|
||||
this.content?.scrollToPoint(null, 0);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue