naive-ui/packages/utils/dom/calcPlacementTransform.js

97 lines
4.3 KiB
JavaScript
Raw Normal View History

2019-07-26 17:58:25 +08:00
export default function calcPlacementTransform (placement, activatorRect, contentRect) {
let contentLeft = null
let contentTop = null
let contentRight = null
let contentBottom = null
2019-12-23 17:40:37 +08:00
let suggesetedTransfromOrigin
if (placement === 'top-start') {
2019-07-26 17:58:25 +08:00
contentTop = activatorRect.top - contentRect.height
contentLeft = activatorRect.left
2019-09-27 22:27:25 +08:00
suggesetedTransfromOrigin = 'bottom left'
} else if (placement === 'top') {
2019-07-26 17:58:25 +08:00
contentTop = activatorRect.top - contentRect.height
contentLeft = activatorRect.left + activatorRect.width / 2 - contentRect.width / 2
2019-09-05 18:06:01 +08:00
suggesetedTransfromOrigin = 'bottom'
} else if (placement === 'top-end') {
2019-07-26 17:58:25 +08:00
contentTop = activatorRect.top - contentRect.height
contentLeft = activatorRect.left + activatorRect.width - contentRect.width
suggesetedTransfromOrigin = 'bottom right'
} else if (placement === 'left-start') {
contentTop = activatorRect.top
2019-07-26 17:58:25 +08:00
contentLeft = activatorRect.left - contentRect.width
2019-09-27 22:27:25 +08:00
suggesetedTransfromOrigin = 'top right'
} else if (placement === 'left') {
2019-07-26 17:58:25 +08:00
contentTop = activatorRect.top + activatorRect.height / 2 - contentRect.height / 2
contentLeft = activatorRect.left - contentRect.width
2019-09-27 22:27:25 +08:00
suggesetedTransfromOrigin = 'center right'
} else if (placement === 'left-end') {
2019-07-26 17:58:25 +08:00
contentTop = activatorRect.top + activatorRect.height - contentRect.height
contentLeft = activatorRect.left - contentRect.width
2019-09-27 22:27:25 +08:00
suggesetedTransfromOrigin = 'bottom right'
} else if (placement === 'right-start') {
2019-12-17 14:36:37 +08:00
const toWindowBottom = window.innerHeight - activatorRect.top - contentRect.height
const toWindowRight = window.innerWidth - activatorRect.right - contentRect.width
if (toWindowBottom < 0) {
contentBottom = window.innerHeight - activatorRect.bottom
suggesetedTransfromOrigin = 'bottom'
} else {
contentTop = activatorRect.top
suggesetedTransfromOrigin = 'top'
}
if (toWindowRight < 0) {
contentRight = window.innerWidth - activatorRect.left
suggesetedTransfromOrigin += ' right'
} else {
contentLeft = activatorRect.left + activatorRect.width
suggesetedTransfromOrigin += ' left'
}
} else if (placement === 'right') {
2019-07-26 17:58:25 +08:00
contentTop = activatorRect.top + activatorRect.height / 2 - contentRect.height / 2
contentLeft = activatorRect.left + activatorRect.width
2019-09-27 22:27:25 +08:00
suggesetedTransfromOrigin = 'center left'
} else if (placement === 'right-end') {
2019-07-26 17:58:25 +08:00
contentTop = activatorRect.top + activatorRect.height - contentRect.height
contentLeft = activatorRect.left + activatorRect.width
2019-09-27 22:27:25 +08:00
suggesetedTransfromOrigin = 'bottom left'
} else if (placement === 'bottom-start') {
const toWindowBottom = window.innerHeight - activatorRect.bottom
2019-10-17 14:03:09 +08:00
const toWindowRight = window.innerWidth - activatorRect.left - contentRect.width
if (contentRect.height > toWindowBottom && activatorRect.top > toWindowBottom) {
contentBottom = toWindowBottom + activatorRect.height
2019-12-17 15:42:55 +08:00
// contentTop = null
2019-10-17 14:03:09 +08:00
suggesetedTransfromOrigin = 'bottom'
} else {
contentTop = activatorRect.top + activatorRect.height
2019-12-17 15:42:55 +08:00
// contentBottom = null
2019-10-17 14:03:09 +08:00
suggesetedTransfromOrigin = 'top'
}
if (toWindowRight < 0) {
contentLeft = activatorRect.right - contentRect.width
suggesetedTransfromOrigin += ' right'
} else {
contentLeft = activatorRect.left
suggesetedTransfromOrigin += ' left'
}
} else if (placement === 'bottom-end') {
contentTop = activatorRect.top + activatorRect.height
2019-07-26 17:58:25 +08:00
contentLeft = activatorRect.left + activatorRect.width - contentRect.width
2019-09-27 22:27:25 +08:00
suggesetedTransfromOrigin = 'top right'
} else {
contentTop = activatorRect.top + activatorRect.height
2019-07-26 17:58:25 +08:00
contentLeft = activatorRect.left + activatorRect.width / 2 - contentRect.width / 2
2019-08-16 16:48:36 +08:00
suggesetedTransfromOrigin = 'top center'
}
/**
* We could also change the position using transform.
* Such as return `transform: translateX(${contentLeft}px) translateY(${contentTop}px);`
* However, I found that the dom delay is very serious.
* So I decide to use left and top for now.
*/
return [{
left: contentLeft && `${contentLeft}px`,
top: contentTop && `${contentTop}px`,
2019-10-17 14:03:09 +08:00
right: contentRight && `${contentRight}px`,
bottom: contentBottom && `${contentBottom}px`
}, suggesetedTransfromOrigin]
}