From f6c93ad9d9069f17fb282384c96b0dc0dcb18c52 Mon Sep 17 00:00:00 2001 From: Damocles Date: Sat, 25 Apr 2026 10:49:08 +0200 Subject: [PATCH] sparkline: smooth quadratic curves between data points --- shell/applets/SparklineCanvas.qml | 42 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/shell/applets/SparklineCanvas.qml b/shell/applets/SparklineCanvas.qml index 8f73858..614fab4 100644 --- a/shell/applets/SparklineCanvas.qml +++ b/shell/applets/SparklineCanvas.qml @@ -103,30 +103,43 @@ Canvas { ctx.stroke(); } - // Build polygon path + // Smooth curve through sample midpoints + function midX(i) { + const [bx, bw] = xOf(i); + return bx + bw / 2; + } + function traceCurve() { + ctx.moveTo(0, yOf(d[0])); + if (n === 1) { + ctx.lineTo(width, yOf(d[0])); + } else { + ctx.lineTo(midX(0), yOf(d[0])); + for (let i = 0; i < n - 1; i++) { + const mx = (midX(i) + midX(i + 1)) / 2; + ctx.quadraticCurveTo(midX(i), yOf(d[i]), mx, (yOf(d[i]) + yOf(d[i + 1])) / 2); + } + ctx.lineTo(midX(n - 1), yOf(d[n - 1])); + ctx.lineTo(width, yOf(d[n - 1])); + } + } + + // Filled polygon const baseY = lo < 0 ? yOf(0) : height; ctx.beginPath(); ctx.moveTo(0, baseY); - for (let i = 0; i < n; i++) { - const [bx, bw] = xOf(i); - const y = yOf(d[i]); - ctx.lineTo(bx, y); - ctx.lineTo(bx + bw, y); - } + traceCurve(); ctx.lineTo(width, baseY); ctx.closePath(); // Vertical gradient fill const grad = ctx.createLinearGradient(0, height, 0, 0); if (colorAt) { - // Explicit colorAt: sample across the value range const steps = 8; for (let s = 0; s <= steps; s++) { const frac = s / steps; grad.addColorStop(frac, colorAt(lo + frac * range).toString()); } } else if (thresholds.length) { - // Auto-derive from thresholds as smooth gradient const sorted = thresholds.slice().sort((a, b) => a.value - b.value); grad.addColorStop(0, strokeColor.toString()); for (const th of sorted) { @@ -137,7 +150,6 @@ Canvas { } grad.addColorStop(1, sorted[sorted.length - 1].color.toString()); } else { - // Uniform fill grad.addColorStop(0, strokeColor.toString()); grad.addColorStop(1, strokeColor.toString()); } @@ -146,15 +158,7 @@ Canvas { // Stroke line on top ctx.beginPath(); - for (let i = 0; i < n; i++) { - const [bx, bw] = xOf(i); - const y = yOf(d[i]); - if (i === 0) - ctx.moveTo(bx, y); - else - ctx.lineTo(bx, y); - ctx.lineTo(bx + bw, y); - } + traceCurve(); ctx.strokeStyle = strokeColor.toString(); ctx.lineWidth = root.lineWidth; ctx.stroke();