移动端弹出框跟随手指滑动改变高度

移动端touch事件:

常见的触摸事件:

touchstart:(手指触摸屏幕时触发),

touchmove:(手指移动时触发),

touchend:(手指离开屏幕时触发)

跟踪触摸的属性:

touches:表示当前跟踪的触摸操作的touch对象的数组。

targetTouches:特定于事件目标的Touch对象的数组。

(正在触摸当前 DOM 元素上的手指的一个列表。)

changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组。

每个touch对象包含的属性:

Touch.identifier:此 Touch 对象的唯一标识符。 一次触摸动作(我们指的是手指的触摸)在平 面上移动的 整个过程中,该标识符不变。 可以根据它来判断跟踪的是否是同一次触摸过程,此值为只读属性。

Touch.screenX:触点相对于屏幕左边沿的X坐标。只读属性。

Touch.screenY:触点相对于屏幕上边沿的Y坐标。只读属性

Touch.clientX:触点相对于可见视区(visual viewport)左边沿的X坐标。不包括任何滚动偏移。只读属性。

Touch.clientY:触点相对于可见视区(visual viewport)上边沿的Y坐标。不包括任何滚动偏移。只读属性。

Touch.pageX:触点相对于HTML文档左边沿的X坐标。当存在水平滚动的偏移时,这个值包含了水平滚动的偏移。只读属性。

Touch.pageY:触点相对于HTML文档上边沿的Y坐标。当存在水平滚动的偏移时,这个值包含了垂直滚动的偏移。只读属性。

Touch.radiusX:能够包围用户和触摸平面的接触面的最小椭圆的水平轴(X轴)半径。这个值的单位和 screenX 相同。只读属性。

Touch.radiusY:能够包围用户和触摸平面的接触面的最小椭圆的垂直轴(Y轴)半径。这个值的单位和 screenY 相同。只读属性。

Touch.rotationAngle:它是这样一个角度值:由radiusX 和 radiusY描述的正方向的椭圆,需要通过顺时针旋转这个角度值,才能最精确地覆盖住用户和触摸平面的接触面。只读属性。

Touch.force:手指挤压触摸平面的压力大小,从0.0(没有压力)到1.0(最大压力)的浮点数。只读属性。

Touch.target:当这个触点最开始被跟踪时(在 touchstart 事件中),触点位于的HTML元素。

需求:模拟贝壳找房弹出框效果。

  1. 当手指在框内区域按下并移动时,弹出框跟随手指移动距离改变其高度,手指离开时弹到最高点,高度变化过程中,列表元素不发生滚动。
  2. 弹框在最高点时,手指向下滑动时,列表下移,列表到达scrollTop为0时,改变弹框高度。
  3. 手指上移弹到最高点,手指下移弹到最低点
//touch事件无效时加上.native修饰符即可解决
//(该修饰符的作用就是把一个vue组件转化为一个普通的HTML标签)
@touchstart.native="touchstart"
@touchmove.native="touchmove"
@touchend.native="touchend"

动态获取屏幕高度,并将弹出框最高点、最低点、判断点分别设置为屏幕高度的3/4、1/3、2/3

this.bodyHeight = document.documentElement.clientHeight
      this.halfHeight = (this.bodyHeight / 3) * 2
      this.lowHeight = this.bodyHeight / 3
      this.highHeight = (this.bodyHeight / 4) * 3
    handler(ev){
      // console.log('事件名称',ev)
        ev.preventDefault();
    }, 
 //滑动事件start-------------------------------------------------------
     touchstart(event) {
      // 判断是否达到最大高度,若未达到最大高度,添加阻止默认事件,让list不滚动
       if(this.$refs.tabsHeaderRef.$el.style.height!= this.highHeight + 'px'){
//在事件发生期间,调用 preventDefault()事件可以阻止滚动。
            window.addEventListener("touchmove", this.handler, { passive: false });
          }
        var touch = event.touches[0];
        this.startY = touch.pageY;//触发点位置
        this.startX = touch.pageX;
        // 获取手指按下时的元素高度,若为0,则是第一次渲染元素,赋值最低点px
        if(this.startHeight==0){
          this.startHeight = Number(this.lowHeight)
          this.$refs.tabsHeaderRef.$el.style.height=this.lowHeight + 'px'
        }
        else{
          let hh=this.$refs.tabsHeaderRef.$el.style.height
          this.startHeight = Number(hh.substring(0,hh.indexOf('p')));
        }
    },
          
      touchmove(event) {
        // alert(event)
          var touch = event.touches[0];
//当前移动距离
          this.endY = this.startY - touch.pageY;
          this.endX = this.startX - touch.pageX;
          this.touchY = touch.pageY
//判断弹出框是否在最高点
          if(this.$refs.tabsHeaderRef.$el.style.height == this.highHeight + 'px'){
            const body = document.getElementById("positionValue");   // 获取滚动条的dom
            // 获取滚动框距离顶部的距离
            const scrollTop =  body.scrollTop
            // 获取可视区的高度
            const windowHeight = body.clientHeight;
            // 获取滚动条的总高度
            const scrollHeight = body.scrollHeight;
            //当弹出框在最高点、移动距离小于0(手指向下移动)且滚动狂距顶部位置为0(即滚动条滚动到最上方)
            if(this.endY < 0 && scrollTop == 0){
//将弹出框高度设置为手指按下时高度 + 移动距离
              this.$refs.tabsHeaderRef.$el.style.height = (this.startHeight + this.endY)+'px';
              this.$refs.tabsHeaderRef.$el.style.transition = 'all -.29s ease-in-out';
            }
            // 下拉刷新不起作用,此处采用判断当前是否滑动到底部,滑动到底部是触发加载事件,偶尔会有1px之类的误差,所以+100
            // 因为移动事件一直被触发,所以对加载事件做了防抖
            if(scrollTop + windowHeight + 100 >= scrollHeight){
              this.debounce(this.onLoad(), 500)
            }
          }
          if(this.$refs.tabsHeaderRef.$el.style.height != this.highHeight + 'px'){
            // this.listIsShow = true;
            this.$refs.tabsHeaderRef.$el.style.height = (this.startHeight + this.endY)+'px';
            this.$refs.tabsHeaderRef.$el.style.transition = 'all -.29s ease-in-out';
          }
          
      },


      //防抖函数
      debounce(fn, delay) {
        // 定时器
          let timer = null
          // 将debounce处理结果当作函数返回
          return function () {
            // 保留调用时的this上下文
            let context = this
            // 保留调用时传入的参数
            let args = arguments
            // 每次事件被触发时,都去清除之前的旧定时器
            if(timer) {
                clearTimeout(timer)
            }
            // 设立新定时器
            timer = setTimeout(function () {
              fn.apply(context, args)
            }, delay)
          }
        },


      touchend(event) {
//手指离开元素时,清除 preventDefault()事件。
        window.removeEventListener("touchmove", this.handler, { passive: false });
          if (this.endY>0) {
              this.$refs.tabsHeaderRef.$el.style.height = this.highHeight + 'px'
              this.$refs.tabsHeaderRef.$el.style.transition = 'all .2s ease-in-out'
          } else {
                    if(this.$refs.tabsHeaderRef.$el.style.height != this.highHeight + 'px'){
                      if(this.$refs.tabsHeaderRef.$el.style.height < this.lowHeight + 'px'){
                        this.$refs.tabsHeaderRef.$el.style.height = '0px'
                        this.$refs.tabsHeaderRef.$el.style.transition = 'all .2s ease-in-out'
                        this.customerInfo = false
                      }
                      else{
                        this.$refs.tabsHeaderRef.$el.style.height = this.lowHeight + 'px'
                        this.$refs.tabsHeaderRef.$el.style.transition = 'all .2s ease-in-out'
                      }
                    }
                }
          this.endY = 0;
      },
        //滑动事件end----------------------------------------------------------------

参考:(58条消息) 移动端手指滑动,高度跟随手指滑动位置而改变_管理员--0728的博客-CSDN博客

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值