uniapp仿抖音评论区popup对话框实现(多端兼容)

一、先看一下弹框实现效果

二、对话框跟随手势下拉实现

从上面的实现效果图中可以发现,弹窗会跟随手势向下移动进行同步移动,想要实现这个功能,需要获取我们的手势向下的移动距离,然后再把这个距离设置给弹窗,作为向下隐藏的距离。

即:弹窗向下移动的距离 = 手势向下移动的距离

1.手势向下移动距离的计算公式

手势向下移动的距离 = 手势当前向下移动到的Y坐标 - 手势开始移动的Y坐标

uniapp中提供了可以兼容多端的监听页面上元素的触摸方法:

1.手指开始触摸元素

element.touchstart:element.touchstart(options: Object): Promise<void>

2.手指触摸元素后移动。

element.touchmove:element.touchmove(options: Object): Promise<void>

3.手指结束触摸元素

element.touchend:element.touchend(options: Object): Promise<void>

options 字段定义如下:

字段 类型 必填 默认值 说明
touches array - 触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouches array - 触摸事件,当前变化的触摸点信息的数组

2.获取手势向下移动的距离

下面将使用选项api 来实现相应功能,目的也是为了同时兼容 vue2vue3版本。

js 复制代码
<template>
<uni-popup ref="popup" type="bottom">
    <view class="content"
        @touchstart="touchstart" 
        @touchmove="touchmove"
    >
      ...
    </view>
</uni-popup>
</template>

<script>
  export default {
    data() {
      return {
        // 手势向下移动距离
        moveDistance: 0
      }
    },
    methods: {
      // 开始触摸元素
      touchstart(e) {
        this.startY = e.changedTouches[0].clientY;
        this.startIme = Date.now()
        this.toumoveTime = Date.now()
      },
      // 触摸元素后移动
      touchmove(e) {
        const clientY = e.changedTouches[0].clientY;
        // 忽略上划
        if (clientY < this.startY) {
          return
        }
        // 下滑,计算手势移动距离
        this.moveDistance = clientY - this.startY
      },
    }
  }
</script>

通过e.changedTouches[0].clientY可获取当前屏幕触摸的Y坐标。

3.弹框向下隐藏同步手指向下触摸移动距离

可以通过css属性transform来设置弹窗向下移动距离,来达到隐藏弹窗的效果。

transform: `translateY(${this.moveDistance}px)`

js 复制代码
<script>
  export default {
    data() {
      return {
        // 手势向下移动距离
        moveDistance: 0
      }
    },
    computed: {
      contentStyle() {
        return {
          transform: `translateY(${this.moveDistance}px)`,
        }
      }
    },
  }
</script>

<template>
<uni-popup ref="popup" type="bottom">
    <view class="content"
        ...
       :style="contentStyle"
    >
      ...
    </view>
</uni-popup>
</template>

三、关闭弹窗时机

上面已经完成了弹窗的随手势进行移动,下面将确定弹窗隐藏的时机,即满足条件调用this.$refs.popup.close()方法关闭弹窗。经过我的一番测试,发现抖音 的评论区弹窗具有两种关闭时机,分别为距离底部一定距离时手指开始、移动、结束触摸元素这三个事件快速完成时都会关闭弹窗。

关闭弹窗我们可以在元素上绑定touchend方法,当触发触摸结束方法时进行相关计算。

1.计算距离底部距离

距离底部距离 = 窗口高度 - 当前手指触摸结束的Y坐标

js 复制代码
touchend(e) {
    // 触摸结束Y坐标
    const clientY = e.changedTouches[0].clientY;
    // 获取窗口高度
    const { windowHeight } = uni.getSystemInfoSync();
    // 距离底部距离
    const distance = windowHeight - clientY
}

2.计算手势完成时间

js 复制代码
touchstart(e) {
    this.startIme = Date.now()
},
touchend(e) {
    // 手势完成时间(毫秒)
    const toumoveTime = Date.now() - this.startIme
},

3.根据计算值,完成弹窗关闭逻辑

js 复制代码
touchend(e) {
    // 触摸结束Y坐标
    const clientY = e.changedTouches[0].clientY;
    // 获取窗口高度
    const { windowHeight } = uni.getSystemInfoSync();
    // 距离底部距离
    const distance = windowHeight - clientY

    // 滑动时间(毫秒),小于某个时间则自动close
    const toumoveTime = Date.now() - this.startIme

    // 必须触发了touchmove方法
    if (this.moveDistance > 0 && (distance < this.bottomCloseValue || toumoveTime < this.moveCloseTime)) {
      this.close();
    } else {
      this.moveDistance = 0;
    }
},

当结束触摸时,如果满足设置的距离设置的触摸完成时间,则关闭弹窗;反之,则复原弹窗。

四、打开全屏

打开全屏主要是计算可用视口高度,并把弹窗内容高度设置为可用视口高度。

js 复制代码
toggleFullScreen() {
    if (this.isFullScrren) {
      // 关闭全屏,高度设为内容高度
      this.height = this.contentHeight
    } else {
    // 开启全屏,设为视口高度
      this.height = this.windowHeight
    }
    this.isFullScrren = !this.isFullScrren
},

同时兼容ios微信小程序和App端顶部和底部安全区域适配

适配iphone手机顶部和底部安全区域

js 复制代码
const {
    safeArea,
    windowHeight,
    screenHeight,
    osName
} = uni.getSystemInfoSync();
// 适配顶部和底部安全区域, safeArea.height安全区域的高度,单位逻辑像素
const safeWindowHeight = windowHeight - (screenHeight - safeArea.bottom)
// 打开全屏的高度
this.windowHeight = safeWindowHeight

适配Android手机app端顶部和底部安全区域

js 复制代码
// #ifdef APP-PLUS
const {
    windowHeight,
    osName
} = uni.getSystemInfoSync();
if (osName === 'ios') {
    // ios没设备
} else {
    // android
    打开全屏的高度
    this.windowHeight = windowHeight
}

五、总结

以上实现主要有三部分内容:

1.弹窗跟随手势向下移动。

2.手势距离底部一定距离或者手势移动足够快关闭弹窗。

3.通过uni.getSystemInfoSync()获取设备信息计算弹窗的全屏高度,兼容不同设备类型。

去体验插件:uniapp插件市场

相关推荐
Hilaku14 小时前
深入URL和URLSearchParams:别再用正则表达式去折磨URL了
前端·javascript·代码规范
pubuzhixing14 小时前
Canvas 的性能卓越,用它解决一个棘手问题
前端
weixin_4569042714 小时前
Vue.jsmain.js/request.js/user.js/store/index.js Vuex状态管理项目核心模块深度解析
前端·javascript·vue.js
伍哥的传说14 小时前
Vue 3.6 Alien Signals:让响应式性能飞跃式提升
前端·javascript·vue.js·vue性能优化·alien-signals·细粒度更新·vue 3.6新特性
永日4567014 小时前
学习日记-HTML-day51-9.9
前端·学习·html
狗头大军之江苏分军15 小时前
iPhone 17 vs iPhone 17 Pro:到底差在哪?买前别被忽悠了
前端
小林coding15 小时前
再也不怕面试了!程序员 AI 面试练习神器终于上线了
前端·后端·面试
文心快码BaiduComate15 小时前
WAVE SUMMIT深度学习开发者大会2025举行 文心大模型X1.1发布
前端·后端·程序员
babytiger15 小时前
python 通过selenium调用chrome浏览器
前端·chrome