import { Store } from '@/lib/store'; import { nextTick } from '@vue/composition-api'; import { RIGHT_MENU_SHADOW_PX_BUFFER } from '@/lib/constants/dom-buffer'; export class BodyMenuOperator { private readonly store: Store; private getBodyDom: () => Element; private getMenuDom: () => Element; constructor(store: Store) { this.store = store; } public concatDom(getGridDom: () => Element, getMenuDom: () => Element) { this.getBodyDom = getGridDom; this.getMenuDom = getMenuDom; } public async active(e: PointerEvent) { const girdElement = this.getBodyDom(); this.store.mutation.inactiveRightMenu(); const bodyLocation = girdElement.getBoundingClientRect(); const scrollTop = girdElement.scrollTop; const scrollLeft = girdElement.scrollLeft; // 弹窗位置 const targetY = e.clientY - bodyLocation.y + scrollTop; const targetX = e.clientX - bodyLocation.x + scrollLeft; this.store.mutation.activeRightMenu(targetY, targetX); await nextTick(); // 弹窗自身宽高 const menuElement = this.getMenuDom(); const menuHeight = menuElement.clientHeight; const menuWidth = menuElement.clientWidth; // 视图边界 X const maxY = scrollTop + girdElement.clientHeight; const maxX = scrollLeft + girdElement.clientWidth; // 视图边界 Y this.store.mutation.activeRightMenu( Math.min(targetY, maxY - menuHeight - RIGHT_MENU_SHADOW_PX_BUFFER), Math.min(targetX, maxX - menuWidth - RIGHT_MENU_SHADOW_PX_BUFFER), ); } public inactive() { this.store.mutation.inactiveRightMenu(); } }