feat: assen bij de luchtdrukgrafiek

De lijn had geen schaal, dus je kon niet zien hoeveel hPa de uitslag was
of wanneer een dip viel. Nu links de hoogste en laagste waarde van het
venster in hele hPa, uitgelijnd op boven- en onderkant van de lijn, en
eronder vijf tijdlabels (0/25/50/75/100% van het venster) met "nu"
rechts, ondersteund door drie lichte verticale hulplijnen. Posities
komen uit de pure functie axisMarks(), met tests.

De losse tekst "1009 – 1015 hPa in 24 u" in de kopregel vervalt: de
y-as zegt hetzelfde en de x-as maakt het venster duidelijk. De extra
labelrij past door de marge onder de grote temperatuur 8px te krappen;
er blijft 5px speling boven en onder de hero. Servicewerker naar v8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-13 11:30:11 +02:00
co-authored by Claude Opus 5
parent c95d198341
commit c0715b7cc9
7 changed files with 77 additions and 14 deletions
+13 -2
View File
@@ -2,7 +2,7 @@ import {
f1, fInt, fmm, markerPos, barHeights, wmoIcon, trendLabel,
formatDate, formatTime, dayAbbr, monthName, isOlderThan, msUntil,
co2Level, fPct, fHpa, seriesRange, sparklinePath,
windArrowDeg, fKmh, formatHour, formatFullDate, pinRoom,
windArrowDeg, fKmh, formatHour, formatFullDate, pinRoom, axisMarks,
} from './format.js';
import { icon, windArrow } from './icons.js';
@@ -104,10 +104,21 @@ function renderRain(rain, now) {
function renderPressure(p) {
setText('press', fHpa(p.current));
setText('press-trend', trendLabel(p.trend));
const values = p.history.map((h) => h.hpa);
const range = seriesRange(values);
setText('press-range', range ? `${Math.round(range.min)} – ${Math.round(range.max)} hPa in 24 u` : '');
setText('press-max', range ? String(Math.round(range.max)) : '–');
setText('press-min', range ? String(Math.round(range.min)) : '–');
$('press-path').setAttribute('d', sparklinePath(values, 560, 56));
// Tijdlabels op dezelfde posities als de punten waar ze bij horen; de laatste is "nu".
const marks = axisMarks(p.history.length);
$('press-hours').innerHTML = marks.map((m, i) => {
const last = i === marks.length - 1;
const label = last ? 'nu' : formatTime(p.history[m.index].at, state.tz);
const style = i === 0 ? 'left:0' : last ? 'right:0' : `left:${m.percent}%;transform:translateX(-50%)`;
return `<span style="${style}">${label}</span>`;
}).join('');
}
function renderForecast(days) {
+10
View File
@@ -219,3 +219,13 @@ export function pinRoom(rooms, pinnedId) {
copy.unshift(pinned);
return copy;
}
/**
* Posities voor labels langs een as. Geeft per fractie de bijbehorende index in een reeks van
* `length` punten, plus het percentage waarop dat label hoort te staan. Onder de 2 punten valt er
* niets zinnigs te labelen.
*/
export function axisMarks(length, fractions = [0, 0.25, 0.5, 0.75, 1]) {
if (length < 2) return [];
return fractions.map((f) => ({ index: Math.round(f * (length - 1)), percent: f * 100 }));
}
+13 -5
View File
@@ -36,11 +36,19 @@
</div>
</div>
<div class="a-pressure">
<p class="a-plabel">Luchtdruk <b class="num" id="press">–</b><span class="a-trend" id="press-trend"></span><span class="a-prange num" id="press-range"></span></p>
<svg class="a-spark" viewBox="0 0 560 56" preserveAspectRatio="none" aria-hidden="true">
<line class="a-spark-base" x1="0" y1="55.5" x2="560" y2="55.5"/>
<path class="a-spark-line" id="press-path" d=""/>
</svg>
<p class="a-plabel">Luchtdruk <b class="num" id="press">–</b><span class="a-trend" id="press-trend"></span></p>
<div class="a-pgrid">
<div class="a-py num"><span id="press-max">–</span><span id="press-min">–</span></div>
<svg class="a-spark" viewBox="0 0 560 56" preserveAspectRatio="none" aria-hidden="true">
<line class="a-spark-grid" x1="140" y1="0" x2="140" y2="56"/>
<line class="a-spark-grid" x1="280" y1="0" x2="280" y2="56"/>
<line class="a-spark-grid" x1="420" y1="0" x2="420" y2="56"/>
<line class="a-spark-base" x1="0" y1="55.5" x2="560" y2="55.5"/>
<path class="a-spark-line" id="press-path" d=""/>
</svg>
<div></div>
<div class="a-px num" id="press-hours"></div>
</div>
</div>
</section>
+9 -5
View File
@@ -80,7 +80,7 @@ html, body {
.a-hero { align-self: center; }
.a-label { font-size: 22px; color: var(--muted); font-weight: 500; display: flex; gap: 14px; align-items: baseline; }
.a-trend { font-size: 17px; font-weight: 400; }
.a-temp { font-size: 200px; font-weight: 200; letter-spacing: -.045em; line-height: .95; margin: 4px 0 18px -8px; }
.a-temp { font-size: 200px; font-weight: 200; letter-spacing: -.045em; line-height: .95; margin: 4px 0 10px -8px; }
.a-hum { font-size: 17px; font-weight: 400; }
.a-hum:not(:empty)::before { content: "·"; margin-right: 14px; }
.a-range { width: 560px; }
@@ -89,13 +89,17 @@ html, body {
.a-ends { display: flex; justify-content: space-between; margin-top: 14px; font-size: 17px; color: var(--muted); }
.a-ends b { font-size: 24px; font-weight: 600; margin-right: 6px; }
/* Luchtdruk, 24 uur */
.a-pressure { width: 560px; margin-top: 18px; }
/* Luchtdruk, 24 uur. Grafiek met een y-as (hoogste/laagste waarde) en tijdlabels op de x-as. */
.a-pressure { width: 560px; margin-top: 14px; }
.a-plabel { font-size: 17px; color: var(--muted); display: flex; gap: 12px; align-items: baseline; margin-bottom: 6px; }
.a-plabel b { font-size: 20px; font-weight: 600; color: var(--ink); }
.a-prange { margin-left: auto; font-size: 14px; }
.a-spark { display: block; width: 560px; height: 56px; overflow: visible; }
.a-pgrid { display: grid; grid-template-columns: 44px 1fr; column-gap: 8px; row-gap: 3px; }
.a-py { display: flex; flex-direction: column; justify-content: space-between; text-align: right; font-size: 13px; color: var(--muted); line-height: 1; padding: 1px 0; }
.a-px { position: relative; height: 17px; font-size: 13px; color: var(--muted); }
.a-px span { position: absolute; top: 0; white-space: nowrap; }
.a-spark { display: block; width: 100%; height: 56px; overflow: visible; }
.a-spark-base { stroke: var(--line); stroke-width: 1; }
.a-spark-grid { stroke: var(--line); stroke-width: 1; vector-effect: non-scaling-stroke; opacity: .6; }
.a-spark-line { fill: none; stroke: var(--rain); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
/* Binnen */
+1 -1
View File
@@ -1,6 +1,6 @@
/* Service worker: app-shell cache-first, API network-first met timeout en fallback op de laatste response. */
const VERSION = 'weerscherm-v7';
const VERSION = 'weerscherm-v8';
const SHELL = [
'./',
'./index.html',