vue2.0自定义指令,用touch事件替换scroll事件

  • 首先取消了默认的scroll事件,然后根据滑动的距离计算scrollTop的大小,对于滑动速度过快的,使用定时器制作了一个减速运动,模拟手指离开屏幕时页面继续滑动的情况。
  • 使用这个指令要求绑定元素必须有高度

下面是代码

Vue.directive('touchMove', {
  inserted (el, binding, vnode) {
    if (el.style.height === 'auto') return // 当绑定元素height为auto时,直接返回
    let start, date, dateStart
    let scrollPrevious = 0 // 保存滚动条上次所在位置
    let moveSave = []
    let dateSave = []
    let timmer = null
    let scrollNow = 0 // 滚动当前所在位置
    
    el.addEventListener('touchstart', function (e) {
      clearInterval(timmer)
      moveSave = []
      dateSave = []
      scrollPrevious = el.scrollTop
      start = e.targetTouches[0].clientY // 手指开始接触屏幕时所在屏幕Y轴位置
      dateStart = new Date()
    })

    el.addEventListener('touchmove', function (e) {
      e.preventDefault()
      let move = e.targetTouches[0].clientY // 手指滑动时所在屏幕Y轴位置
      let distance = move - start // 每次滑动的距离
      let date = new Date()
      if (moveSave.length < 2) { 
        moveSave.push(move) // 保存最近两次滑动所在的位置跟时间
        dateSave.push(date)
      } else {
        moveSave.shift()
        moveSave.push(move)
        dateSave.shift()
        dateSave.push(date)
      }
      el.scrollTop = -distance + scrollPrevious
      if (moveSave[1] < moveSave[0]) {
        if (binding.value && binding.value.upScroll) {
          binding.value.upScroll(el, vnode) // 向上滑动时运行的函数
        }
      } else {
        if (binding.value && binding.value.downScroll) {
          binding.value.downScroll(el, vnode) // 向下滑动时运行的函数
        }
      }
    })

    el.addEventListener('touchend', function (e) {
      let speed = 0 // 滑动速度(单位px/ms)
      let elementHeight = el.scrollHeight - el.clientHeight // 滚动条最大值
      let reduction = 0.01 // 加速度
      if (moveSave.length < 2) {
        speed = (moveSave[0] - start) / (dateSave[0] - dateStart)
      } else {
        speed = (moveSave[1] - moveSave[0]) / (dateSave[1] - dateSave[0])
      }
      if (speed > 5) { // 限制speed的最大值跟最小值
        speed = 5
      }
      if (speed < -5) {
        speed = -5
      }
      if (Math.abs(speed) > .5) { // speed超过某一直后就会持续移动
        timmer = setInterval(function() {
          if (speed < 0) {
            speed = speed + reduction
            if (binding.value && binding.value.upScroll) {
              binding.value.upScroll(el) // 向上滑动时运行的函数
            }
            if (speed > 0) {
              speed = 0
            }
            scrollNow += -speed * 16
          } else if (speed > 0) {
            speed = speed - reduction
            if (binding.value && binding.value.downScroll) {
              binding.value.downScroll(el) // 向下滑动时运行的函数
            }
            if (speed < 0) {
              speed = 0
            }
            scrollNow -= speed * 16 
          }
          el.scrollTop = scrollNow
          if (speed === 0 || el.scrollTop === 0 || el.scrollTop === elementHeight) {
            clearInterval(timmer)
          }
        }, 16)
      }
    })
  }
})
复制代码

转载于:https://juejin.im/post/5a51b2235188257322588654

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值