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

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

下面是代码node

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)
      }
    })
  }
})
复制代码
相关文章
相关标签/搜索