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 来实现相应功能,目的也是为了同时兼容 vue2和vue3版本。

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

相关推荐
时间的情敌5 小时前
Electron 设置-webkit-app-region: drag;实现拖拽后, 无法响应鼠标划过事件及点击事件的解决方式
前端·vue.js
程序猿阿森5 小时前
深入解析 NLI:RAG 与大模型防幻觉的“最后一道防线”
前端·人工智能·算法
专业程序开发源5 小时前
springboot校企合作双选会一站式预约与面试系统16010-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·面试·php·课程设计
iCxhust6 小时前
模型:500kW飞轮 10kV输电线路 油田抽油机 同时考虑无功补偿 统计:全年节电量 结果56万度电
前端·css·css3·电力·飞轮
志尊宝7 小时前
AI原生前端开发(011):Chrome 148+内置Gemini Nano入门
前端·chrome·ai-native
Liu.7747 小时前
uniapp swiper 常见问题及修复
前端·uni-app
u0111026757 小时前
图片生成任务的日志记录与敏感信息取舍
前端·图像处理·算法·ai作画
Eastmount7 小时前
[论文阅读] (54)NDSS26 JSIMPLIFIER:动静态与LLM如何协同完成JavaScript解混淆?
javascript·论文阅读·恶意代码分析·智能体安全·ndss
凯凯姜7 小时前
Vue 3 深入学习笔记 16:API 请求封装与统一错误处理
vue.js·笔记·学习