📱 优化仪表盘健康卡与趋势图触控
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<div class="relative overflow-visible rounded-[30px] border" :class="panelClass">
|
||||
<canvas
|
||||
ref="canvasRef"
|
||||
class="block h-80 min-h-80 w-full touch-none select-none md:h-72 md:min-h-72"
|
||||
class="block h-72 min-h-72 w-full touch-pan-y select-none sm:h-80 sm:min-h-80 md:h-72 md:min-h-72"
|
||||
@wheel.prevent="handleWheel"
|
||||
@pointerdown="handlePointerDown"
|
||||
@pointermove="handlePointerMove"
|
||||
@@ -44,8 +44,11 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
type DragState = {
|
||||
startX: number
|
||||
lastX: number
|
||||
time: number
|
||||
pointerType: string
|
||||
moved: boolean
|
||||
}
|
||||
|
||||
type TooltipState = {
|
||||
@@ -381,36 +384,67 @@ const handleWheel = (event: WheelEvent) => {
|
||||
zoom(event.deltaY > 0 ? 1.16 : 0.86, rect ? (event.clientX - rect.left) / rect.width : 0.5)
|
||||
}
|
||||
|
||||
const setHoverFromClientX = (clientX: number) => {
|
||||
const rect = canvasRef.value?.getBoundingClientRect()
|
||||
if (!rect) return
|
||||
hoverX.value = clamp(clientX - rect.left, 0, rect.width)
|
||||
scheduleDraw()
|
||||
}
|
||||
|
||||
const handlePointerDown = (event: PointerEvent) => {
|
||||
canvasRef.value?.setPointerCapture(event.pointerId)
|
||||
cancelInertia()
|
||||
velocity.value = 0
|
||||
drag.value = { lastX: event.clientX, time: event.timeStamp || performance.now() }
|
||||
setHoverFromClientX(event.clientX)
|
||||
drag.value = {
|
||||
startX: event.clientX,
|
||||
lastX: event.clientX,
|
||||
time: event.timeStamp || performance.now(),
|
||||
pointerType: event.pointerType,
|
||||
moved: false
|
||||
}
|
||||
}
|
||||
|
||||
const handlePointerMove = (event: PointerEvent) => {
|
||||
const rect = canvasRef.value?.getBoundingClientRect()
|
||||
const pointerEvents = event.getCoalescedEvents?.() || [event]
|
||||
const coalescedEvents = event.getCoalescedEvents?.() || []
|
||||
const pointerEvents = coalescedEvents.length ? coalescedEvents : [event]
|
||||
const latestEvent = pointerEvents[pointerEvents.length - 1] || event
|
||||
if (rect) hoverX.value = latestEvent.clientX - rect.left
|
||||
if (!drag.value) {
|
||||
scheduleDraw()
|
||||
return
|
||||
}
|
||||
|
||||
if (drag.value.pointerType === 'touch') {
|
||||
scheduleDraw()
|
||||
return
|
||||
}
|
||||
|
||||
const totalDistance = Math.abs(latestEvent.clientX - drag.value.startX)
|
||||
const threshold = 3
|
||||
if (!drag.value.moved && totalDistance < threshold) {
|
||||
scheduleDraw()
|
||||
return
|
||||
}
|
||||
drag.value.moved = true
|
||||
|
||||
pointerEvents.forEach((pointerEvent) => {
|
||||
const now = pointerEvent.timeStamp || performance.now()
|
||||
const deltaX = pointerEvent.clientX - drag.value!.lastX
|
||||
const deltaTime = Math.max(1, now - drag.value!.time)
|
||||
velocity.value = deltaX / deltaTime
|
||||
pan(deltaX)
|
||||
drag.value = { lastX: pointerEvent.clientX, time: now }
|
||||
drag.value = { ...drag.value!, lastX: pointerEvent.clientX, time: now, moved: true }
|
||||
})
|
||||
}
|
||||
|
||||
const handlePointerUp = () => {
|
||||
const shouldInertia = Boolean(drag.value?.moved)
|
||||
drag.value = null
|
||||
cancelInertia()
|
||||
inertiaRafId.value = window.requestAnimationFrame(applyInertia)
|
||||
if (shouldInertia) inertiaRafId.value = window.requestAnimationFrame(applyInertia)
|
||||
else scheduleDraw()
|
||||
}
|
||||
|
||||
const handlePointerCancel = () => {
|
||||
|
||||
Reference in New Issue
Block a user