当前位置: 首页 > news >正文

uniapp 实现一个底部悬浮面板

一. 效果

二. 设计目标

  • 地图不被完全遮挡:初始仅露出半屏地图,用户可继续拖动。

  • 内容可滚动:面板内部承载列表、卡片、工具栅格。

  • 交互自然:滚动顺滑、视觉层级清晰。

  • 适配微信小程序:避免使用不兼容语法。

  • 结构清晰、易扩展:后续可嵌入折叠动画、筛选控件等

三. 结构设计思路

层级说明
底层<map> 组件(高德/腾讯地图)
中层搜索栏 + 悬浮按钮(FAB)
顶层可滚动浮层(scroll-view 承载)

浮层的核心是一个 scroll-view 包裹的「透明占位 + 面板」结构:

<scroll-view class="overlay-scroll" :scroll-y="true"><!-- 透明 spacer 决定初始地图可见高度 --><div class="top-spacer" :style="{ height: spacerPx + 'px' }">…</div><!-- 真正的工具面板 --><div class="tool-sheet"><div class="sheet-header"><div class="grabber"></div></div><div class="sheet-body">…</div></div>
</scroll-view>

这里的 top-spacer 负责“撑开”地图初始露出的部分。当用户向上滚动时,它被滚走,tool-sheet 便自然上移覆盖地图。
这种结构无需复杂的 JS 拖拽计算,就能通过 滚动惯性 实现“半屏到全屏”的视觉切换。

四. 交互与布局逻辑

1. scroll-view 占满全屏

.overlay-scroll {
position: absolute;
inset: 0;
z-index: 10;
background: transparent;
}

2.top-spacer 控制地图漏出比例 

const sys = uni.getSystemInfoSync()
const spacerPx = Math.floor(sys.windowHeight * 0.5)

设置屏高50%,即初始漏出地图半屏

3. tool-sheet(面板)

.tool-sheet {
background: #fff;
border-top-left-radius: 24rpx;
border-top-right-radius: 24rpx;
min-height: 70vh;
box-shadow: 0 -8rpx 30rpx rgba(0, 0, 0, 0.12);
display: flex;
flex-direction: column;
overflow: hidden;
}

五. 完整代码

<template><jc-Layout><!-- 地图底层 --><mapclass="map":latitude="center.lat":longitude="center.lng":scale="12":enable-3D="true":enable-overlooking="false":enable-satellite="false":show-location="true":markers="markers"><!-- 顶部搜索栏 --><view class="search-bar"><view class="search-input"><wd-inputv-model="keyword"clearableborder="none"custom-input-class="ipt"no-border><template #prefix><view class="search-icon"><jc-icon size="28rpx" name="sousuo1" /></view></template></wd-input></view><view class="mr-2"><wd-buttontype="info"plain:round="false"size="small"@click="onSearch">搜索</wd-button></view></view></map><!-- 可滚动浮层 --><scroll-viewclass="overlay-scroll":scroll-y="true":enhanced="true":bounces="false":show-scrollbar="false"><!-- Spacer 控制地图露出比例 --><view class="top-spacer" :style="{ height: spacerPx + 'px' }"><jc-fab :absolute="true" icon="fuhao-tuceng" top="600" left="24" /><jc-fab:absolute="true"icon="shuaxin"top="700"left="24"@click="refresh"/><jc-fab :absolute="true" icon="dingwei" top="700" right="24" /></view><!-- 工具面板 --><view class="tool-sheet"><!-- 标题头部 --><view class="sheet-header"><view class="grabber" /><view class="title"><wd-icon name="truck" size="18px" /></view></view><!-- 内容区 --><view class="sheet-body"><view class="tool-grid"><view v-for="n in 15" :key="n" class="tool-item"><view class="icon-wrap"><jc-icon name="left" size="20px" /></view><view class="label">功能{{ n }}</view></view></view><!-- 列表 --><view class="detail-list"><wd-cell-group border><wd-cellv-for="n in 14":key="n"title="占位字段"value="占位值"/></wd-cell-group></view></view></view></scroll-view></jc-Layout>
</template><script setup lang="ts">
definePage({style: {navigationStyle: 'custom',navigationBarTitleText: '车辆工具',},
})const keyword = ref('')
const center = ref({ lat: 23.1291, lng: 113.2644 })
const markers = ref<any[]>([])const sys = uni.getSystemInfoSync()
const spacerPx = Math.floor(sys.windowHeight * 0.5) // 露出地图 50%function onSearch() {console.log('搜索关键词:', keyword.value)
}
function refresh() {console.log('刷新数据')
}
</script><style scoped lang="scss">
/* 搜索栏 */
.search-bar {background: #ffffff;height: 100rpx;width: 100%;position: absolute;top: 0rpx;z-index: 10;display: flex;gap: 12rpx;align-items: center;.search-input {width: 95%;:deep(.ipt) {background: #f7f8fa;padding: 0 50rpx;height: 60rpx !important;}}.search-icon {position: absolute;left: 20rpx;top: 50%;transform: translateY(-50%);}
}/* 地图底层 */
.map {position: relative;inset: 0;width: 100%;height: 100%;z-index: 1;
}/* 滚动浮层 */
.overlay-scroll {position: absolute;inset: 0;z-index: 10;background: transparent;.top-spacer {position: relative;width: 100%;}.tool-sheet {background: #fff;border-top-left-radius: 24rpx;border-top-right-radius: 24rpx;box-shadow: 0 -8rpx 30rpx rgba(0, 0, 0, 0.12);min-height: 70vh;display: flex;flex-direction: column;overflow: hidden;}.sheet-header {padding-top: 16rpx;padding-bottom: 12rpx;.grabber {width: 88rpx;height: 8rpx;border-radius: 8rpx;background: #e5e7eb;margin: 0 auto 14rpx;}.title {display: flex;align-items: center;gap: 12rpx;padding: 0 24rpx;.txt {font-size: 30rpx;font-weight: 600;color: #111;}}}.sheet-body {flex: 1;min-height: 0;padding-bottom: env(safe-area-inset-bottom);}.tool-grid {width: 100%;display: flex;flex-wrap: wrap;justify-content: flex-start;padding: 10rpx;box-sizing: border-box;}.tool-item {width: 20%;display: flex;flex-direction: column;align-items: center;justify-content: center;margin-bottom: 32rpx;.icon-wrap {width: 86rpx;height: 86rpx;border-radius: 50%;background: #e9fbf9;display: flex;align-items: center;justify-content: center;}.label {margin-top: 10rpx;font-size: 24rpx;color: #333;}}.detail-list {padding: 0 16rpx 24rpx;}
}
</style>

http://www.dtcms.com/a/545628.html

相关文章:

  • 中国桥梁空间分布数据
  • MutableStateFlow、StateFlow、LiveData在Compose中的运用
  • 网站建设的总结与评价专业定制网站开发公司
  • 应对AI全球化部署挑战:南凌科技云连接服务实现算法模型全球稳定传输
  • 公司网站建设岗位手机软件定制开发公司
  • 网站推广app软件一级注册工程师
  • LeetCode算法日记 - Day 87: 单词拆分
  • 学术论文写作与发表精讲:融合AI工具的高效方法与实战案例
  • 天津开发网站公司虚拟主机如何建设多个网站
  • 跟公司产品做网站制作app软件工具免费
  • 133-Spring AI Alibaba Vector Redis 功能完整案例
  • 线段树详解
  • AI 大模型应用中的图像,视频,音频的处理
  • 2025年大专建筑工程技术专业前景!
  • @1Panel 全面指南:从部署到高阶使用
  • SAP MM 采购申请转采购订单功能分享
  • FPGA设计中的“幽灵信号:一条走线,两种命运——浅析路径延迟导致的逻辑错误
  • 网站建设将新建用户授权为管理员免费搭建手机网站源码
  • 北京企业网站建设费用新闻最新消息
  • 算法工具箱之二分查找
  • undefined reference to `cJSON_AddStringToObject‘
  • 仓颉语言中TreeMap红黑树结构的实现与优化
  • Rust 的构建系统和包管理器
  • AI驱动嵌入式软件全链路变革:从芯片到系统的深度智能重构
  • 怎么修改网站域名推广网站排行榜
  • 靠谱的电磁阀维护保养
  • 【自动化测试函数 (下)】Web自动化攻坚:应对加载等待、浏览器导航与无头模式的自动化脚本艺术
  • 正向代理工具
  • 攀枝花建设工程有限责任公司网站中国兰州网
  • Kubernetes 部署