Uniapp 实现微信小程序滑动面板功能详解

文章目录


前言

Uniapp 实现微信小程序滑动面板功能详解


一、功能概述

滑动面板是移动端常见的交互组件,通常用于在页面底部展开内容面板。本文将介绍如何使用 Uniapp 开发一个支持手势滑动的底部面板组件,实现以下核心功能:

触摸滑动调整面板高度

边界限制

与地图组件的层级适配

二、实现思路

使用 Uniapp 框架实现跨平台兼容

通过 CSS transform 实现动画效果

基于微信小程序触摸事件体系

结合选择器 API 获取元素尺寸

触摸事件监听:捕获 touchstart/touchmove/touchend 事件

滑动距离计算:通过 clientY 坐标差值计算滑动距离

边界限制:确保面板在允许的高度范围内滑动

弹性动画:使用 CSS transition 实现平滑过渡

层级管理:通过 z-index 控制与其他组件的层级关系

三、代码实现

javascript 复制代码
<template>
  <view
    class="slider-panel"
    @touchstart="handleTouchStart"
    @touchmove.stop.prevent="handleTouchMove"
    @touchend="handleTouchEnd"
    :style="{
      'min-height': `${initialPosition}px`,
      transform: `translateY(${translateY}px)`
    }"
  >
    <view class="slider-panel-handle"></view>
    <view class="slider-panel-content">
      <slot></slot>
    </view>
  </view>
</template>
<script>
export default {
  name: 'SliderPanel',
  props: {
    initialPosition: {
      type: Number,
      default: 100
    },
    deltaYThreshold: {
      type: Number,
      default: 100
    }
  },
  data() {
    return {
      isDragging: false,
      startY: 0,
      translateY: 0,
      panelHeight: 0,
      panelInitialShowHeight: 0
    }
  },
  async mounted() {
    const { height } = await this.getSelectorRect('.slider-panel-content')
    this.panelHeight = height
    if (this.initialPosition > this.panelHeight) {
      this.panelInitialShowHeight = this.panelHeight
    } else {
      this.panelInitialShowHeight = height - this.initialPosition
      this.translateY = this.panelInitialShowHeight
    }
  },
  methods: {
    getSelectorRect(selector) {
      const query = wx.createSelectorQuery().in(this)
      return new Promise((resolve) => {
        query
          .select(selector)
          .boundingClientRect((rect) => {
            resolve(rect)
          })
          .exec()
      })
    },
    handleTouchStart(event) {
      const { clientY } = event.touches[0]
      this.isDragging = true
      this.startY = clientY
    },
    handleTouchMove(event) {
      if (this.isDragging) {
        const { clientY } = event.touches[0]
        const deltaY = clientY - this.startY
        this.startY = clientY
        this.translateY += deltaY
        if (this.translateY < 0) {
          this.translateY = 0
        }
        if (this.translateY > this.panelInitialShowHeight) {
          this.translateY = this.panelInitialShowHeight
        }
      }
    },
    handleTouchEnd() {
      this.isDragging = false
    }
  }
}
</script>

<style scoped lang="scss">
.slider-panel {
  position: fixed;
  width: 100%;
  box-sizing: border-box;
  left: 0;
  bottom: 0;
  background: #fff;
  padding: 20rpx;
  border-radius: 24px 24px 0 0;
  box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.1);
  z-index: 30;
  will-change: transform;
  .slider-panel-handle {
    width: 60rpx;
    height: 6rpx;
    border-radius: 3rpx;
    background: #f0f0f0;
    margin: 16rpx auto 24rpx;
  }
}
</style>
javascript 复制代码
<template>
  <view class="container">
    <map style="width: 100%; height: 100%" :enable-scroll="false"></map>
    <slider-panel>
      <view v-for="item in 20" :key="item">
        <view class="item">
          {{ item }}
        </view>
      </view>
    </slider-panel>
  </view>
</template>
<script>
import SliderPanel from '@/components/sliderPanel'
export default {
  components: {
    SliderPanel
  },
  data() {
    return {}
  },
  methods: {}
}
</script>

<style lang="scss">
page {
  height: 100%;
  width: 100%;
}
</style>

<style scoped lang="scss">
.container {
  position: relative;
  height: 100%;
  width: 100%;
  overflow: hidden;
  .item {
    display: flex;
    align-items: center;
    justify-content: center;
    border-bottom: 1px solid #ccc;
    height: 80rpx;
  }
}
</style>

总结

通过 Uniapp 开发滑动面板组件,可以有效实现跨平台兼容。核心在于:

正确处理触摸事件流

合理使用 CSS 动画

精确控制滑动边界

做好性能优化

相关推荐
CSharp精选营3 小时前
记一次家庭物品管理的折腾:从“收纳”到“可检索”
微信小程序·aicoding·屋册有序·物品收纳管理·家庭收纳管理工具
软件技术NINI7 小时前
基于SpringBoot和Vue的新能源汽车销售推荐系统
java·vue.js·spring boot·后端·汽车·毕业设计·毕设
招风的黑耳9 小时前
SpringBoot+Vue+MySQL 民宿在线预定平台 完整可运行版(源码+文档)
vue.js·spring boot·mysql
dreams_dream1 天前
微信小程序:页面事件-上拉触底
微信小程序·小程序
10share1 天前
基于大模型的 i18n 方案:把中文原文当 Key,轻松搞定多语言维护
前端·vue.js
鹏多多1 天前
AI 到底能不能独立做个产品?我拿一个小程序验证了
前端·微信小程序·ai编程
啾咪orJIUMI1 天前
Vue 3 + 高德地图封装实战:点位、区域、Loca 流光与 Vue 信息窗体
前端·vue.js
FRing031 天前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
无懈可击1 天前
Vue 可视化AI表单设计器 FcDesigner v3.6 版本发布,支持导出 SQL功能!
vue.js·开源·ai编程
徐小夕1 天前
JitArchives,一款基于JitWord协同AI文档打造的企业级电子档案系统
前端·vue.js·github