@ucloud-fe/react-components
Version:
UCloud react components
118 lines (88 loc) • 4.18 kB
JavaScript
"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;