refactor(tooltip): refactor tooltip add useCalculatePosition and useAdjust-position

This commit is contained in:
Sagi 2022-10-15 16:28:06 +08:00
parent f10e8b849d
commit fbaeb43a8a
4 changed files with 121 additions and 135 deletions

View File

@ -6,7 +6,11 @@ export type RectSizeProperty = 'height' | 'width';
export interface RectPosition {
top: number;
left: number;
right: number;
right?: number;
}
export interface TooltipPosition {
arrow: RectPosition;
tooltip: RectPosition;
}
export interface UseTooltipPosition {
@ -14,3 +18,13 @@ export interface UseTooltipPosition {
tooltipPosition: ComputedRef<RectPosition>;
arrowPosition: ComputedRef<RectPosition>;
}
export interface UseCalculatePosition {
calculate: (
placementAndAlignment: TooltipPlacement,
hostBound: DOMRect,
tooltipBound: DOMRect,
tooltipContentBound: DOMRect,
arrowBound: DOMRect
) => TooltipPosition;
}

View File

@ -0,0 +1,13 @@
import { SetupContext } from "vue";
import { TooltipProps } from "../tooltip.props";
export function useTooltipPosition(
props: TooltipProps,
context: SetupContext,
hostBound: DOMRect,
tooltipContentBound: DOMRect,
tooltipBound: DOMRect,
arrowBound: DOMRect) {
}

View File

@ -0,0 +1,93 @@
import { SetupContext } from "vue";
import { TooltipPlacement, TooltipProps } from "../tooltip.props";
import { RectPosition } from "./types";
export function useCalculatePosition(
props: TooltipProps,
context: SetupContext) {
function calculateArrowPosition(
placementAndAlignment: TooltipPlacement,
hostBound: DOMRect,
tooltipPosition: RectPosition,
tooltipContentBound: DOMRect,
arrowBound: DOMRect
): RectPosition {
const placementAndAlignmentArray = placementAndAlignment.split('-');
const placement = placementAndAlignmentArray[0];
const alignment = placementAndAlignmentArray[1] || 'middle';
const offsetX = ['top', 'bottom'].includes(placement) ?
(
alignment === 'middle' ?
(tooltipContentBound.width - arrowBound.width) / 2 :
(alignment === 'right' ? tooltipContentBound.width - arrowBound.width - space : space)
) : 0;
const offsetY = ['left', 'right'].includes(placement) ?
(
alignment === 'middle' ?
(tooltipContentBound.height - arrowBound.height) / 2 :
(alignment === 'bottom' ? tooltipContentBound.height - arrowBound.height - space : space)
) : 0;
const arrowLeft = placement === 'left' ? tooltipContentBound.width + arrowBound.width : 0;
const arrowTop = placement === 'top' ? tooltipContentBound.height + arrowBound.height : 0;
return { left: arrowLeft + offsetX, top: arrowTop + offsetY, right: 0 };
}
function calculateTooltipPosition(
placementAndAlignment: TooltipPlacement,
hostBound: DOMRect,
tooltipBound: DOMRect,
tooltipContentBound: DOMRect,
arrowBound: DOMRect) {
const placementAndAlignmentArray = placementAndAlignment.split('-');
const placement = placementAndAlignmentArray[0];
const alignment = placementAndAlignmentArray[1] || 'middle';
const horizontalMarginSpace = (tooltipBound.width - tooltipContentBound.width) / 2;
const verticalMarginSpace = (tooltipBound.height - tooltipContentBound.height) / 2;
const originalPositionX = placement === 'right' ? hostBound.right : hostBound.left;
const originalPositionY = placement === 'bottom' ? hostBound.bottom : hostBound.top;
const offsetY = placement === 'top' ?
0 - verticalMarginSpace - tooltipContentBound.height - arrowBound.height :
(placement === 'bottom' ? (0 - verticalMarginSpace) + arrowBound.height : 0);
const verticalAlignmentOffset = ['left', 'right'].includes(placement) ?
(
alignment === 'middle' ?
(hostBound.height - tooltipContentBound.height) / 2 :
(alignment === 'bottom' ? hostBound.height - tooltipContentBound.height : 0)
) : 0;
const offsetX = placement === 'left' ?
0 - horizontalMarginSpace - tooltipContentBound.width - arrowBound.width :
(placement === 'right' ? (0 - horizontalMarginSpace) + arrowBound.width : 0);
const horizontalAlignmentOffset = ['top', 'bottom'].includes(placement) ?
(alignment === 'middle' ?
(hostBound.width - tooltipContentBound.width) / 2 :
(alignment === 'right' ? hostBound.width - tooltipContentBound.width : 0)
) : 0;
const top = originalPositionY + offsetY + verticalAlignmentOffset;
const left = originalPositionX + offsetX + horizontalAlignmentOffset;
return { left, top };
}
function calculate(
placementAndAlignment: TooltipPlacement,
hostBound: DOMRect,
tooltipBound: DOMRect,
tooltipContentBound: DOMRect,
arrowBound: DOMRect
) {
const tooltip = calculateTooltipPosition(placementAndAlignment, hostBound, tooltipBound, tooltipContentBound, arrowBound);
const arrow = calculateArrowPosition(placementAndAlignment, hostBound, tooltipBound, tooltipContentBound, arrowBound);
return { arrow, tooltip };
}
return { calculate };
}

View File

@ -1,4 +1,3 @@
import { max } from "lodash";
import { computed, ref, SetupContext } from "vue";
import { TooltipPlacement, TooltipProps } from "../tooltip.props";
import { RectDirection, RectPosition, RectSizeProperty } from "./types";
@ -55,93 +54,7 @@ export function useTooltipPosition(
return rectifyPlacement;
}
function calculateTooltipTopPositoin(
placementAndAlignment: TooltipPlacement,
hostBound: DOMRect,
tooltipContentBound: DOMRect,
arrowBound: DOMRect
) {
const placementAndAlignmentArray = placementAndAlignment.split('-');
const placement = placementAndAlignmentArray[0];
const alignment = placementAndAlignmentArray[1] || 'middle';
const marginSpace = (tooltipBound.height - tooltipContentBound.height) / 2;
const originalPositionY = placement === 'bottom' ? hostBound.bottom : hostBound.top;
const offsetY = placement === 'top' ?
0 - marginSpace - tooltipContentBound.height - arrowBound.height :
(placement === 'bottom' ? (0 - marginSpace) + arrowBound.height : 0);
const offsetAlignment = ['left', 'right'].includes(placement) ?
(
alignment === 'middle' ?
(hostBound.height - tooltipContentBound.height) / 2 :
(alignment === 'bottom' ? hostBound.height - tooltipContentBound.height : 0)
) : 0;
return originalPositionY + offsetY + offsetAlignment;
}
function calculateTooltipLeftPosition(
placementAndAlignment: TooltipPlacement,
hostBound: DOMRect,
tooltipContentBound: DOMRect,
arrowBound: DOMRect
) {
const placementAndAlignmentArray = placementAndAlignment.split('-');
const placement = placementAndAlignmentArray[0];
const alignment = placementAndAlignmentArray[1] || 'middle';
const marginSpace = (tooltipBound.width - tooltipContentBound.width) / 2;
const originalPositionX = placement === 'right' ? hostBound.right : hostBound.left;
const offsetX = placement === 'left' ?
0 - marginSpace - tooltipContentBound.width - arrowBound.width :
(placement === 'right' ? (0 - marginSpace) + arrowBound.width : 0);
const offsetAlignment = ['top', 'bottom'].includes(placement) ?
(
alignment === 'middle' ?
(hostBound.width - tooltipContentBound.width) / 2 :
(alignment === 'right' ? hostBound.width - tooltipContentBound.width : 0)
) : 0;
// let offsetX = 0;
// const horizontalAlignment = placement.indexOf('right') > -1 ? 'right' : (placement.indexOf('left') > -1 ? 'left' : 'center');
// const originalPositionX = horizontalAlignment === 'right' ? hostBound.right : hostBound.left;
// if (['left', 'left-top', 'left-bottom'].includes(placement)) {
// offsetX = 0 - tooltipBound.width - space;
// } else if (['top', 'bottom'].includes(placement)) {
// offsetX = (hostBound.width - tooltipBound.width) / 2;
// } else if (['right', 'right-top', 'right-bottom'].includes(placement)) {
// offsetX = space;
// } else if (['top-right', 'bottom-right'].includes(placement)) {
// offsetX = 0 - tooltipBound.width;
// } else if (['top-left', 'bottom-left'].includes(placement)) {
// offsetX = 0;
// } else {
// return 0;
// }
return originalPositionX + offsetX + offsetAlignment;
}
function calculateTooltipRightPosition(placement: TooltipPlacement, hostBound: DOMRect, tooltipBound: DOMRect, arrowBound: DOMRect) {
let offsetX = 0;
const horizontalAlignment = placement.indexOf('right') > -1 ? 'right' : (placement.indexOf('left') > -1 ? 'left' : 'center');
const originalPositionX = horizontalAlignment === 'right' ? hostBound.right : hostBound.left;
if (['top', 'bottom'].includes(placement)) {
offsetX = (hostBound.width - tooltipBound.width) / 2 + tooltipBound.width;
} else if (['top-left', 'bottom-left'].includes(placement)) {
offsetX = tooltipBound.width;
} else if (['top-right', 'bottom-right'].includes(placement)) {
offsetX = 0;
} else {
return 0;
}
return originalPositionX + offsetX;
}
/**
*
@ -222,54 +135,7 @@ export function useTooltipPosition(
return { left: fixedLeft, top: fixedTop, right: originalPosition.right };
}
function calculateArrowPosition(
placementAndAlignment: TooltipPlacement,
hostBound: DOMRect,
tooltipPosition: RectPosition,
tooltipContentBound: DOMRect,
arrowBound: DOMRect
): RectPosition {
const placementAndAlignmentArray = placementAndAlignment.split('-');
const placement = placementAndAlignmentArray[0];
const alignment = placementAndAlignmentArray[1] || 'middle';
const offsetX = ['top', 'bottom'].includes(placement) ?
(
alignment === 'middle' ?
(tooltipContentBound.width - arrowBound.width) / 2 :
(alignment === 'right' ? tooltipContentBound.width - arrowBound.width - space : space)
) : 0;
const offsetY = ['left', 'right'].includes(placement) ?
(
alignment === 'middle' ?
(tooltipContentBound.height - arrowBound.height) / 2 :
(alignment === 'bottom' ? tooltipContentBound.height - arrowBound.height - space : space)
) : 0;
const arrowLeft = placement === 'left' ? tooltipContentBound.width + arrowBound.width : 0;
const arrowTop = placement === 'top' ? tooltipContentBound.height + arrowBound.height : 0;
return { left: arrowLeft + offsetX, top: arrowTop + offsetY, right: 0 };
// const leftAlignment = placement.endsWith('left');
// const rightAlignment = placement.endsWith('right');
// const topAlignment = placement.endsWith('top');
// const bottomAlignment = placement.endsWith('bottom');
// const offsetX = leftAlignment ? hostBound.width * 0.4 : (rightAlignment ? 0 - hostBound.width * 0.4 : 0);
// const offsetY = topAlignment ? hostBound.height * 0.4 : (bottomAlignment ? 0 - hostBound.height * 0.4 : 0);
// const fixedArrowLeft = tooltipPosition.left - hostBound.left - hostBound.width * 0.5 + arrowBound.width * 0.5 + offsetX;
// const fixedArrowTop = tooltipPositoin.top - hostBound.top - hostBound.height * 0.5 + arrowBound.height * 0.5 + offsetY;
// const fixedArrowLeft = leftAlignment ?
// tooltipContentBound.width + arrowBound.width :
// (rightAlignment ? 0 : (tooltipBound.width - arrowBound.width) / 2);
// const fixedArrowTop = topAlignment ?
// (tooltipBound.height - tooltipContentBound.height) / 2 + tooltipContentBound.height :
// (bottomAlignment ? 0 : (tooltipBound.height - arrowBound.height) / 2);
// return { left: Math.abs(fixedArrowLeft), top: fixedArrowTop, right: 0 };
}
const tooltipPlacement = computed<string>(() => {
return placementAndAlignment.value.split('-')[0];