n-float-panel 浮动面板
平台兼容性
| App-Android | App-iOS | App-Harmony | Web | 微信小程序 |
|---|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ | ✓ |
使用说明
常驻底部的可拖拽浮动面板(bottom-sheet):拖动头部或内容区在锚点档位间切换可见高度,松手吸附最近锚点;支持多锚点、遮罩、底部安全区与内容滚动,常用于筛选面板、详情面板与快捷操作面板。
html
<template>
<n-float-panel :anchors="[200, 600]">
<scroll-view direction="vertical" style="flex: 1">
<view v-for="i in 20" :key="i" class="list-item">
<text class="list-text">列表项 {{ i }}</text>
</view>
</scroll-view>
</n-float-panel>
</template>
锚点用面板的可见高度(px)描述:anchors="[200, 600]" 表示面板初始露出 200px、向上拖动展开到 600px。面板本体始终以 height(默认 600)布局内容,收展通过整体下移完成,内容不会被压扁或重排。锚点为 0 时面板完全收起(触摸不可达),再次展开用实例方法 toAnchor。
内容滚动:内容区放 scroll-view(direction="vertical" + flex: 1)即可滚动浏览;此时面板拖动走头部把手,两者互不干扰。若内容不需要滚动(如固定操作区),传 :scrollable="false" 让拖内容也能拖面板。
跳转锚点:
html
<script setup lang="uts">
import { ref } from "vue";
const panel = ref<NFloatPanelComponentPublicInstance | null>(null);
function expand(): void {
panel.value?.toAnchor(1);
}
</script>
遮罩:overlay 显示遮罩层(层级在面板之下),close-on-click-overlay 点击遮罩收回面板到最小锚点。
实现说明(机制对照)
| 机制 | 参考做法 | 本库做法 | 分歧理由 |
|---|---|---|---|
| 收展实现 | 参考以面板高度动画驱动 | 面板本体高度固定 = height,translateY 下移收起 |
内容按完整高度布局不被压扁,展开收起过程内容零重排(bottom-sheet 标准做法) |
| 锚点类型 | 文档称锚点支持像素或百分比 | 只收 px(number[]) | 百分比的类型形态无法核实(参考源加密),px 语义明确,百分比由使用者换算 |
| 内容滚动与拖动竞争 | 两开关(contentDraggable/scrollable)叠加时的手势竞争语义无法核实(源码加密) | scrollable 为 true 时内容区手势交还滚动容器(拖面板走头部);false 且 contentDraggable 开启时拖内容即拖面板 |
手势竞争必须有确定语义;该模型与参考官方示例行为一致(scroll-view 列表滚动正常、「仅头部拖拽」示例成立) |
| 点击遮罩的「关闭」 | 文档描述点击遮罩关闭面板,未定义关闭后的状态(无 visible/收起 API) | 收回面板到最小锚点并发 change | 面板无常驻显隐 API,收回最小锚点是唯一自洽落地;无法核实项如实标注 |
| change 参数 | 文档未给出参数形态 | { index, height }(落定锚点下标与可见高度) |
从使用者视角补全;参考源加密无法核对 |
| 底色 | 默认硬编码白色 | bgColor 空值走主题背景色(深浅自动),显式传值覆盖 |
库内主题一致性 |
| 自由悬浮容器(参考一) | 任意方向拖拽 + 边缘吸附的悬浮球形态 | 不收录 | 悬浮球场景由悬浮按钮组件的 free 拖拽模式承担,面板形态不适用吸边/尺寸语义 |
| 网格排序拖拽(参考三) | 九宫格长按排序 + 删除菜单 | 不收录 | 排序功能由拖拽排序组件承担,与本组件(浮动面板)形态不同 |
API
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| height | number | 600 | 面板本体最大高度(px);锚点值不得超过该值(超出按该值处理) |
| anchors | number[] | [] | 锚点可见高度数组(px,升序),如 [200, 600];空数组时按 [height] 单锚点处理 |
| default-anchor | number | 0 | 初始锚点下标,越界时钳制到有效范围 |
| duration | number | 300 | 锚点切换过渡时长(ms);0 为无过渡直接跳转 |
| z-index | number | 1000 | 面板层级;遮罩层级为该值减 10 |
| bg-color | string | "" | 面板底色;空值使用主题背景色(深浅模式自动切换),显式传入时覆盖 |
| safe-area-inset-bottom | boolean | true | 是否在面板内底部垫底部安全区高度(小白条 / 手势条机型) |
| content-draggable | boolean | true | 内容区触摸是否可拖动面板;内容为滚动列表时保持 scrollable 开启(内容滚动优先,拖面板走头部) |
| scrollable | boolean | true | 内容是否可滚动:true 时内容区手势交还滚动容器;false 且 content-draggable 开启时拖内容即拖面板 |
| overlay | boolean | false | 是否显示遮罩层 |
| overlay-opacity | number | 0.35 | 遮罩透明度(0~1) |
| overlay-fade | boolean | true | 遮罩显隐是否启用淡入淡出过渡 |
| close-on-click-overlay | boolean | false | 点击遮罩是否收回面板到最小锚点 |
| custom-class | string | "" | 组件根节点类名 |
| custom-style | string | "" | 组件根节点行内样式 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
| change | (detail: { index: number, height: number }) | 面板落定锚点变化时触发(拖动落锚、toAnchor、遮罩收回),index 为锚点下标、height 为可见高度 |
| move | (detail: { height: number }) | 面板拖动中实时触发,height 为当前可见高度 |
方法
| 方法 | 签名 | 说明 |
|---|---|---|
| toAnchor | (index: number) => void | 跳转到指定锚点(下标越界时钳制),带过渡并发 change 事件 |
插槽
| 名称 | 参数 | 说明 |
|---|---|---|
| handle | — | 头部拖拽区内容,覆盖默认拖拽指示条;触摸绑定由组件承载 |
| default | — | 面板主体内容;滚动内容放 scroll-view(direction="vertical" + flex: 1) |