UNPKG

@ucloud-fe/react-components

Version:
118 lines (88 loc) 4.18 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _utils = _interopRequireDefault(require("./utils")); var _getOffsetParent = _interopRequireDefault(require("./getOffsetParent")); var _isAncestorFixed = _interopRequireDefault(require("./isAncestorFixed")); /** * 获得元素的显示部分的区域 */ function getVisibleRectForElement(element, alwaysByViewport) { var visibleRect = { left: 0, right: Infinity, top: 0, bottom: Infinity }; var el = (0, _getOffsetParent.default)(element); var doc = _utils.default.getDocument(element); var win = doc.defaultView || doc.parentWindow; var body = doc.body; var documentElement = doc.documentElement; // Determine the size of the visible rect by climbing the dom accounting for // all scrollable containers. while (el) { // clientWidth is zero for inline block elements in ie. if ((navigator.userAgent.indexOf('MSIE') === -1 || el.clientWidth !== 0) && // body may have overflow set on it, yet we still get the entire // viewport. In some browsers, el.offsetParent may be // document.documentElement, so check for that too. el !== body && el !== documentElement && _utils.default.css(el, 'overflow') !== 'visible') { var pos = _utils.default.offset(el); // add border pos.left += el.clientLeft; pos.top += el.clientTop; visibleRect.top = Math.max(visibleRect.top, pos.top); visibleRect.right = Math.min(visibleRect.right, // consider area without scrollBar pos.left + el.clientWidth); visibleRect.bottom = Math.min(visibleRect.bottom, pos.top + el.clientHeight); visibleRect.left = Math.max(visibleRect.left, pos.left); } else if (el === body || el === documentElement) { break; } el = (0, _getOffsetParent.default)(el); } // Set element position to fixed // make sure absolute element itself don't affect it's visible area // https://github.com/ant-design/ant-design/issues/7601 var originalPosition = null; if (!_utils.default.isWindow(element) && element.nodeType !== 9) { originalPosition = element.style.position; var position = _utils.default.css(element, 'position'); if (position === 'absolute') { element.style.position = 'fixed'; } } var scrollX = _utils.default.getWindowScrollLeft(win); var scrollY = _utils.default.getWindowScrollTop(win); var viewportWidth = _utils.default.viewportWidth(win); var viewportHeight = _utils.default.viewportHeight(win); var documentWidth = documentElement.scrollWidth; var documentHeight = documentElement.scrollHeight; // scrollXXX on html is sync with body which means overflow: hidden on body gets wrong scrollXXX. // We should cut this ourself. var bodyStyle = window.getComputedStyle(body); if (bodyStyle.overflowX === 'hidden') { documentWidth = win.innerWidth; } if (bodyStyle.overflowY === 'hidden') { documentHeight = win.innerHeight; } // Reset element position after calculate the visible area if (element.style) { element.style.position = originalPosition; } if (alwaysByViewport || (0, _isAncestorFixed.default)(element)) { // Clip by viewport's size. visibleRect.left = Math.max(visibleRect.left, scrollX); visibleRect.top = Math.max(visibleRect.top, scrollY); visibleRect.right = Math.min(visibleRect.right, scrollX + viewportWidth); visibleRect.bottom = Math.min(visibleRect.bottom, scrollY + viewportHeight); } else { // Clip by document's size. var maxVisibleWidth = Math.max(documentWidth, scrollX + viewportWidth); visibleRect.right = Math.min(visibleRect.right, maxVisibleWidth); var maxVisibleHeight = Math.max(documentHeight, scrollY + viewportHeight); visibleRect.bottom = Math.min(visibleRect.bottom, maxVisibleHeight); } return visibleRect.top >= 0 && visibleRect.left >= 0 && visibleRect.bottom > visibleRect.top && visibleRect.right > visibleRect.left ? visibleRect : null; } var _default = getVisibleRectForElement; exports.default = _default;