From e1d20c24077c30cf6d26dd033c1b3a5e31302d4b Mon Sep 17 00:00:00 2001 From: Damocles Date: Sat, 25 Apr 2026 10:10:59 +0200 Subject: [PATCH] sparkline: render as continuous filled polygon with gradient color interpolation --- shell/applets/SparklineCanvas.qml | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/shell/applets/SparklineCanvas.qml b/shell/applets/SparklineCanvas.qml index 4322656..8f32f47 100644 --- a/shell/applets/SparklineCanvas.qml +++ b/shell/applets/SparklineCanvas.qml @@ -133,22 +133,30 @@ Canvas { ctx.lineWidth = root.lineWidth; ctx.stroke(); } else { - // Bar chart - bars grow from zero line (or bottom if all positive) + // Filled area - continuous polygon, no visible bar boundaries const hasCF = typeof colorFunction === "function"; - const zy = lo < 0 ? yOf(0) : height; - if (!hasCF) - ctx.fillStyle = color.toString(); + const baseY = lo < 0 ? yOf(0) : height; + ctx.beginPath(); + ctx.moveTo(0, baseY); for (let i = 0; i < n; i++) { - if (hasCF) - ctx.fillStyle = colorFunction(d[i]).toString(); const [bx, bw] = xOf(i); - const x0 = Math.floor(bx); - const x1 = Math.floor(bx + bw); - const dy = yOf(d[i]); - const barTop = Math.min(dy, zy); - const barH = Math.max(1, Math.abs(dy - zy)); - ctx.fillRect(x0, barTop, Math.max(1, x1 - x0), barH); + const y = yOf(d[i]); + ctx.lineTo(bx, y); + ctx.lineTo(bx + bw, y); } + ctx.lineTo(width, baseY); + ctx.closePath(); + if (hasCF) { + const grad = ctx.createLinearGradient(0, 0, width, 0); + for (let i = 0; i < n; i++) { + const [bx, bw] = xOf(i); + grad.addColorStop(Math.min(1, (bx + bw / 2) / width), colorFunction(d[i]).toString()); + } + ctx.fillStyle = grad; + } else { + ctx.fillStyle = color.toString(); + } + ctx.fill(); } } }