export function resolvePosition()

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 };
}