enhance(client): tweak contextmenu position calculation
This commit is contained in:
parent
3c01c0cbf2
commit
e7a1046b87
3 changed files with 45 additions and 23 deletions
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div ref="el" class="sfhdhdhr">
|
||||
<MkMenu ref="menu" :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/>
|
||||
<div ref="el" :class="$style.root">
|
||||
<MkMenu :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, shallowRef, watch } from 'vue';
|
||||
import { nextTick, onMounted, onUnmounted, shallowRef, watch } from 'vue';
|
||||
import MkMenu from './MkMenu.vue';
|
||||
import { MenuItem } from '@/types/menu';
|
||||
|
||||
|
@ -25,11 +25,21 @@ const emit = defineEmits<{
|
|||
const el = shallowRef<HTMLElement>();
|
||||
const align = 'left';
|
||||
|
||||
const SCROLLBAR_THICKNESS = 16;
|
||||
|
||||
function setPosition() {
|
||||
const rootRect = props.rootElement.getBoundingClientRect();
|
||||
const rect = props.targetElement.getBoundingClientRect();
|
||||
const left = props.targetElement.offsetWidth;
|
||||
const top = (rect.top - rootRect.top) - 8;
|
||||
const parentRect = props.targetElement.getBoundingClientRect();
|
||||
const myRect = el.value.getBoundingClientRect();
|
||||
|
||||
let left = props.targetElement.offsetWidth;
|
||||
let top = (parentRect.top - rootRect.top) - 8;
|
||||
if (rootRect.left + left + myRect.width >= (window.innerWidth - SCROLLBAR_THICKNESS)) {
|
||||
left = -myRect.width;
|
||||
}
|
||||
if (rootRect.top + top + myRect.height >= (window.innerHeight - SCROLLBAR_THICKNESS)) {
|
||||
top = top - ((rootRect.top + top + myRect.height) - (window.innerHeight - SCROLLBAR_THICKNESS));
|
||||
}
|
||||
el.value.style.left = left + 'px';
|
||||
el.value.style.top = top + 'px';
|
||||
}
|
||||
|
@ -46,13 +56,22 @@ watch(() => props.targetElement, () => {
|
|||
setPosition();
|
||||
});
|
||||
|
||||
const ro = new ResizeObserver((entries, observer) => {
|
||||
setPosition();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
ro.observe(el.value);
|
||||
setPosition();
|
||||
nextTick(() => {
|
||||
setPosition();
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
ro.disconnect();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
checkHit: (ev: MouseEvent) => {
|
||||
return (ev.target === el.value || el.value.contains(ev.target));
|
||||
|
@ -60,8 +79,8 @@ defineExpose({
|
|||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sfhdhdhr {
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue