📈 修复趋势坐标轴与移动日期选择

This commit is contained in:
2026-07-10 11:40:11 +08:00
parent 398aad011f
commit dad3b97dfc
3 changed files with 54 additions and 15 deletions
@@ -212,6 +212,32 @@ const updatePart = (part: DatePart, value: string) => {
pointer-events: none;
}
@media (max-width: 639px) {
.native-date-strip {
min-height: 2.35rem;
padding-inline: 0.35ch;
}
.native-date-part {
height: 2.25rem;
font-size: 0.82rem;
}
.native-date-year {
width: 3.7ch;
}
.native-date-month,
.native-date-day {
width: 1.8ch;
}
.native-date-separator {
margin-inline: 0.15ch;
font-size: 0.82rem;
}
}
.dark .native-date-strip {
background: rgba(38, 57, 65, 0.62);
color: #d8e3e5;
+24 -9
View File
@@ -44,10 +44,11 @@ const emit = defineEmits<{
}>()
type DragState = {
startX: number
startOffset: number
lastX: number
time: number
pointerType: string
isTimeline: boolean
moved: boolean
}
@@ -162,10 +163,11 @@ const draw = (timestamp = performance.now()) => {
const padBottom = mobile ? 42 : 36
const width = Math.max(1, rect.width - padLeft - padRight)
const height = Math.max(1, rect.height - padTop - padBottom)
const max = Math.max(
1,
const rawMax = Math.max(
0,
...visible.flatMap((row) => [Number(row.downloads || 0), Number(row.uploads || 0)])
)
const max = rawMax <= 2 ? 3 : Math.ceil(rawMax / 3) * 3
const muted = props.isDarkMode ? '#9ca3af' : '#6b7280'
const border = props.isDarkMode ? '#374151' : '#e5e7eb'
const downloadColor = props.isDarkMode ? '#8fb6c5' : '#5f8fa3'
@@ -185,17 +187,23 @@ const draw = (timestamp = performance.now()) => {
}
const denominator = Math.max(1, windowSize.value - 1)
const plotLeft = padLeft
const plotRight = padLeft + width
const buildPoints = (field: 'downloads' | 'uploads') =>
visible
.map((row, index) => {
const sourceIndex = start + index
return {
x: padLeft + ((sourceIndex - offset.value) / denominator) * width,
x: clamp(
padLeft + ((sourceIndex - offset.value) / denominator) * width,
plotLeft,
plotRight
),
y: padTop + height - (Number(row[field] || 0) / max) * height,
row
}
})
.filter((point) => point.x >= padLeft - 50 && point.x <= padLeft + width + 50)
.filter((point) => point.x >= plotLeft && point.x <= plotRight)
const drawSeries = (points: ChartPoint[], color: string) => {
ctx.strokeStyle = color
@@ -392,17 +400,21 @@ const setHoverFromClientX = (clientX: number) => {
}
const handlePointerDown = (event: PointerEvent) => {
const rect = canvasRef.value?.getBoundingClientRect()
canvasRef.value?.setPointerCapture(event.pointerId)
cancelInertia()
velocity.value = 0
setHoverFromClientX(event.clientX)
const isTimeline = Boolean(rect && event.clientY - rect.top >= rect.height - 52)
drag.value = {
startX: event.clientX,
startOffset: offset.value,
lastX: event.clientX,
time: event.timeStamp || performance.now(),
pointerType: event.pointerType,
isTimeline,
moved: false
}
if (isTimeline) canvasRef.value!.style.touchAction = 'none'
}
const handlePointerMove = (event: PointerEvent) => {
@@ -416,12 +428,12 @@ const handlePointerMove = (event: PointerEvent) => {
return
}
if (drag.value.pointerType === 'touch') {
if (drag.value.pointerType === 'touch' && !drag.value.isTimeline) {
scheduleDraw()
return
}
const totalDistance = Math.abs(latestEvent.clientX - drag.value.startX)
const totalDistance = Math.abs(latestEvent.clientX - drag.value.lastX)
const threshold = 3
if (!drag.value.moved && totalDistance < threshold) {
scheduleDraw()
@@ -440,15 +452,18 @@ const handlePointerMove = (event: PointerEvent) => {
}
const handlePointerUp = () => {
const timelineDrag = drag.value?.isTimeline
const shouldInertia = Boolean(drag.value?.moved)
drag.value = null
if (canvasRef.value) canvasRef.value.style.touchAction = ''
cancelInertia()
if (shouldInertia) inertiaRafId.value = window.requestAnimationFrame(applyInertia)
if (shouldInertia && !timelineDrag) inertiaRafId.value = window.requestAnimationFrame(applyInertia)
else scheduleDraw()
}
const handlePointerCancel = () => {
drag.value = null
if (canvasRef.value) canvasRef.value.style.touchAction = ''
}
const handlePointerLeave = () => {