refactor(tooltip): refactor tooltip types

This commit is contained in:
Sagi 2022-10-13 11:59:36 +08:00
parent 4367870061
commit 7a107b1f06
4 changed files with 37 additions and 136 deletions

View File

@ -0,0 +1,16 @@
import { ComputedRef } from "vue";
import { TooltipPlacement } from "../tooltip.props";
export type RectDirection = 'top' | 'bottom' | 'right' | 'left';
export type RectSizeProperty = 'height' | 'width';
export interface RectPosition {
top: number;
left: number;
right: number;
}
export interface UseTooltipPosition {
tooltipPlacement: ComputedRef<TooltipPlacement>;
tooltipPosition: ComputedRef<RectPosition>;
arrowPosition: ComputedRef<RectPosition>;
}

View File

@ -1,13 +1,6 @@
import { computed, ref, SetupContext } from "vue";
import { TooltipPlacement, TooltipProps } from "../tooltip.props";
type RectDirection = 'top' | 'bottom' | 'right' | 'left';
type RectSizeProperty = 'height' | 'width';
interface RectPosition {
top: number;
left: number;
right: number;
}
import { RectDirection, RectPosition, RectSizeProperty } from "./types";
export function useTooltipPosition(
props: TooltipProps,
@ -30,14 +23,10 @@ export function useTooltipPosition(
const placement = ref(props.placement);
const tooltipPlacement = computed(() => {
return props.placement;
});
function revertPlacement(placement: string, direction: RectDirection) {
function revertPlacement(placement: string, direction: RectDirection): TooltipPlacement {
const revertDirection: RectDirection = revertDirectionMap.get(direction) || direction;
const revertedPlacement = placement.replace(direction, revertDirection);
return revertDirection;
const revertedPlacement = placement.replace(direction, revertDirection) as TooltipPlacement;
return revertedPlacement;
}
function autoRectifyDirection(
@ -165,8 +154,8 @@ export function useTooltipPosition(
function calculateArrowPosition(
placement: TooltipPlacement,
hostBound: DOMRect,
fixedTooltipBound: DOMRect,
arrowBound: DOMRect): DOMRect {
tooltipPositoin: RectPosition,
arrowBound: DOMRect): RectPosition {
const leftAlignment = placement.indexOf('-left') > 0;
const rightAlignment = placement.indexOf('-right') > 0;
const topAlignment = placement.indexOf('-top') > 0;
@ -174,12 +163,17 @@ export function useTooltipPosition(
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 = fixedTooltipBound.left - hostBound.left - hostBound.width * 0.5 + arrowBound.width * 0.5 + offsetX;
const fixedArrowTop = fixedTooltipBound.top - hostBound.top - hostBound.height * 0.5 + arrowBound.height * 0.5 + offsetY;
const fixedArrowLeft = tooltipPositoin.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;
return Object.assign({}, arrowBound, { left: Math.abs(fixedArrowLeft), top: Math.abs(fixedArrowTop) });
return { left: Math.abs(fixedArrowLeft), top: Math.abs(fixedArrowTop), right: 0 };
}
const tooltipPlacement = computed<TooltipPlacement>(() => {
const rectifyPlacement = autoRectifyDirection(placement.value, hostBound, hostBound, tooltipBound, arrowBound);
return rectifyPlacement;
});
const tooltipPosition = computed<RectPosition>(() => {
const originalTop = calculateTooltipTopPositoin(placement.value, hostBound, tooltipBound, arrowBound);
const originalLeft = calculateTooltipLeftPosition(placement.value, hostBound, tooltipBound, arrowBound);
@ -194,119 +188,10 @@ export function useTooltipPosition(
return { top, left, right };
});
/* 计算tooltip最新位置 */
function calculatePosition(hostBound: DOMRect, tooltipBound: DOMRect, arrowBound: DOMRect) {
let top = 0;
let left = 0;
let right = 0;
const arrowPosition = computed<RectPosition>(() => {
const { top, left, right } = calculateArrowPosition(placement.value, hostBound, tooltipPosition.value, arrowBound);
return { top, left, right };
});
switch (this.rectifyPlacement) {
case 'top':
top = hostPosition.top - tooltipSize.height - 2;
left = hostPosition.left + (hostPosition.width - tooltipSize.width) / 2;
right = left + tooltipSize.width;
break;
case 'left':
top = hostPosition.top + (hostPosition.height - tooltipSize.height) / 2;
left = hostPosition.left - tooltipSize.width - 2;
break;
case 'right':
top = hostPosition.top + (hostPosition.height - tooltipSize.height) / 2;
left = hostPosition.right + 2;
break;
case 'bottom':
top = hostPosition.bottom + arrowSize.height + 2;
left = hostPosition.left + (hostPosition.width - tooltipSize.width) / 2;
right = left + tooltipSize.width;
break;
case 'top-left':
top = hostPosition.top - tooltipSize.height - 2;
left = hostPosition.left;
right = left + tooltipSize.width;
break;
case 'top-right':
top = hostPosition.top - tooltipSize.height - 2;
left = hostPosition.right - tooltipSize.width;
right = hostPosition.right;
break;
case 'right-top':
top = hostPosition.top;
left = hostPosition.right + 2;
this.arrowNode.nativeElement.style.top = '10%';
break;
case 'right-bottom':
top = hostPosition.bottom - tooltipSize.height;
left = hostPosition.right + 2;
this.arrowNode.nativeElement.style.bottom = '10%';
break;
case 'bottom-left':
top = hostPosition.bottom + arrowSize.height + 2;
left = hostPosition.left;
right = left + tooltipSize.width;
break;
case 'bottom-right':
top = hostPosition.bottom + arrowSize.height + 2;
left = hostPosition.right - tooltipSize.width;
right = hostPosition.right;
break;
case 'left-top':
top = hostPosition.top;
left = hostPosition.left - tooltipSize.width - 2;
this.arrowNode.nativeElement.style.top = '10%';
break;
case 'left-bottom':
top = hostPosition.bottom - tooltipSize.height;
left = hostPosition.left - tooltipSize.width - 2;
this.arrowNode.nativeElement.style.bottom = '10%';
}
let overResult;
let arrowLeft = 0;
let arrowTop = 0
switch (this.rectifyPlacement) {
case 'top':
case 'top-left':
case 'top-right':
case 'bottom':
case 'bottom-left':
case 'bottom-right':
overResult = this.isOverBounding('left', left);
if (overResult.isOver) {
left = overResult.newValue;
} else {
overResult = this.isOverBounding('right', right);
if (overResult.isOver) {
left = overResult.newValue - tooltipSize.width;
}
}
arrowLeft = left - hostPosition.left - hostPosition.width * 0.5 + arrowSize.width * 0.5;
if (this.rectifyPlacement.indexOf('-left') > 0) {
arrowLeft += hostPosition.width * 0.4;
} else if (this.rectifyPlacement.indexOf('-right') > 0) {
arrowLeft -= hostPosition.width * 0.4;
}
this.arrowNode.nativeElement.style.left = Math.abs(arrowLeft) + 'px';
break;
default:
overResult = this.isOverBounding('top', top);
if (overResult.isOver) {
top = overResult.newValue;
} else {
overResult = this.isOverBounding('bottom', bottom);
if (overResult.isOver) {
top = overResult.newValue - tooltipSize.height;
}
}
arrowTop = top - hostPosition.top - hostPosition.height * 0.5 + arrowSize.height * 0.5;;
if (this.rectifyPlacement.indexOf('-top') > 0) {
arrowTop += hostPosition.height * 0.4;
} else if (this.rectifyPlacement.indexOf('-bottom') > 0) {
arrowTop -= hostPosition.height * 0.4;
}
this.arrowNode.nativeElement.style.top = Math.abs(arrowTop) + 'px';
}
this.tooltipNode.nativeElement.style.top = top + 'px';
this.tooltipNode.nativeElement.style.left = left + 'px';
}
return { arrowPosition, tooltipPlacement, tooltipPosition };
}

View File

@ -15,7 +15,7 @@ export default defineComponent({
tooltip: true,
show: true
} as any;
const tooltipClassName = `bs-tooltip-${props.position}`;
const tooltipClassName = `bs-tooltip-${props.placement}`;
classObject[tooltipClassName] = true;
return classObject;
});

View File

@ -32,7 +32,7 @@ const tooltipDirective = {
content: 'This is a tooltip',
width: 100,
customClass: '',
position: 'top',
placement: 'top',
referenceBoundingRect: element.getBoundingClientRect()
});
});