UNPKG

@opensig/opendesign

Version:

221 lines (220 loc) 7.09 kB
import { easeInOutCubic } from "./easing.mjs"; import { throttleRAF } from "./helper.mjs"; import { isWindow, isFunction } from "./is.mjs"; function isDocument(val) { return val instanceof Document || (val == null ? void 0 : val.constructor.name) === "HTMLDocument"; } function isHtmlElement(el) { if (typeof HTMLElement === "object") { return el instanceof HTMLElement; } else if (el && typeof el === "object") { const ele = el; return (ele.nodeType === 1 || ele.nodeType === 9) && typeof ele.nodeName === "string"; } return false; } function getOffsetElement(el) { const offsetEl = el.offsetParent; if (offsetEl && offsetEl.tagName === "BODY") { const stylePosition = window.getComputedStyle(document.body).getPropertyValue("position"); if (stylePosition === "static") { return document.documentElement; } } return offsetEl; } function getScroll(el) { const rlt = { scrollLeft: 0, scrollTop: 0 }; if (!el) { return rlt; } if (isWindow(el)) { rlt.scrollLeft = window.scrollX; rlt.scrollTop = window.scrollY; } else if (isDocument(el)) { rlt.scrollLeft = el.documentElement.scrollLeft; rlt.scrollTop = el.documentElement.scrollTop; } else { rlt.scrollLeft = el.scrollLeft; rlt.scrollTop = el.scrollTop; } return rlt; } function getScrollParents(el) { const parents = []; let ele = el == null ? void 0 : el.parentElement; while (ele && ele !== document.documentElement) { const { offsetHeight, offsetWidth, scrollHeight, scrollWidth } = ele; if (offsetHeight < scrollHeight || offsetWidth < scrollWidth) { parents.push(ele); } ele = ele.parentElement; } return parents; } function findClosestElementWithClass(target, className, rootContainer) { if (!(target instanceof HTMLElement)) { return null; } let currentElement = target; while (currentElement && currentElement !== rootContainer) { if (currentElement.classList && currentElement.classList.contains(className)) { return currentElement; } currentElement = currentElement.parentElement; } return null; } function getElementSize(el) { return { width: el.innerWidth || el.clientWidth, height: el.innerHeight || el.clientHeight, offsetWidth: el.innerWidth || el.offsetWidth, offsetHeight: el.innerHeight || el.offsetHeight }; } function getElementRectByRAF(el) { return new Promise((resolve) => { const checkLayout = () => { const rect = el.getBoundingClientRect(); if (rect.width > 0 || rect.height > 0) { resolve(rect); } else { requestAnimationFrame(checkLayout); } }; requestAnimationFrame(checkLayout); }); } function getCssVariable(key, el) { const ele = el ? el : document.documentElement; return window.getComputedStyle(ele).getPropertyValue(key); } function supportTouch() { return "ontouchstart" in window; } let cancelScrollRAF = null; function scrollTo(y, opts) { const { container = window, duration = 450 } = opts; const { scrollTop } = getScroll(container); const startTime = Date.now(); if (isFunction(cancelScrollRAF)) { cancelScrollRAF(); cancelScrollRAF = null; } return new Promise((resolve) => { const frameFn = () => { const timeStamp = Date.now(); const time = timeStamp - startTime; const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration); if (isWindow(container)) { window.scrollTo({ left: window.scrollX, top: nextScrollTop, behavior: "instant" }); } else if (isDocument(container)) { container.documentElement.scrollTop = nextScrollTop; } else { container.scrollTop = nextScrollTop; } if (time < duration) { const fn = throttleRAF(frameFn); cancelScrollRAF = fn.cancel; fn(); } else { throttleRAF(resolve)(); } }; throttleRAF(frameFn)(); }); } function isOverflown(element) { if (!element) { return false; } return element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight; } function checkElementOverflowHorizontal(options) { const { element, parentElement, threshold = 0 } = options; if (!(element instanceof HTMLElement)) { throw new Error("参数必须是有效的HTMLElement"); } const scrollParent = parentElement ? parentElement : getScrollParents(element)[0]; if (!scrollParent) { return { isOverflowLeft: false, isOverflowRight: false, overflowLeft: 0, overflowRight: 0 }; } const elementRect = element.getBoundingClientRect(); const parentRect = scrollParent.getBoundingClientRect(); const elementLeftRelativeToParent = elementRect.left - parentRect.left + scrollParent.scrollLeft; const elementRightRelativeToParent = elementLeftRelativeToParent + elementRect.width; const parentVisibleLeft = scrollParent.scrollLeft; const parentVisibleRight = scrollParent.scrollLeft + scrollParent.clientWidth; const overflowLeft = parentVisibleLeft - elementLeftRelativeToParent; const isOverflowLeft = overflowLeft > threshold; const overflowRight = elementRightRelativeToParent - parentVisibleRight; const isOverflowRight = overflowRight > threshold; return { isOverflowLeft, isOverflowRight, overflowLeft, overflowRight }; } function checkElementOverflowVertical(options) { const { element, parentElement, threshold = 0 } = options; if (!(element instanceof HTMLElement)) { throw new Error("参数必须是有效的HTMLElement"); } const scrollParent = parentElement ? parentElement : getScrollParents(element)[0]; if (!scrollParent) { return { isOverflowTop: false, isOverflowBottom: false, overflowTop: 0, overflowBottom: 0 }; } const elementRect = element.getBoundingClientRect(); const parentRect = scrollParent.getBoundingClientRect(); const elementTopRelativeToParent = elementRect.top - parentRect.top + scrollParent.scrollTop; const elementBottomRelativeToParent = elementTopRelativeToParent + elementRect.height; const parentVisibleTop = scrollParent.scrollTop; const parentVisibleBottom = scrollParent.scrollTop + scrollParent.clientHeight; const overflowTop = parentVisibleTop - elementTopRelativeToParent; const isOverflowTop = overflowTop > threshold; const overflowBottom = elementBottomRelativeToParent - parentVisibleBottom; const isOverflowBottom = overflowBottom > threshold; return { isOverflowTop, isOverflowBottom, overflowTop, overflowBottom }; } function checkElementOverflow(options) { return { ...checkElementOverflowHorizontal(options), ...checkElementOverflowVertical(options) }; } export { checkElementOverflow, checkElementOverflowHorizontal, checkElementOverflowVertical, findClosestElementWithClass, getCssVariable, getElementRectByRAF, getElementSize, getOffsetElement, getScroll, getScrollParents, isDocument, isHtmlElement, isOverflown, scrollTo, supportTouch };