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插件市场

相关推荐
Benzenene!1 分钟前
让Chrome信任自签名证书
前端·chrome
yangholmes88881 分钟前
如何在 web 应用中使用 GDAL (二)
前端·webassembly
jacy3 分钟前
图片大图预览就该这样做
前端
林太白5 分钟前
Nuxt3 功能篇
前端·javascript·后端
YuJie7 分钟前
webSocket Manager
前端·javascript
Mapmost22 分钟前
Mapmost SDK for UE5 内核升级,三维场景渲染效果飙升!
前端
Mapmost25 分钟前
重磅升级丨Mapmost全面兼容3DTiles 1.1,3DGS量测精度跃升至亚米级!
前端·vue.js·three.js
wycode31 分钟前
Promise(一)极简版demo
前端·javascript
浮幻云月32 分钟前
一个自开自用的Ai提效VsCode插件
前端·javascript