(component): [dropdown]支持 right,left 位置

This commit is contained in:
sight 2022-06-26 22:08:36 +08:00
parent bfde04c2f1
commit 33258dac6c
3 changed files with 139 additions and 24 deletions

View File

@ -149,8 +149,8 @@ const updateContentStyle = () => {
const triggerRect = dropdownRef.value!.getBoundingClientRect(); const triggerRect = dropdownRef.value!.getBoundingClientRect();
const contentRect = contentRef.value!.getBoundingClientRect(); const contentRect = contentRef.value!.getBoundingClientRect();
let { top, left } = style; let { top, left } = style;
top = Number(top.toString().replace("px", "")) top = Number(top.toString().replace("px", ""));
left = Number(left.toString().replace("px", "")) left = Number(left.toString().replace("px", ""));
const { top: fitTop, left: fitLeft } = getFitPlacement( const { top: fitTop, left: fitLeft } = getFitPlacement(
top, top,
left, left,
@ -160,10 +160,10 @@ const updateContentStyle = () => {
); );
style.top = `${fitTop}px`; style.top = `${fitTop}px`;
style.left = `${fitLeft}px`; style.left = `${fitLeft}px`;
contentStyle.value = { contentStyle.value = {
...style ...style,
} };
}) });
} }
}; };
@ -188,6 +188,22 @@ const getContentStyle = (
}; };
}; };
const getPosition = (placement: DropdownPlacement) => {
if (["top", "top-left", "top-right"].includes(placement)) {
return "top";
}
if (["bottom", "bottom-left", "bottom-right"].includes(placement)) {
return "bottom";
}
if (["left", "left-bottom", "left-top"].includes(placement)) {
return "left";
}
if (["right", "right-bottom", "right-top"].includes(placement)) {
return "right";
}
return "bottom";
};
const getFitPlacement = ( const getFitPlacement = (
top: number, top: number,
left: number, left: number,
@ -195,30 +211,50 @@ const getFitPlacement = (
triggerRect: DOMRect, triggerRect: DOMRect,
contentRect: DOMRect contentRect: DOMRect
) => { ) => {
// // FIXME
if (contentRect.bottom > windowHeight.value) { const position = getPosition(placement);
top = -contentRect.height - props.contentOffset; if (["top", "bottom"].includes(position)) {
//
if (contentRect.bottom > windowHeight.value) {
top = -contentRect.height - props.contentOffset;
}
//
if (contentRect.top < 0) {
top = triggerRect.height + props.contentOffset;
}
//
if (contentRect.left < 0) {
left = left + (0 - contentRect.left);
}
//
if (contentRect.right > windowWidth.value) {
left = left - (contentRect.right - windowWidth.value);
}
} }
// if (["left", "right"].includes(position)) {
if (contentRect.top < 0) { //
top = triggerRect.height + props.contentOffset; if (contentRect.bottom > windowHeight.value) {
} top = top - (contentRect.bottom - windowHeight.value);
}
// //
if(contentRect.left < 0){ if (contentRect.top < 0) {
left = left + (0 - contentRect.left) top = top + (0 - contentRect.top);
} }
//
// if (contentRect.left < 0) {
if(contentRect.right > windowWidth.value){ left = triggerRect.width + props.contentOffset;
left = left - (contentRect.right - windowWidth.value) }
//
if (contentRect.right > windowWidth.value) {
left = -(contentRect.width + props.contentOffset);
}
} }
return { return {
top, top,
left, left,
}; };
} };
const getContentOffset = ( const getContentOffset = (
placement: DropdownPlacement, placement: DropdownPlacement,
@ -256,6 +292,36 @@ const getContentOffset = (
top: triggerRect.height + props.contentOffset, top: triggerRect.height + props.contentOffset,
left: -(contentRect.width - triggerRect.width), left: -(contentRect.width - triggerRect.width),
}; };
case "right":
return {
top: -(contentRect.height - triggerRect.height) / 2,
left: triggerRect.width + props.contentOffset,
};
case "right-top":
return {
top: 0,
left: triggerRect.width + props.contentOffset,
};
case "right-bottom":
return {
top: -(contentRect.height - triggerRect.height),
left: triggerRect.width + props.contentOffset,
};
case "left":
return {
top: -(contentRect.height - triggerRect.height) / 2,
left: -(contentRect.width + props.contentOffset),
};
case "left-top":
return {
top: 0,
left: -(contentRect.width + props.contentOffset),
};
case "left-bottom":
return {
top: -(contentRect.height - triggerRect.height),
left: -(contentRect.width + props.contentOffset),
};
default: default:
return { return {
left: 0, left: 0,

View File

@ -5,4 +5,10 @@ export type DropdownPlacement =
| "top-right" | "top-right"
| "bottom" | "bottom"
| "bottom-left" | "bottom-left"
| "bottom-right"; | "bottom-right"
| "right"
| "right-top"
| "right-bottom"
| "left"
| "left-top"
| "left-bottom";

View File

@ -296,6 +296,49 @@ export default {
<div style="width:300px;height:200px;"></div> <div style="width:300px;height:200px;"></div>
</template> </template>
</lay-dropdown> </lay-dropdown>
<br><br>
&nbsp;&nbsp;
<lay-dropdown placement="right-top">
<lay-button type="primary">right-top</lay-button>
<template #content>
<div style="width:300px;height:200px;"></div>
</template>
</lay-dropdown>
&nbsp;&nbsp;
<lay-dropdown placement="right">
<lay-button type="primary">right</lay-button>
<template #content>
<div style="width:300px;height:200px;"></div>
</template>
</lay-dropdown>
&nbsp;&nbsp;
<lay-dropdown placement="right-bottom">
<lay-button type="primary">right-bottom</lay-button>
<template #content>
<div style="width:300px;height:200px;"></div>
</template>
</lay-dropdown>
&nbsp;&nbsp;
<lay-dropdown placement="left-top">
<lay-button type="primary">left-top</lay-button>
<template #content>
<div style="width:300px;height:200px;"></div>
</template>
</lay-dropdown>
&nbsp;&nbsp;
<lay-dropdown placement="left">
<lay-button type="primary">left</lay-button>
<template #content>
<div style="width:300px;height:200px;"></div>
</template>
</lay-dropdown>
&nbsp;&nbsp;
<lay-dropdown placement="left-bottom">
<lay-button type="primary">left-bottom</lay-button>
<template #content>
<div style="width:300px;height:200px;"></div>
</template>
</lay-dropdown>
</template> </template>
<script> <script>