更新记录

1.0.0(2025-10-19) 下载此版本

v1.0.0 (2024-10-19)


平台兼容性

uni-app(4.81)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× - - - - - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - -

可拖拽浮动面板组件 (DraggablePanel)

项目简介

一个基于 uni-app + Vue3 开发的高性能可拖拽浮动面板组件,支持触摸拖拽、自动吸附、内容滚动等丰富功能。该组件特别适用于移动端应用中需要展示详情信息的场景,如地图应用的位置详情、电商应用的商品详情、美食应用的店铺信息等。

技术栈

  • 框架: uni-app 3.0
  • 语言: Vue 3 + JavaScript
  • 样式: SCSS
  • 构建工具: Vite 5.2.8
  • 支持平台: H5、微信小程序、支付宝小程序、百度小程序等全平台

核心特性

🎯 主要功能

  1. 触摸拖拽交互

    • 流畅的原生触摸事件处理
    • 支持上拉展开、下拉收起
    • 实时位置跟随,无延迟感
  2. 自动吸附

    • 智能边界吸附
    • 可配置吸附阈值
    • 平滑动画过渡
  3. 内容滚动

    • 内部内容可独立滚动
    • 支持 uni-app 增强滚动
    • 滚动条显示控制
  4. 动态高度

    • 自动计算容器高度
    • 适配不同屏幕尺寸
    • 支持导航栏高度兼容
  5. 编程式控制

    • 提供展开/收起/切换方法
    • 支持设置具体位置
    • 丰富的事件回调

🎨 视觉特性

  • Material Design 风格阴影效果
  • 可自定义圆角和背景色
  • 优雅的拖拽指示器
  • 平滑的动画过渡效果

项目结构

my-FloatingPanel/
├── src/
│   ├── pages/
│   │   └── index/
│   │       ├── index.vue                 # 示例页面(美食详情)
│   │       ├── index2.vue                # 备用页面
│   │       └── DraggablePanel/
│   │           └── index.vue             # 可拖拽面板组件
│   ├── App.vue                          # 应用入口
│   ├── main.js                          # 主入口文件
│   ├── manifest.json                    # 应用配置
│   └── pages.json                       # 页面配置
├── package.json                         # 项目依赖
└── vite.config.js                      # Vite配置

组件使用

基础用法

<template>
  <DraggablePanel
    ref="draggablePanel"
    :initialTop="'500rpx'"
    :minTranslateY="-500"
    :maxTranslateY="0"
    :showHandle="true"
    :scrollable="true"
    @change="onPanelChange"
    @expand="onPanelExpand"
    @collapse="onPanelCollapse"
  >
    <!-- 你的内容 -->
    <view class="content">
      <!-- 内容区域 -->
    </view>
  </DraggablePanel>
</template>

<script setup>
import DraggablePanel from './DraggablePanel/index.vue'
import { ref } from 'vue'

const draggablePanel = ref(null)

// 面板位置变化
const onPanelChange = (data) => {
  console.log('位置变化', data.translateY, '进度', data.progress)
}

// 面板展开
const onPanelExpand = () => {
  console.log('面板已展开')
}

// 面板收起
const onPanelCollapse = () => {
  console.log('面板已收起')
}
</script>

编程式控制

// 展开面板
draggablePanel.value?.expand()

// 收起面板
draggablePanel.value?.collapse()

// 切换状态
draggablePanel.value?.toggle()

// 设置具体位置
draggablePanel.value?.setTranslateY(-250)

// 获取当前状态
const isExpanded = draggablePanel.value?.isExpanded
const currentPosition = draggablePanel.value?.translateY

API 文档

Props 属性

属性 说明 类型 默认值
位置控制
initialTranslateY 初始Y轴偏移量 Number 0
minTranslateY 最小偏移量(最大上拉距离) Number -500
maxTranslateY 最大偏移量(最大下拉距离) Number 0
initialTop 初始顶部位置 String '500rpx'
手柄配置
showHandle 是否显示拖拽手柄 Boolean true
handleColor 拖拽手柄颜色 String '#d9d9d9'
滚动配置
scrollable 是否启用内容滚动 Boolean true
enhanced 是否启用增强滚动 Boolean true
showScrollbar 是否显示滚动条 Boolean false
吸附动画
autoSnap 是否启用自动吸附 Boolean true
snapThreshold 自动吸附阈值(0-1) Number 0.5
animationDuration 动画持续时间(ms) Number 300
外观配置
borderRadius 面板圆角设置 String '20rpx 20rpx 0rpx 0rpx'
backgroundColor 面板背景颜色 String '#ffffff'
enableShadow 是否启用阴影效果 Boolean true
高度配置
dynamicHeight 是否启用动态高度 Boolean true

Events 事件

事件名 说明 回调参数
change 面板位置变化时触发 { translateY, progress }
dragstart 开始拖拽时触发 { translateY, pageY }
dragend 结束拖拽时触发 { translateY, oldTranslateY, isExpanded }
expand 面板展开时触发 -
collapse 面板收起时触发 -
scroll 内容滚动时触发 { type, scrollTop, deltaX, deltaY }

Methods 方法

方法名 说明 参数
expand() 展开面板 -
collapse() 收起面板 -
toggle() 切换面板状态 -
setTranslateY(value) 设置面板位置 value: Number

Expose 暴露属性

属性名 说明 类型
translateY 当前Y轴偏移量 Ref
isExpanded 是否已展开 ComputedRef

使用场景示例

1. 美食详情页(当前示例)

项目中的 index.vue 展示了一个美食详情页的实现:

  • 顶部区域: 美食主图展示
  • 浮动面板: 包含美食名称、标签、评分、描述和相关餐厅列表
  • 交互特性: 上拉查看更多内容,下拉回到概览状态

2. 地图位置详情

<DraggablePanel
  :initialTop="'600rpx'"
  :minTranslateY="-400"
  :maxTranslateY="0"
>
  <view class="location-info">
    <view class="location-name">{{ location.name }}</view>
    <view class="location-address">{{ location.address }}</view>
    <view class="location-actions">
      <button>导航</button>
      <button>分享</button>
    </view>
  </view>
</DraggablePanel>

3. 商品快速预览

<DraggablePanel
  :initialTop="'400rpx'"
  :minTranslateY="-600"
  :snapThreshold="0.3"
>
  <view class="product-preview">
    <image :src="product.image" />
    <view class="product-info">
      <text class="price">¥{{ product.price }}</text>
      <button @click="addToCart">加入购物车</button>
    </view>
  </view>
</DraggablePanel>

性能优化

已实现的优化

  1. 使用 transform 而非 top/bottom

    • 利用 GPU 加速,避免重排重绘
    • 确保 60fps 的流畅动画
  2. 拖拽时禁用过渡动画

    • 消除拖拽延迟感
    • 提高响应速度
  3. 事件防抖与节流

    • 优化滚动事件处理
    • 减少不必要的计算
  4. 动态高度计算缓存

    • 使用 computed 缓存计算结果
    • 避免重复计算

建议的最佳实践

  1. 合理设置初始位置

    • 根据内容重要性设置 initialTop
    • 避免初始位置过高或过低
  2. 适当的吸附阈值

    • 一般设置为 0.3-0.7
    • 根据用户习惯调整
  3. 内容懒加载

    • 展开时再加载详细内容
    • 减少初始渲染压力

开发指南

环境准备

# 安装依赖
npm install

# 运行到 H5
npm run dev:h5

# 运行到微信小程序
npm run dev:mp-weixin

# 运行到支付宝小程序  
npm run dev:mp-alipay

代码规范

  1. 组件命名: 使用 PascalCase,如 DraggablePanel
  2. 事件命名: 使用 kebab-case,如 @drag-start
  3. 属性命名: 使用 camelCase,如 minTranslateY
  4. 样式命名: 使用 kebab-case + BEM,如 .drag-handle__bar

调试技巧

  1. 查看高度计算日志

    // 组件内已包含调试日志
    console.log('高度计算:', {
     screenHeight,
     availableHeight,
     finalHeight,
     translateY
    })
  2. 监听所有事件

    <DraggablePanel
     @change="log('change', $event)"
     @dragstart="log('dragstart', $event)"
     @dragend="log('dragend', $event)"
     @expand="log('expand')"
     @collapse="log('collapse')"
     @scroll="log('scroll', $event)"
    />

兼容性

平台 支持版本 测试状态
H5 ✅ 全版本 已测试
微信小程序 ✅ 基础库 2.0+ 已测试
支付宝小程序 ✅ 全版本 待测试
百度小程序 ✅ 全版本 待测试
QQ小程序 ✅ 全版本 待测试
字节小程序 ✅ 全版本 待测试
快应用 ✅ 全版本 待测试
App ✅ 全版本 待测试

常见问题

Q: 面板拖拽不流畅怎么办?

A: 检查以下几点:

  1. 确保没有在 touchmove 事件中进行复杂计算
  2. 检查是否正确设置了 is-dragging
  3. 避免在拖拽时触发其他动画

Q: 内容滚动与拖拽冲突怎么处理?

A: 组件已内置处理逻辑:

  • 内容滚动到顶部时才能下拉
  • 通过 isScrollAtTop 状态控制

Q: 如何自定义过渡动画?

A: 修改组件样式中的 transition 属性:

.draggable-panel {
  transition: transform 0.5s ease-in-out; // 自定义时长和缓动
}

Q: 支持横向拖拽吗?

A: 当前版本仅支持纵向拖拽。如需横向拖拽,可修改:

  • handleTouchMove 中的 deltaX 计算
  • transform 使用 translateX

更新日志

v1.0.0 (2024-10-19)

  • 🎉 初始版本发布
  • ✨ 实现基础拖拽功能
  • ✨ 添加自动吸附特性
  • ✨ 支持内容滚动
  • ✨ 提供编程式控制接口
  • 📝 完善组件文档

贡献指南

欢迎提交 Issue 和 Pull Request!

提交 Issue

  • 使用清晰的标题描述问题
  • 提供复现步骤和环境信息
  • 附上相关代码和截图

提交 PR

  • Fork 项目并创建特性分支
  • 编写清晰的提交信息
  • 确保代码符合项目规范
  • 添加必要的注释和文档

许可证

MIT License

联系方式

  • 作者邮箱: [***@qq.com]

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。