UNPKG

shineout

Version:

Shein 前端组件库

90 lines (84 loc) 3.19 kB
import { docScroll, docSize } from './document' import { PopoverPositionType } from '../../Popover/Props' interface PositionInfo { top?: number left?: number right?: number bottom?: number } const posKeys = ['left', 'top', 'bottom', 'right'] export const getPosition = ( position: PopoverPositionType, el: HTMLElement, container: HTMLElement | undefined = document.body ) => { const rect = el.getBoundingClientRect() let containerRect = { top: 0, left: 0, bottom: 0, right: 0 } if (container.tagName === 'BODY') container = undefined if (container) containerRect = container.getBoundingClientRect() const scrollTop = container ? 0 : docScroll.top const scrollLeft = container ? 0 : docScroll.left const pos: PositionInfo = {} switch (position) { case 'top-left': pos.left = scrollLeft + rect.left - containerRect.left pos.top = scrollTop + rect.top - containerRect.top break case 'top': pos.left = scrollLeft + rect.left - containerRect.left + rect.width / 2 pos.top = scrollTop + rect.top - containerRect.top break case 'top-right': pos.right = (containerRect.right || docSize.width) - rect.right - scrollLeft pos.top = scrollTop + rect.top - containerRect.top break case 'left-top': pos.left = scrollLeft + rect.left - containerRect.left pos.top = scrollTop + rect.top - containerRect.top break case 'left': pos.left = scrollLeft + rect.left - containerRect.left pos.top = scrollTop + rect.top - containerRect.top + rect.height / 2 break case 'left-bottom': pos.left = scrollLeft + rect.left - containerRect.left pos.top = scrollTop + rect.bottom - containerRect.bottom break case 'right-top': pos.left = scrollLeft + rect.left - containerRect.left + rect.width pos.top = scrollTop + rect.top - containerRect.top break case 'right': pos.left = scrollLeft + rect.left - containerRect.left + rect.width pos.top = scrollTop + rect.top - containerRect.top + rect.height / 2 break case 'right-bottom': pos.left = scrollLeft + rect.left - containerRect.left + rect.width pos.top = scrollTop + rect.bottom - containerRect.bottom break case 'bottom-left': pos.left = scrollLeft + rect.left - containerRect.left pos.top = scrollTop + rect.top - containerRect.top + rect.height break case 'bottom': pos.left = scrollLeft + rect.left - containerRect.left + rect.width / 2 pos.top = scrollTop + rect.top - containerRect.top + rect.height break case 'bottom-right': pos.right = (containerRect.right || docSize.width) - rect.right - scrollLeft pos.top = scrollTop + rect.top - containerRect.top + rect.height break case 'cover': pos.left = scrollLeft + rect.left - containerRect.left pos.top = scrollTop + rect.top - containerRect.top break default: } return posKeys.reduce( (data, key: keyof PositionInfo) => ({ ...data, [key]: typeof pos[key] === 'number' ? `${Math.round(pos[key]!)}px` : 'auto', }), {} as Record<keyof PositionInfo, string> ) }