- 首先取消了默认的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)
}
})
}
})
复制代码