Make the Sleep trend chart taller with a finer 1-hour y-axis
220px viewBox (was 160) and 1-hour gridlines via a trend-specific axis helper, so curves that run close together separate visually. Labels drop to every other gridline past 16 steps to keep the text readable.
This commit is contained in:
+15
-3
@@ -1341,10 +1341,18 @@
|
|||||||
return { today, yesterday, avg, avgDays, projected };
|
return { today, yesterday, avg, avgDays, projected };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trend-specific y-axis: 1-hour gridlines (vs the bar charts' 2-hour steps)
|
||||||
|
// so nearby curves separate visually; still capped at 24h.
|
||||||
|
function niceAxisTrendHours(rawMax) {
|
||||||
|
if (!(rawMax > 0)) return { yMax: 2, steps: 2 };
|
||||||
|
const m = Math.min(24, Math.max(2, Math.ceil(rawMax)));
|
||||||
|
return { yMax: m, steps: m };
|
||||||
|
}
|
||||||
|
|
||||||
function drawSleepTrendChart(curves) {
|
function drawSleepTrendChart(curves) {
|
||||||
const svg = document.getElementById("chart-sleep-trend");
|
const svg = document.getElementById("chart-sleep-trend");
|
||||||
if (!svg) return;
|
if (!svg) return;
|
||||||
const W = 320, H = 160;
|
const W = 320, H = 220;
|
||||||
const ML = 26, MR = 8, MT = 10, MB = 22;
|
const ML = 26, MR = 8, MT = 10, MB = 22;
|
||||||
const innerW = W - ML - MR;
|
const innerW = W - ML - MR;
|
||||||
const innerH = H - MT - MB;
|
const innerH = H - MT - MB;
|
||||||
@@ -1358,18 +1366,22 @@
|
|||||||
].filter(s => s.pts && s.pts.length > 1);
|
].filter(s => s.pts && s.pts.length > 1);
|
||||||
|
|
||||||
const rawMax = Math.max(...series.flatMap(s => s.pts.map(p => p.y)));
|
const rawMax = Math.max(...series.flatMap(s => s.pts.map(p => p.y)));
|
||||||
const { yMax, steps: ySteps } = niceAxisSleepHours(rawMax);
|
const { yMax, steps: ySteps } = niceAxisTrendHours(rawMax);
|
||||||
|
|
||||||
const xOf = (hour) => ML + (hour / 24) * innerW;
|
const xOf = (hour) => ML + (hour / 24) * innerW;
|
||||||
const yOf = (v) => MT + innerH * (1 - v / yMax);
|
const yOf = (v) => MT + innerH * (1 - v / yMax);
|
||||||
|
|
||||||
|
// Every gridline gets a label unless that would crowd the 9px text.
|
||||||
|
const labelEvery = ySteps > 16 ? 2 : 1;
|
||||||
const parts = [];
|
const parts = [];
|
||||||
for (let i = 0; i <= ySteps; i++) {
|
for (let i = 0; i <= ySteps; i++) {
|
||||||
const y = MT + innerH * (1 - i / ySteps);
|
const y = MT + innerH * (1 - i / ySteps);
|
||||||
const v = Math.round(yMax * i / ySteps * 10) / 10;
|
const v = Math.round(yMax * i / ySteps * 10) / 10;
|
||||||
const vText = v % 1 === 0 ? v : v.toFixed(1);
|
const vText = v % 1 === 0 ? v : v.toFixed(1);
|
||||||
parts.push(`<line class="grid" x1="${ML}" y1="${y}" x2="${W - MR}" y2="${y}"/>`);
|
parts.push(`<line class="grid" x1="${ML}" y1="${y}" x2="${W - MR}" y2="${y}"/>`);
|
||||||
parts.push(`<text x="${ML - 4}" y="${y + 3}" text-anchor="end">${vText}h</text>`);
|
if (i % labelEvery === 0) {
|
||||||
|
parts.push(`<text x="${ML - 4}" y="${y + 3}" text-anchor="end">${vText}h</text>`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const hr of [0, 6, 12, 18, 24]) {
|
for (const hr of [0, 6, 12, 18, 24]) {
|
||||||
const x = xOf(hr);
|
const x = xOf(hr);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
[
|
[
|
||||||
|
{ "date": "2026-07-15", "text": "The Sleep trend chart is taller with 1-hour gridlines, so nearby lines are easier to tell apart" },
|
||||||
{ "date": "2026-07-15", "text": "The Sleep trend legend shows the hours for each line — Today, Yesterday and the average, next to the projection" },
|
{ "date": "2026-07-15", "text": "The Sleep trend legend shows the hours for each line — Today, Yesterday and the average, next to the projection" },
|
||||||
{ "date": "2026-07-15", "text": "The Sleep trend chart projects where today will land by midnight — a dashed tail continues today's line following the average day's rhythm" },
|
{ "date": "2026-07-15", "text": "The Sleep trend chart projects where today will land by midnight — a dashed tail continues today's line following the average day's rhythm" },
|
||||||
{ "date": "2026-07-15", "text": "The charts highlight the selected day, so it's easy to spot which bars, rows and cells you're looking at" },
|
{ "date": "2026-07-15", "text": "The charts highlight the selected day, so it's easy to spot which bars, rows and cells you're looking at" },
|
||||||
|
|||||||
+1
-1
@@ -222,7 +222,7 @@
|
|||||||
|
|
||||||
<section class="patterns" data-panel="sleep-trend">
|
<section class="patterns" data-panel="sleep-trend">
|
||||||
<h2>Sleep trend</h2>
|
<h2>Sleep trend</h2>
|
||||||
<svg id="chart-sleep-trend" class="chart-svg" viewBox="0 0 320 160" role="img" aria-label="Cumulative sleep hours through the day: today, yesterday, the recent average and the projected end-of-day total"></svg>
|
<svg id="chart-sleep-trend" class="chart-svg" viewBox="0 0 320 220" role="img" aria-label="Cumulative sleep hours through the day: today, yesterday, the recent average and the projected end-of-day total"></svg>
|
||||||
<div class="legend">
|
<div class="legend">
|
||||||
<span class="lg trend-today"><span class="sw"></span><span id="legend-trend-today-text">Today</span></span>
|
<span class="lg trend-today"><span class="sw"></span><span id="legend-trend-today-text">Today</span></span>
|
||||||
<span class="lg trend-projected" id="legend-trend-projected" hidden><span class="sw"></span><span id="legend-trend-projected-text">Projected</span></span>
|
<span class="lg trend-projected" id="legend-trend-projected" hidden><span class="sw"></span><span id="legend-trend-projected-text">Projected</span></span>
|
||||||
|
|||||||
Reference in New Issue
Block a user