From fbaeb43a8aa572ff3ccc26090e36bb0fb9cbe5ba Mon Sep 17 00:00:00 2001 From: Sagi Date: Sat, 15 Oct 2022 16:28:06 +0800 Subject: [PATCH] refactor(tooltip): refactor tooltip add useCalculatePosition and useAdjust-position --- .../tooltip/src/composition/types.ts | 16 ++- .../src/composition/use-adjust-position.ts | 13 ++ .../src/composition/use-calculate-position.ts | 93 ++++++++++++ .../src/composition/use-tooltip-position.ts | 134 ------------------ 4 files changed, 121 insertions(+), 135 deletions(-) create mode 100644 packages/ui-vue/components/tooltip/src/composition/use-adjust-position.ts create mode 100644 packages/ui-vue/components/tooltip/src/composition/use-calculate-position.ts diff --git a/packages/ui-vue/components/tooltip/src/composition/types.ts b/packages/ui-vue/components/tooltip/src/composition/types.ts index f848d81..d900343 100644 --- a/packages/ui-vue/components/tooltip/src/composition/types.ts +++ b/packages/ui-vue/components/tooltip/src/composition/types.ts @@ -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; arrowPosition: ComputedRef; } + +export interface UseCalculatePosition { + calculate: ( + placementAndAlignment: TooltipPlacement, + hostBound: DOMRect, + tooltipBound: DOMRect, + tooltipContentBound: DOMRect, + arrowBound: DOMRect + ) => TooltipPosition; +} diff --git a/packages/ui-vue/components/tooltip/src/composition/use-adjust-position.ts b/packages/ui-vue/components/tooltip/src/composition/use-adjust-position.ts new file mode 100644 index 0000000..b81678f --- /dev/null +++ b/packages/ui-vue/components/tooltip/src/composition/use-adjust-position.ts @@ -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) { + + +} diff --git a/packages/ui-vue/components/tooltip/src/composition/use-calculate-position.ts b/packages/ui-vue/components/tooltip/src/composition/use-calculate-position.ts new file mode 100644 index 0000000..6bc0f9a --- /dev/null +++ b/packages/ui-vue/components/tooltip/src/composition/use-calculate-position.ts @@ -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 }; +} diff --git a/packages/ui-vue/components/tooltip/src/composition/use-tooltip-position.ts b/packages/ui-vue/components/tooltip/src/composition/use-tooltip-position.ts index d5b5068..9df4233 100644 --- a/packages/ui-vue/components/tooltip/src/composition/use-tooltip-position.ts +++ b/packages/ui-vue/components/tooltip/src/composition/use-tooltip-position.ts @@ -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(() => { return placementAndAlignment.value.split('-')[0];