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 动画

精确控制滑动边界

做好性能优化

相关推荐
2305_797882092 分钟前
AI识图小程序的功能框架设计
人工智能·微信小程序·小程序
6武736 分钟前
Vue 数据传递流程图指南
前端·javascript·vue.js
goto_w40 分钟前
uniapp上使用webview与浏览器交互,支持三端(android、iOS、harmonyos next)
android·vue.js·ios·uni-app·harmonyos
小宝小白1 小时前
【vue3】黑马小兔鲜儿项目uniapp navigationStyle
uni-app
暮雨哀尘1 小时前
微信小程序开发:开发实践
开发语言·算法·微信小程序·小程序·notepad++·性能·技术选型
samuel9181 小时前
axios取消重复请求
前端·javascript·vue.js
苹果酱05671 小时前
Golang标准库——runtime
java·vue.js·spring boot·mysql·课程设计
滿2 小时前
Vue 3 中按照某个字段将数组分成多个数组
前端·javascript·vue.js
幽络源小助理3 小时前
微信小程序实验室管理SSM系统设计与实现
微信小程序·小程序
....4924 小时前
Vue3 + Element Plus + AntV X6 实现拖拽树组件
javascript·vue.js·elementui·antvx6