UNPKG

@v4fire/client

Version:

V4Fire client core library

122 lines (104 loc) 2.79 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ import type { ElementRect } from 'core/dom/in-view/interface'; // tslint:disable-next-line strict-type-predicates export const hasMutationObserver = typeof MutationObserver === 'function'; /** * Returns the top offset relative to the root * * @param root * @param el */ export function getOffsetTop({scrollTop}: RootRect, {top}: DOMRect | ClientRect): number { return top + scrollTop; } /** * Returns the left offset relative to the root * * @param root * @param el */ export function getOffsetLeft({scrollLeft}: RootRect, {left}: DOMRect | ClientRect): number { return left + scrollLeft; } /** * Returns true if an element is visible * @param rect */ export function isElementVisible(rect: {width: number; height: number}): boolean { return rect.width > 0 && rect.height > 0; } /** * Returns an element geometry relative to the root * * @param root * @param el */ export function getElementRect(root: RootRect, el: Element): ElementRect { const rect = el.getBoundingClientRect(), {width, height} = rect; const top = getOffsetTop(root, rect), left = getOffsetLeft(root, rect); return { bottom: top + height, right: left + width, top, left, width, height }; } /** * Returns the page root */ export function getRoot(): Element { return document.documentElement; } /** * Returns the root element geometry */ export function getRootRect(): RootRect { const r = getRoot(), s = <Element>document.scrollingElement; return { width: r.clientWidth, height: r.clientHeight, scrollLeft: s.scrollLeft, scrollTop: s.scrollTop }; } interface RootRect { width: number; height: number; scrollTop: number; scrollLeft: number; } /** * Returns true if the specified element is in view * * @param elRect * @param rootRect * @param threshold */ export function isElementInView(elRect: ElementRect, rootRect: RootRect, threshold: number): boolean { if (elRect.width === 0 || elRect.height === 0) { return false; } const isBoxInRootY = rootRect.scrollTop + rootRect.height >= elRect.top + elRect.height * threshold, isBoxInRootX = rootRect.scrollLeft + rootRect.width >= elRect.left + elRect.width * threshold, isVisibleYTop = elRect.top + elRect.height * threshold >= rootRect.scrollTop, isVisibleYBottom = elRect.bottom - elRect.height * threshold < rootRect.scrollTop, isVisibleX = elRect.left > 0 ? elRect.left - elRect.width * threshold <= rootRect.scrollLeft + rootRect.width : elRect.left + elRect.width * threshold >= rootRect.scrollLeft; return isBoxInRootY && isBoxInRootX && isVisibleYTop && isVisibleX && !isVisibleYBottom; }