Floating UI是什么?
Floating UI( floating-ui.com )是Popper.js的升级版,把官网的介绍翻译过来就是:
一个 JavaScript 库,用于定位浮动元素并为其创建交互。 "Smart Anchor Positioning"(智能锚定定位)是该库提供的一个功能,它可以将浮动元素相对于另一个元素进行定位,并确保它保持在可视区域内,避免与其他元素发生碰撞。这使得你可以优化地定位工具提示(tooltips)、弹出框(popovers)或下拉菜单(dropdowns)等浮动元素。
简而言之,该库可以帮助你轻松地将浮动元素放置在其他元素旁边,并自动调整其位置,以避免与其他元素重叠或超出可视区域。这提供了更好的用户体验,并确保了浮动元素的可见性和可用性。
安装模块
npm install @floating-ui/vue
Vue3代码
html
<template>
<div
style="
display: flex;
justify-content: center;
align-items: center;
margin: auto;
height: 100%;
"
>
<div style="height: 100%; width: 100%; text-align: center">
<div style="height: 1000px"></div>
<span ref="reference">
<el-button @click="isShow = !isShow">trigger</el-button>
</span>
<div
v-if="isShow"
ref="floating"
:style="{ left: floatingStyles.left, top: floatingStyles.top }"
style="background: pink; width: 50px; height: 150px; position: absolute"
>
Floating
</div>
<div style="height: 1000px"></div>
</div>
</div>
</template>
js
<script setup lang="ts">
import {
arrow,
useFloating,
computePosition,
shift,
flip,
offset,
} from "@floating-ui/vue";
import { watch } from "vue";
import { ref, onMounted, nextTick, watchEffect } from "vue";
let isShow = ref(false);
const reference = ref<HTMLElement | null>(null);
let floating = ref<HTMLElement | null>(null);
// 初始化,中间件middleware还可以设置箭头之类的,这里我没有配置
const { floatingStyles, middlewareData } = useFloating(reference, floating, {
middleware: [],
});
console.log(
"初始化",
floatingStyles.value,
floatingStyles.value.left,
floatingStyles.value.top
);
const middleware = [shift(), flip(), offset(10)];
// 核心代码,调用FloatingUI的computePosition函数,自动调整floating元素的位置
const updatePosition = () => {
computePosition(
reference.value as HTMLElement,
floating.value as HTMLElement,
{
middleware, // 按需引用的中间件
placement: "bottom", // 指定初始化浮动位置
}
).then(({ x, y }) => {
// computePosition根据传入参数计算目标元素和浮动元素位置,
// 异步返回浮动元素坐标后可手动设置浮层位置
Object.assign(floating.value.style, {
left: `${x}px`,
top: `${y}px`,
});
console.log(
"调整位置",
floatingStyles.value,
floatingStyles.value.left,
floatingStyles.value.top
);
});
};
// 浮动元素显示时,启动resize和scroll的监听,否则清除监听
watch(
() => isShow.value,
() => {
if (isShow.value) {
nextTick(() => {
updatePosition();
// 这里注意应该还要做一下debounce的处理
window.onresize = function () {
updatePosition();
};
window.onscroll = function () {
updatePosition();
};
});
} else {
window.onresize = null;
window.onscroll = null;
}
}
);
</script>
scss
<style lang="scss">
#app {
height: 100%;
}
</style>