From fd58320c8b6c3c8de5fa5fa9b71bd72691f5afd0 Mon Sep 17 00:00:00 2001 From: Orion Date: Fri, 10 Jul 2026 15:20:20 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=88=20=E4=BF=AE=E6=AD=A3=E8=B6=8B?= =?UTF-8?q?=E5=8A=BF=E5=9B=BE=E6=95=B4=E6=95=B0=E5=88=BB=E5=BA=A6=E5=AF=B9?= =?UTF-8?q?=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/SmoothTrendCanvas.vue | 22 ++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/components/common/SmoothTrendCanvas.vue b/src/components/common/SmoothTrendCanvas.vue index 158b187..3b4275e 100644 --- a/src/components/common/SmoothTrendCanvas.vue +++ b/src/components/common/SmoothTrendCanvas.vue @@ -88,6 +88,16 @@ const INERTIA_DECAY_PER_120HZ_FRAME = 0.96 const INERTIA_STOP_VELOCITY = 0.01 const HOVER_EASE_PER_120HZ_FRAME = 0.34 const HOVER_SNAP_DISTANCE = 0.2 +const getYAxisTicks = (rawMax: number) => { + const roundedMax = Math.max(1, Math.ceil(rawMax)) + if (roundedMax <= 4) { + return Array.from({ length: roundedMax + 1 }, (_, index) => roundedMax - index) + } + + const step = Math.ceil(roundedMax / 4) + const scaleMax = step * Math.ceil(roundedMax / step) + return Array.from({ length: scaleMax / step + 1 }, (_, index) => scaleMax - index * step) +} const panelClass = computed(() => props.isDarkMode @@ -167,7 +177,8 @@ const draw = (timestamp = performance.now()) => { 0, ...visible.flatMap((row) => [Number(row.downloads || 0), Number(row.uploads || 0)]) ) - const max = rawMax <= 2 ? 3 : Math.ceil(rawMax / 3) * 3 + const yTicks = getYAxisTicks(rawMax) + const max = yTicks[0] const muted = props.isDarkMode ? '#9ca3af' : '#6b7280' const border = props.isDarkMode ? '#374151' : '#e5e7eb' const downloadColor = props.isDarkMode ? '#8fb6c5' : '#5f8fa3' @@ -177,14 +188,15 @@ const draw = (timestamp = performance.now()) => { ctx.lineWidth = 1 ctx.fillStyle = muted ctx.font = '12px system-ui' - for (let i = 0; i < 4; i += 1) { - const y = padTop + (height * i) / 3 + const yTickCount = Math.max(1, yTicks.length - 1) + yTicks.forEach((tick, index) => { + const y = padTop + (height * index) / yTickCount ctx.beginPath() ctx.moveTo(padLeft, y) ctx.lineTo(padLeft + width, y) ctx.stroke() - ctx.fillText(String(Math.round(max * (1 - i / 3))), 4, y + 4) - } + ctx.fillText(String(tick), 4, y + 4) + }) const denominator = Math.max(1, windowSize.value - 1) const plotLeft = padLeft