mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 05:21:52 +08:00
@ -57,14 +57,10 @@ export class Header implements ComponentInterface {
|
|||||||
// Determine if the header can collapse
|
// Determine if the header can collapse
|
||||||
const hasCollapse = this.collapse === 'condense';
|
const hasCollapse = this.collapse === 'condense';
|
||||||
const canCollapse = (hasCollapse && getIonMode(this) === 'ios') ? hasCollapse : false;
|
const canCollapse = (hasCollapse && getIonMode(this) === 'ios') ? hasCollapse : false;
|
||||||
|
|
||||||
if (!canCollapse && this.collapsibleHeaderInitialized) {
|
if (!canCollapse && this.collapsibleHeaderInitialized) {
|
||||||
this.destroyCollapsibleHeader();
|
this.destroyCollapsibleHeader();
|
||||||
} else if (canCollapse && !this.collapsibleHeaderInitialized) {
|
} else if (canCollapse && !this.collapsibleHeaderInitialized) {
|
||||||
const tabs = this.el.closest('ion-tabs');
|
const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
|
||||||
const page = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
|
|
||||||
|
|
||||||
const pageEl = (tabs) ? tabs : (page) ? page : null;
|
|
||||||
const contentEl = (pageEl) ? pageEl.querySelector('ion-content') : null;
|
const contentEl = (pageEl) ? pageEl.querySelector('ion-content') : null;
|
||||||
|
|
||||||
await this.setupCollapsibleHeader(contentEl, pageEl);
|
await this.setupCollapsibleHeader(contentEl, pageEl);
|
||||||
@ -101,21 +97,17 @@ export class Header implements ComponentInterface {
|
|||||||
|
|
||||||
setHeaderActive(mainHeaderIndex, false);
|
setHeaderActive(mainHeaderIndex, false);
|
||||||
|
|
||||||
// TODO: Find a better way to do this
|
readTask(() => {
|
||||||
let remainingHeight = 0;
|
const mainHeaderHeight = mainHeaderIndex.el.clientHeight;
|
||||||
for (let i = 1; i <= scrollHeaderIndex.toolbars.length - 1; i++) {
|
|
||||||
remainingHeight += scrollHeaderIndex.toolbars[i].el.clientHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle interaction between toolbar collapse and
|
* Handle interaction between toolbar collapse and
|
||||||
* showing/hiding content in the primary ion-header
|
* showing/hiding content in the primary ion-header
|
||||||
|
* as well as progressively showing/hiding the main header
|
||||||
|
* border as the top-most toolbar collapses or expands.
|
||||||
*/
|
*/
|
||||||
const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); };
|
const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); };
|
||||||
|
this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: [0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` });
|
||||||
readTask(() => {
|
|
||||||
const mainHeaderHeight = mainHeaderIndex.el.clientHeight;
|
|
||||||
this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: 0.25, rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` });
|
|
||||||
this.intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el);
|
this.intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -124,7 +116,7 @@ export class Header implements ComponentInterface {
|
|||||||
* showing/hiding border on last toolbar
|
* showing/hiding border on last toolbar
|
||||||
* in primary header
|
* in primary header
|
||||||
*/
|
*/
|
||||||
this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, mainHeaderIndex, scrollHeaderIndex, remainingHeight); };
|
this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, scrollHeaderIndex); };
|
||||||
this.scrollEl.addEventListener('scroll', this.contentScrollCallback);
|
this.scrollEl.addEventListener('scroll', this.contentScrollCallback);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -49,20 +49,13 @@ export const createHeaderIndex = (headerEl: HTMLElement | undefined): HeaderInde
|
|||||||
} as HeaderIndex;
|
} as HeaderIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleContentScroll = (scrollEl: HTMLElement, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex, remainingHeight = 0) => {
|
export const handleContentScroll = (scrollEl: HTMLElement, scrollHeaderIndex: HeaderIndex) => {
|
||||||
readTask(() => {
|
readTask(() => {
|
||||||
const scrollTop = scrollEl.scrollTop;
|
const scrollTop = scrollEl.scrollTop;
|
||||||
const lastMainToolbar = mainHeaderIndex.toolbars[mainHeaderIndex.toolbars.length - 1];
|
|
||||||
|
|
||||||
const scale = clamp(1, 1 + (-scrollTop / 500), 1.1);
|
const scale = clamp(1, 1 + (-scrollTop / 500), 1.1);
|
||||||
|
|
||||||
const borderOpacity = clamp(0, (scrollTop - remainingHeight) / lastMainToolbar.el.clientHeight, 1);
|
|
||||||
const maxOpacity = 1;
|
|
||||||
const scaledOpacity = borderOpacity * maxOpacity;
|
|
||||||
|
|
||||||
writeTask(() => {
|
writeTask(() => {
|
||||||
scaleLargeTitles(scrollHeaderIndex.toolbars, scale);
|
scaleLargeTitles(scrollHeaderIndex.toolbars, scale);
|
||||||
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], (scaledOpacity === 1) ? undefined : scaledOpacity);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -75,6 +68,13 @@ const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | un
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleToolbarBorderIntersection = (ev: any, mainHeaderIndex: HeaderIndex) => {
|
||||||
|
if (!ev[0].isIntersecting) { return; }
|
||||||
|
|
||||||
|
const scale = ((1 - ev[0].intersectionRatio) * 100) / 75;
|
||||||
|
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], (scale === 1) ? undefined : scale);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If toolbars are intersecting, hide the scrollable toolbar content
|
* If toolbars are intersecting, hide the scrollable toolbar content
|
||||||
* and show the primary toolbar content. If the toolbars are not intersecting,
|
* and show the primary toolbar content. If the toolbars are not intersecting,
|
||||||
@ -82,7 +82,10 @@ const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | un
|
|||||||
*/
|
*/
|
||||||
export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex) => {
|
export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex) => {
|
||||||
writeTask(() => {
|
writeTask(() => {
|
||||||
|
handleToolbarBorderIntersection(ev, mainHeaderIndex);
|
||||||
|
|
||||||
const event = ev[0];
|
const event = ev[0];
|
||||||
|
|
||||||
const intersection = event.intersectionRect;
|
const intersection = event.intersectionRect;
|
||||||
const intersectionArea = intersection.width * intersection.height;
|
const intersectionArea = intersection.width * intersection.height;
|
||||||
const rootArea = event.rootBounds.width * event.rootBounds.height;
|
const rootArea = event.rootBounds.width * event.rootBounds.height;
|
||||||
@ -114,6 +117,7 @@ export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex,
|
|||||||
if (hasValidIntersection) {
|
if (hasValidIntersection) {
|
||||||
setHeaderActive(mainHeaderIndex);
|
setHeaderActive(mainHeaderIndex);
|
||||||
setHeaderActive(scrollHeaderIndex, false);
|
setHeaderActive(scrollHeaderIndex, false);
|
||||||
|
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -126,7 +130,6 @@ export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => {
|
|||||||
} else {
|
} else {
|
||||||
headerIndex.el.classList.add('header-collapse-condense-inactive');
|
headerIndex.el.classList.add('header-collapse-condense-inactive');
|
||||||
}
|
}
|
||||||
setToolbarBackgroundOpacity(headerIndex.toolbars[0], (active) ? undefined : 0);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user