This commit is contained in:
Leo Vasanko 2025-08-25 17:34:58 -06:00
parent e0f0da1c8c
commit c3ba8e1b0c

View File

@ -70,6 +70,9 @@ function createMomentumDrag({
momentumFrame = requestAnimationFrame(step) momentumFrame = requestAnimationFrame(step)
} }
function applyDragByDelta(deltaY, reason) { function applyDragByDelta(deltaY, reason) {
const now = performance.now()
while (samples[0]?.timestamp < now - VELOCITY_MS) samples.shift()
samples.push({ timestamp: now, position: deltaY })
const newScrollTop = startScroll - deltaY * speed const newScrollTop = startScroll - deltaY * speed
const maxScroll = Math.max(0, contentHeight.value - viewportHeight.value) const maxScroll = Math.max(0, contentHeight.value - viewportHeight.value)
const clamped = Math.max(0, Math.min(newScrollTop, maxScroll)) const clamped = Math.max(0, Math.min(newScrollTop, maxScroll))
@ -80,14 +83,15 @@ function createMomentumDrag({
applyDragByDelta(deltaY, reason) applyDragByDelta(deltaY, reason)
} }
function endDrag() { function endDrag() {
if (!dragging) return
dragging = false dragging = false
window.removeEventListener('pointermove', onPointerMove, true) window.removeEventListener('pointermove', onPointerMove, true)
window.removeEventListener('pointerup', onPointerUp, true) window.removeEventListener('pointerup', endDrag, true)
window.removeEventListener('pointercancel', onPointerUp, true) window.removeEventListener('pointercancel', endDrag, true)
if (allowTouch) { if (allowTouch) {
window.removeEventListener('touchmove', onTouchMove) window.removeEventListener('touchmove', onTouchMove)
window.removeEventListener('touchend', onTouchEnd) window.removeEventListener('touchend', endDrag)
window.removeEventListener('touchcancel', onTouchEnd) window.removeEventListener('touchcancel', endDrag)
} }
document.removeEventListener('pointerlockchange', onPointerLockChange, true) document.removeEventListener('pointerlockchange', onPointerLockChange, true)
if (usingPointerLock && document.pointerLockElement === viewport.value) { if (usingPointerLock && document.pointerLockElement === viewport.value) {
@ -108,31 +112,19 @@ function createMomentumDrag({
startMomentum() startMomentum()
} }
function onPointerMove(e) { function onPointerMove(e) {
if (!dragging) return if (!dragging || document.pointerLockElement !== viewport.value) return
if (document.pointerLockElement === viewport.value) {
// Use movementY deltas under pointer lock
const now = performance.now()
dragAccumY += e.movementY dragAccumY += e.movementY
while (samples[0]?.timestamp < now - VELOCITY_MS) samples.shift()
samples.push({ timestamp: now, position: dragAccumY })
applyDragByDelta(dragAccumY, reasonDragPointer) applyDragByDelta(dragAccumY, reasonDragPointer)
}
e.preventDefault() e.preventDefault()
} }
function onPointerUp() {
if (dragging) endDrag()
}
function onTouchMove(e) { function onTouchMove(e) {
if (!dragging) return if (!dragging) return
const t = e.touches[0] if (e.touches.length !== 1) {
const now = performance.now() endDrag()
while (samples[0]?.timestamp < now - VELOCITY_MS) samples.shift() return
samples.push({ timestamp: now, position: t.clientY })
applyDragPosition(t.clientY, reasonDragTouch)
e.preventDefault()
} }
function onTouchEnd() { applyDragPosition(e.touches[0].clientY, reasonDragTouch)
if (dragging) endDrag() e.preventDefault()
} }
function handlePointerDown(e) { function handlePointerDown(e) {
if (e.button !== undefined && e.button !== 0) return if (e.button !== undefined && e.button !== 0) return
@ -146,10 +138,10 @@ function createMomentumDrag({
dragAccumY = 0 dragAccumY = 0
samples = [{ timestamp: performance.now(), position: e.clientY }] samples = [{ timestamp: performance.now(), position: e.clientY }]
window.addEventListener('pointermove', onPointerMove, true) window.addEventListener('pointermove', onPointerMove, true)
window.addEventListener('pointerup', onPointerUp, true) window.addEventListener('pointerup', endDrag, true)
window.addEventListener('pointercancel', onPointerUp, true) window.addEventListener('pointercancel', endDrag, true)
document.addEventListener('pointerlockchange', onPointerLockChange, true) document.addEventListener('pointerlockchange', onPointerLockChange, true)
viewport.value.requestPointerLock() viewport.value.requestPointerLock({ unadjustedMovement: true })
} }
function handleTouchStart(e) { function handleTouchStart(e) {
if (!allowTouch) return if (!allowTouch) return
@ -164,8 +156,8 @@ function createMomentumDrag({
dragAccumY = 0 dragAccumY = 0
samples = [{ timestamp: performance.now(), position: t.clientY }] samples = [{ timestamp: performance.now(), position: t.clientY }]
window.addEventListener('touchmove', onTouchMove, { passive: false }) window.addEventListener('touchmove', onTouchMove, { passive: false })
window.addEventListener('touchend', onTouchEnd, { passive: false }) window.addEventListener('touchend', endDrag, { passive: false })
window.addEventListener('touchcancel', onTouchEnd, { passive: false }) window.addEventListener('touchcancel', endDrag, { passive: false })
e.preventDefault() e.preventDefault()
} }
function onPointerLockChange() { function onPointerLockChange() {