vue 手写 移动端 左右滑动 防止上下滑动冲突 超过宽度一半切换

原理是通过touchstart touchmove touchend三个事件配合transform属性实现

<div ref="mattersContent" @touchstart='touchStart' @touchmove='touchMove' @touchend='touchEnd' :style="{transform: 'translateX('+translateX+'px)',transition: transition+'s',white-space: 'nowrap'}">
   <div :style="{width:'100%',height:'200px'}">1111</div>
   <div :style="{width:'100%',height:'200px'}">2222</div>
</div>

touchstart事件中需要特别注意的是需要保存当前触发时的transform的值特别是translateX的值,因为不是每次触发按下事件都是没有进行滑动过的,只要进行了过滑动计算距离就不能单单是clientX距离页面的绝对距离了 需要配合上上一次的transform才能实现正常的滑动

  data() {
    return {
      isFirst:false,
      x: 0,
      y: 0,
      _x: 0,
      _y: 0,
      translateX: 0,
      startTranslate:0,
      transition:0,
      },
    }
    methods: {
        touchStart(e) {
	      // this.x  this.y 按下时 触点位置
	      // transition每次点击时 清除过渡时间
	      // this.startTranslate是当前按下时的translateX的值 需要这个变量的原因是可能当前位置是有过translate移动的 如果不加上相当于每次都是translateX(0)
	      this.transition = 0
	      this.x = e.touches[0].clientX;
	      this.y = e.touches[0].clientY;
	      console.log('touchStart',this.x,this.y)
	      this.startTranslate = this.translateX
	    },
	    touchMove(e) {
	      // this._x this._y 移动时 触点位置
	      this._x = e.touches[0].clientX
	      this._y = e.touches[0].clientY
	      // console.log('touchMove',this._x,this._x)
	      // disY disX计算是不是左右滑动 
	      let disY = Math.abs(this._y - this.y)
	      let disX = Math.abs(this._x - this.x)
	      if (this.isFirst) {
	        this.isFirst = false;
	        //判断方向
	        if (disY > disX) {
	          this.isHori = false;
	        }
	
	        if (disY < disX) {
	          this.isHori = true;
	        }
	      }
	      //判断方向 决定是否阻止默认行为
	      if (this.isHori) {
	        e.preventDefault();
	        e.stopPropagation()
	      } else {
	        return;
	      }
	      // 每一次触发都要移动时间 就改变一次translate  
	      this.translateX = this._x - this.x + this.startTranslate;
	      // console.log('this.translateX = this._x - this.x + this.translateX;', this._x , this.x ,this.translateX,this._x - this.x + this.translateX)
	      
	    },
	    touchEnd(e) {
	      this.isFirst = true
	      if (!this.isHori) return;
	      let mattersContentWidth = this.$refs.mattersContent.offsetWidth;
	      if (e.changedTouches.length == 1) {
	        this._x = e.changedTouches[0].clientX;
	        // 移动时的x 减去 初始位置的x 就是移动的距离 负为左滑 正为右滑
	        this.disX = this._x - this.x;
	        console.log(this.disX, 'this.disX')
	        // console.log((mattersContentWidth / 2), 'mattersContentWidth/2');
	        // 只有滑动距离大于整个宽的一半距离才进行切换
	        if (Math.abs(this.disX) > (mattersContentWidth / 2)) {
	          if (this.disX < 0) {
	            console.log('左滑',mattersContentWidth);
	            // transform直接累加一个宽 这里需要注意根据自己能滑动的次数判断 如果多的话用累加 += 要设上边界值
	            this.translateX = - mattersContentWidth
	            this.transition = 0.2
	          } 
	          else {
	            console.log('右滑',this.startTranslate, mattersContentWidth,this.startTranslate + mattersContentWidth,this.startTranslate >= mattersContentWidth ? this.startTranslate - mattersContentWidth : 0);
	            this.transition = 0.2
	            // 右滑时 如果当前点下时保存的startTranslate大于宽说明可以右滑 否者说明已经是最边上了 直接为0
	            this.translateX = Math.abs(this.startTranslate) >= mattersContentWidth ? this.startTranslate + mattersContentWidth : 0
	          }
	        } else{
	        	// 没有大于整个宽的一半 恢复按下时初始位置的startTranslate
	        	console.log('没有超过临结值 不变',this.startTranslate);
	          	this.transition = 0.2
	          	this.translateX = this.startTranslate
	        }
	      }
	    }
    }
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值