in packages/editor-core/src/widgets/tip/utils.ts [106:187]
export function resolvePosition(popup: any, target: any, arrow: any, bounds: any, prefer: any) {
popup = {
extraOffset: arrow.height,
top: popup.top,
right: popup.right,
left: popup.left,
bottom: popup.bottom,
height: popup.height,
width: popup.width,
};
const prefers = resolvePrefer(prefer, target, bounds);
const edge = resolveEdge(popup, target, arrow, bounds);
// 选择方向
const dir = resolveDirection(popup, target, edge, bounds, prefers);
let top;
let left;
let arrowTop;
let arrowLeft;
// 或得该方位上横向 或 纵向的 偏移
if (dir === 'top' || dir === 'bottom') {
if (dir === 'top') {
top = target.top - popup.extraOffset - popup.height;
} else {
top = target.bottom + popup.extraOffset;
}
// 解决横向偏移
const offset = arrow.width > target.width ? (arrow.width - target.width) / 2 : 0;
const minLeft = target.left + arrow.width - offset - popup.width;
const maxLeft = target.right - arrow.width + offset;
const centerLeft = target.left - (popup.width - target.width) / 2;
if (prefers.offset === 'left') {
left = minLeft;
} else if (prefers.offset === 'right') {
left = maxLeft;
} else {
left = centerLeft;
}
if (!prefers.forceOffset) {
left = Math.max(Math.min(edge.right - popup.width, left), minLeft);
left = Math.min(Math.max(edge.left, left), maxLeft);
}
arrowLeft = Math.min(popup.width - arrow.width, Math.max(target.left - (arrow.width - target.width) / 2 - left, 0));
} else {
if (dir === 'left') {
left = target.left - popup.extraOffset - popup.width;
} else {
left = target.right + popup.extraOffset;
}
// 解决纵向偏移
const offset = arrow.width > target.height ? (arrow.width - target.height) / 2 : 0;
const minTop = target.top + arrow.width - offset - popup.height;
const maxTop = target.bottom - arrow.width + offset;
const centerTop = target.top - (popup.height - target.height) / 2;
if (prefers.offset === 'top') {
top = minTop;
} else if (prefers.offset === 'bottom') {
top = maxTop;
} else {
top = centerTop;
}
if (!prefers.forceOffset) {
top = Math.max(Math.min(edge.bottom - popup.height, top), minTop);
top = Math.min(Math.max(edge.top, top), maxTop);
}
arrowTop = Math.min(popup.height - arrow.height, Math.max(target.top - (arrow.width - target.height) / 2 - top, 0));
}
return { dir, left, top, arrowLeft, arrowTop };
}