mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 07:24:13 +00:00 
			
		
		
		
	enhance(client): improve tooltip position calclation
This commit is contained in:
		
							parent
							
								
									e5d6d1dcf0
								
							
						
					
					
						commit
						5792eea1b1
					
				
					 2 changed files with 130 additions and 21 deletions
				
			
		| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<MkTooltip ref="tooltip" :showing="showing" :x="x" :y="y" :max-width="340" @closed="emit('closed')">
 | 
					<MkTooltip ref="tooltip" :showing="showing" :x="x" :y="y" :max-width="340" :direction="'left'" :inner-margin="16" @closed="emit('closed')">
 | 
				
			||||||
	<div v-if="title" class="qpcyisrl">
 | 
						<div v-if="title" class="qpcyisrl">
 | 
				
			||||||
		<div class="title">{{ title }}</div>
 | 
							<div class="title">{{ title }}</div>
 | 
				
			||||||
		<div v-for="x in series" class="series">
 | 
							<div v-for="x in series" class="series">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,8 +17,12 @@ const props = withDefaults(defineProps<{
 | 
				
			||||||
	y?: number;
 | 
						y?: number;
 | 
				
			||||||
	text?: string;
 | 
						text?: string;
 | 
				
			||||||
	maxWidth?: number;
 | 
						maxWidth?: number;
 | 
				
			||||||
 | 
						direction?: 'top' | 'bottom' | 'right' | 'left';
 | 
				
			||||||
 | 
						innerMargin?: number;
 | 
				
			||||||
}>(), {
 | 
					}>(), {
 | 
				
			||||||
	maxWidth: 250,
 | 
						maxWidth: 250,
 | 
				
			||||||
 | 
						direction: 'top',
 | 
				
			||||||
 | 
						innerMargin: 0,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const emit = defineEmits<{
 | 
					const emit = defineEmits<{
 | 
				
			||||||
| 
						 | 
					@ -34,21 +38,22 @@ const setPosition = () => {
 | 
				
			||||||
	const contentWidth = el.value.offsetWidth;
 | 
						const contentWidth = el.value.offsetWidth;
 | 
				
			||||||
	const contentHeight = el.value.offsetHeight;
 | 
						const contentHeight = el.value.offsetHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let left: number;
 | 
					 | 
				
			||||||
	let top: number;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let rect: DOMRect;
 | 
						let rect: DOMRect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (props.targetElement) {
 | 
						if (props.targetElement) {
 | 
				
			||||||
		rect = props.targetElement.getBoundingClientRect();
 | 
							rect = props.targetElement.getBoundingClientRect();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const calcPosWhenTop = () => {
 | 
				
			||||||
 | 
							let left: number;
 | 
				
			||||||
 | 
							let top: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (props.targetElement) {
 | 
				
			||||||
			left = rect.left + window.pageXOffset + (props.targetElement.offsetWidth / 2);
 | 
								left = rect.left + window.pageXOffset + (props.targetElement.offsetWidth / 2);
 | 
				
			||||||
		top = rect.top + window.pageYOffset - contentHeight;
 | 
								top = (rect.top + window.pageYOffset - contentHeight) - props.innerMargin;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		el.value.style.transformOrigin = 'center bottom';
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			left = props.x;
 | 
								left = props.x;
 | 
				
			||||||
		top = props.y - contentHeight;
 | 
								top = (props.y - contentHeight) - props.innerMargin;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		left -= (el.value.offsetWidth / 2);
 | 
							left -= (el.value.offsetWidth / 2);
 | 
				
			||||||
| 
						 | 
					@ -57,16 +62,120 @@ const setPosition = () => {
 | 
				
			||||||
			left = window.innerWidth - contentWidth + window.pageXOffset - 1;
 | 
								left = window.innerWidth - contentWidth + window.pageXOffset - 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [left, top];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const calcPosWhenBottom = () => {
 | 
				
			||||||
 | 
							let left: number;
 | 
				
			||||||
 | 
							let top: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (props.targetElement) {
 | 
				
			||||||
 | 
								left = rect.left + window.pageXOffset + (props.targetElement.offsetWidth / 2);
 | 
				
			||||||
 | 
								top = (rect.top + window.pageYOffset + props.targetElement.offsetHeight) + props.innerMargin;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								left = props.x;
 | 
				
			||||||
 | 
								top = (props.y) + props.innerMargin;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							left -= (el.value.offsetWidth / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (left + contentWidth - window.pageXOffset > window.innerWidth) {
 | 
				
			||||||
 | 
								left = window.innerWidth - contentWidth + window.pageXOffset - 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [left, top];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const calcPosWhenLeft = () => {
 | 
				
			||||||
 | 
							let left: number;
 | 
				
			||||||
 | 
							let top: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (props.targetElement) {
 | 
				
			||||||
 | 
								left = (rect.left + window.pageXOffset - contentWidth) - props.innerMargin;
 | 
				
			||||||
 | 
								top = rect.top + window.pageYOffset + (props.targetElement.offsetHeight / 2);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								left = (props.x - contentWidth) - props.innerMargin;
 | 
				
			||||||
 | 
								top = props.y;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							top -= (el.value.offsetHeight / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (top + contentHeight - window.pageYOffset > window.innerHeight) {
 | 
				
			||||||
 | 
								top = window.innerHeight - contentHeight + window.pageYOffset - 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [left, top];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const calcPosWhenRight = () => {
 | 
				
			||||||
 | 
							let left: number;
 | 
				
			||||||
 | 
							let top: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (props.targetElement) {
 | 
				
			||||||
 | 
								left = (rect.left + window.pageXOffset) + props.innerMargin;
 | 
				
			||||||
 | 
								top = rect.top + window.pageYOffset + (props.targetElement.offsetHeight / 2);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								left = props.x + props.innerMargin;
 | 
				
			||||||
 | 
								top = props.y;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							top -= (el.value.offsetHeight / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (top + contentHeight - window.pageYOffset > window.innerHeight) {
 | 
				
			||||||
 | 
								top = window.innerHeight - contentHeight + window.pageYOffset - 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [left, top];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const calc = (): {
 | 
				
			||||||
 | 
							left: number;
 | 
				
			||||||
 | 
							top: number;
 | 
				
			||||||
 | 
							transformOrigin: string;
 | 
				
			||||||
 | 
						} => {
 | 
				
			||||||
 | 
							switch (props.direction) {
 | 
				
			||||||
 | 
								case 'top': {
 | 
				
			||||||
 | 
									const [left, top] = calcPosWhenTop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// ツールチップを上に向かって表示するスペースがなければ下に向かって出す
 | 
									// ツールチップを上に向かって表示するスペースがなければ下に向かって出す
 | 
				
			||||||
				if (top - window.pageYOffset < 0) {
 | 
									if (top - window.pageYOffset < 0) {
 | 
				
			||||||
		if (props.targetElement) {
 | 
										const [left, top] = calcPosWhenBottom();
 | 
				
			||||||
			top = rect.top + window.pageYOffset + props.targetElement.offsetHeight;
 | 
										return { left, top, transformOrigin: 'center top' };
 | 
				
			||||||
			el.value.style.transformOrigin = 'center top';
 | 
									}
 | 
				
			||||||
		} else {
 | 
					
 | 
				
			||||||
			top = props.y;
 | 
									return { left, top, transformOrigin: 'center bottom' };
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case 'bottom': {
 | 
				
			||||||
 | 
									const [left, top] = calcPosWhenBottom();
 | 
				
			||||||
 | 
									// TODO: ツールチップを下に向かって表示するスペースがなければ上に向かって出す
 | 
				
			||||||
 | 
									return { left, top, transformOrigin: 'center top' };
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case 'left': {
 | 
				
			||||||
 | 
									const [left, top] = calcPosWhenLeft();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// ツールチップを左に向かって表示するスペースがなければ右に向かって出す
 | 
				
			||||||
 | 
									if (left - window.pageXOffset < 0) {
 | 
				
			||||||
 | 
										const [left, top] = calcPosWhenRight();
 | 
				
			||||||
 | 
										return { left, top, transformOrigin: 'left center' };
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return { left, top, transformOrigin: 'right center' };
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case 'right': {
 | 
				
			||||||
 | 
									const [left, top] = calcPosWhenRight();
 | 
				
			||||||
 | 
									// TODO: ツールチップを右に向かって表示するスペースがなければ左に向かって出す
 | 
				
			||||||
 | 
									return { left, top, transformOrigin: 'left center' };
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return null as never;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const { left, top, transformOrigin } = calc();
 | 
				
			||||||
 | 
						el.value.style.transformOrigin = transformOrigin;
 | 
				
			||||||
	el.value.style.left = left + 'px';
 | 
						el.value.style.left = left + 'px';
 | 
				
			||||||
	el.value.style.top = top + 'px';
 | 
						el.value.style.top = top + 'px';
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue