2021-10-21 22:42:47 +08:00
|
|
|
// @ts-noCheck
|
2021-10-21 18:16:42 +08:00
|
|
|
// 是否滚动
|
|
|
|
export const hasScrollbar = () =>
|
|
|
|
document.body.scrollHeight >
|
|
|
|
(window.innerHeight || document.documentElement.clientHeight)
|
|
|
|
// 窗口宽高
|
|
|
|
export const winArea = (type?: any) =>
|
|
|
|
document.documentElement[type ? 'clientWidth' : 'clientHeight']
|
|
|
|
//
|
|
|
|
export const scrollArea: any = (type: any) => {
|
|
|
|
type = type ? 'scrollLeft' : 'scrollTop'
|
|
|
|
return document.body[type] | document.documentElement[type]
|
|
|
|
}
|
|
|
|
|
|
|
|
export function usePosition(elem?: any, elemView?: any, obj?: any) {
|
|
|
|
if (!elemView) return
|
|
|
|
obj = obj || {}
|
|
|
|
|
|
|
|
//如果绑定的是 document 或 body 元素,则直接获取鼠标坐标
|
|
|
|
if (elem === document || elem.name === 'body') {
|
|
|
|
obj.clickType = 'right'
|
|
|
|
}
|
|
|
|
|
|
|
|
//绑定绑定元素的坐标
|
|
|
|
const rect =
|
|
|
|
obj.clickType === 'right'
|
|
|
|
? (function () {
|
|
|
|
const e = obj.e || window.event || {}
|
|
|
|
return {
|
|
|
|
left: e.clientX,
|
|
|
|
top: e.clientY,
|
|
|
|
right: e.clientX,
|
|
|
|
bottom: e.clientY,
|
|
|
|
}
|
|
|
|
})()
|
|
|
|
: elem.getBoundingClientRect()
|
|
|
|
const elemWidth = elemView.offsetWidth //控件的宽度
|
|
|
|
const elemHeight = elemView.offsetHeight //控件的高度
|
|
|
|
|
|
|
|
const margin = 5
|
|
|
|
let left = rect.left
|
|
|
|
let top = rect.bottom
|
|
|
|
|
|
|
|
//相对元素居中
|
|
|
|
if (obj.align === 'center') {
|
|
|
|
left = left - (elemWidth - elem.offsetWidth) / 2
|
|
|
|
} else if (obj.align === 'right') {
|
|
|
|
left = left - elemWidth + elem.offsetWidth
|
|
|
|
}
|
|
|
|
|
|
|
|
//判断右侧是否超出边界
|
|
|
|
if (left + elemWidth + margin > winArea('width')) {
|
|
|
|
left = winArea('width') - elemWidth - margin //如果超出右侧,则将面板向右靠齐
|
|
|
|
}
|
|
|
|
//左侧是否超出边界
|
|
|
|
if (left < margin) left = margin
|
|
|
|
|
|
|
|
//判断底部和顶部是否超出边界
|
|
|
|
if (top + elemHeight + margin > winArea()) {
|
|
|
|
//优先顶部是否有足够区域显示完全
|
|
|
|
if (rect.top > elemHeight + margin) {
|
|
|
|
top = rect.top - elemHeight - margin * 2 //顶部有足够的区域显示
|
|
|
|
} else {
|
|
|
|
//如果面板是鼠标右键弹出,且顶部没有足够区域显示,则将面板向底部靠齐
|
|
|
|
if (obj.clickType === 'right') {
|
|
|
|
top = winArea() - elemHeight - margin * 2
|
|
|
|
if (top < 0) top = 0 //不能溢出窗口顶部
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//定位类型
|
|
|
|
const position = obj.position
|
|
|
|
if (position) elemView.style.position = position
|
|
|
|
|
|
|
|
//设置坐标
|
|
|
|
elemView.style.left = left + (position === 'fixed' ? 0 : scrollArea(1)) + 'px'
|
|
|
|
elemView.style.top = top + (position === 'fixed' ? 0 : scrollArea()) + 'px'
|
|
|
|
|
|
|
|
//防止页面无滚动条时,又因为弹出面板而出现滚动条导致的坐标计算偏差
|
|
|
|
if (!hasScrollbar()) {
|
|
|
|
const rect1 = elemView.getBoundingClientRect()
|
|
|
|
//如果弹出面板的溢出窗口底部,则表示将出现滚动条,此时需要重新计算坐标
|
|
|
|
if (!obj.SYSTEM_RELOAD && rect1.bottom + margin > winArea()) {
|
|
|
|
obj.SYSTEM_RELOAD = true
|
|
|
|
setTimeout(function () {
|
|
|
|
usePosition(elem, elemView, obj)
|
|
|
|
}, 50)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|