- 首先取消了預設的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)
}
})
}
})
複製程式碼