惯性垂直拖动滚动
Vertical drag-scrolling with inertia
我通过使用鼠标拖动 up/down 来在我的网页上进行垂直滚动。但是,问题在于它感觉非常突然,因为当您停止拖动时滚动会立即停止。我想增加一些惯性,让它在你停止拖动后继续滚动一点,直到停止。
这实现起来有点复杂,所以我需要一些帮助。这是我所有的当前代码:
let newScrollY = 0
let element = null
const dragScroll = (enabled) => {
element?.removeEventListener("mousedown", element?.mouseDownFunc, false)
window.removeEventListener("mouseup", element?.mouseUpFunc, false)
window.removeEventListener("mousemove", element?.mouseMoveFunc, false)
element = document.querySelector(".drag")
if (!element || !enabled) return
let lastClientY = 0
let mouseDown = false
element.addEventListener("mousedown", element.mouseDownFunc = (event) => {
event.preventDefault()
mouseDown = true
lastClientY = event.clientY
}, false)
window.addEventListener("mouseup", element.mouseUpFunc = (event) => {
mouseDown = false
}, false)
window.addEventListener("mousemove", element.mouseMoveFunc = (event) => {
if (!mouseDown) return
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
newScrollY = event.clientY - lastClientY
lastClientY = event.clientY
scrollElement.scrollTop -= newScrollY
}, false)
}
我想出了解决办法。关键是使用速度的绝对值,并根据速度的符号 add/subtract 到 scrollTop(表示它们是向上滚动还是向下滚动)。
let newScrollY = 0
let lastScrollTop = 0
let element = null as any
let inertia = false
let mouseDown = false
const dragScroll = (enabled) => {
if (inertia || mouseDown) return
element?.removeEventListener("mousedown", element?.mouseDownFunc, false)
window.removeEventListener("mouseup", element?.mouseUpFunc, false)
window.removeEventListener("mousemove", element?.mouseMoveFunc, false)
element = document.querySelector(".drag")
if (!element || !enabled) return
let lastClientY = 0
mouseDown = false
let time = null
let id = 0
element.addEventListener("mousedown", element.mouseDownFunc = (event) => {
event.preventDefault()
mouseDown = true
inertia = false
time = new Date()
lastClientY = event.clientY
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
lastScrollTop = scrollElement.scrollTop
cancelAnimationFrame(id)
}, false)
window.addEventListener("mouseup", element.mouseUpFunc = (event) => {
mouseDown = false
const timeDiff = (new Date() as any - time)
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
let speedY = (scrollElement.scrollTop - lastScrollTop) / timeDiff * 20
let speedYAbsolute = Math.abs(speedY)
const draw = () => {
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
if (speedYAbsolute > 0) {
if (speedY > 0) {
scrollElement.scrollTop += speedYAbsolute--
} else {
scrollElement.scrollTop -= speedYAbsolute--
}
} else {
inertia = false
}
id = requestAnimationFrame(draw)
}
inertia = true
draw()
}, false)
window.addEventListener("mousemove", element.mouseMoveFunc = (event) => {
if (!mouseDown) return
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
newScrollY = event.clientY - lastClientY
lastClientY = event.clientY
scrollElement.scrollTop -= newScrollY
}, false)
}
我通过使用鼠标拖动 up/down 来在我的网页上进行垂直滚动。但是,问题在于它感觉非常突然,因为当您停止拖动时滚动会立即停止。我想增加一些惯性,让它在你停止拖动后继续滚动一点,直到停止。
这实现起来有点复杂,所以我需要一些帮助。这是我所有的当前代码:
let newScrollY = 0
let element = null
const dragScroll = (enabled) => {
element?.removeEventListener("mousedown", element?.mouseDownFunc, false)
window.removeEventListener("mouseup", element?.mouseUpFunc, false)
window.removeEventListener("mousemove", element?.mouseMoveFunc, false)
element = document.querySelector(".drag")
if (!element || !enabled) return
let lastClientY = 0
let mouseDown = false
element.addEventListener("mousedown", element.mouseDownFunc = (event) => {
event.preventDefault()
mouseDown = true
lastClientY = event.clientY
}, false)
window.addEventListener("mouseup", element.mouseUpFunc = (event) => {
mouseDown = false
}, false)
window.addEventListener("mousemove", element.mouseMoveFunc = (event) => {
if (!mouseDown) return
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
newScrollY = event.clientY - lastClientY
lastClientY = event.clientY
scrollElement.scrollTop -= newScrollY
}, false)
}
我想出了解决办法。关键是使用速度的绝对值,并根据速度的符号 add/subtract 到 scrollTop(表示它们是向上滚动还是向下滚动)。
let newScrollY = 0
let lastScrollTop = 0
let element = null as any
let inertia = false
let mouseDown = false
const dragScroll = (enabled) => {
if (inertia || mouseDown) return
element?.removeEventListener("mousedown", element?.mouseDownFunc, false)
window.removeEventListener("mouseup", element?.mouseUpFunc, false)
window.removeEventListener("mousemove", element?.mouseMoveFunc, false)
element = document.querySelector(".drag")
if (!element || !enabled) return
let lastClientY = 0
mouseDown = false
let time = null
let id = 0
element.addEventListener("mousedown", element.mouseDownFunc = (event) => {
event.preventDefault()
mouseDown = true
inertia = false
time = new Date()
lastClientY = event.clientY
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
lastScrollTop = scrollElement.scrollTop
cancelAnimationFrame(id)
}, false)
window.addEventListener("mouseup", element.mouseUpFunc = (event) => {
mouseDown = false
const timeDiff = (new Date() as any - time)
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
let speedY = (scrollElement.scrollTop - lastScrollTop) / timeDiff * 20
let speedYAbsolute = Math.abs(speedY)
const draw = () => {
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
if (speedYAbsolute > 0) {
if (speedY > 0) {
scrollElement.scrollTop += speedYAbsolute--
} else {
scrollElement.scrollTop -= speedYAbsolute--
}
} else {
inertia = false
}
id = requestAnimationFrame(draw)
}
inertia = true
draw()
}, false)
window.addEventListener("mousemove", element.mouseMoveFunc = (event) => {
if (!mouseDown) return
let scrollElement = element
if (element == document.body) scrollElement = document.documentElement
newScrollY = event.clientY - lastClientY
lastClientY = event.clientY
scrollElement.scrollTop -= newScrollY
}, false)
}