From ac187dc7402e68a06fe2c597b6a3ff22c20ffb11 Mon Sep 17 00:00:00 2001 From: rene Date: Fri, 5 Jun 2026 20:39:41 +0200 Subject: [PATCH 1/2] =?UTF-8?q?Radar-Timeline:=20Slider-Scrubbing=20gefixt?= =?UTF-8?q?=20+=20Breite/H=C3=B6he=20an=20Status-Pill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Scrub-Bug: _radarPause() setzte slider.value zurück, BEVOR der gezogene Wert gelesen wurde → sprang immer auf 'jetzt'. Jetzt Wert zuerst lesen. Scrubben stoppt Play + zeigt den Frame der Position (verifiziert: Klick 20%→Frame 2, Setter→5→Frame 5). - Breite per JS an .map-statusbar angeglichen (gleiche linke + rechte Kante), Höhe/Optik an die Pill (kleinerer Play-Button, flacher). --- VERSION | 2 +- backend/static/css/components.css | 17 ++++++++++------- backend/static/index.html | 24 ++++++++++++------------ backend/static/js/app.js | 2 +- backend/static/js/pages/map.js | 6 +++++- backend/static/landing.html | 2 +- backend/static/sw.js | 2 +- 7 files changed, 31 insertions(+), 24 deletions(-) diff --git a/VERSION b/VERSION index 08e9158..64e9c64 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1217 \ No newline at end of file +1219 \ No newline at end of file diff --git a/backend/static/css/components.css b/backend/static/css/components.css index 77b70ec..87dea9c 100644 --- a/backend/static/css/components.css +++ b/backend/static/css/components.css @@ -3053,17 +3053,18 @@ html.modal-open { .map-legend::-webkit-scrollbar { display: none; } /* Regenradar-Zeitleiste (RainViewer: ~2h Vergangenheit + ~30min Nowcast, Play/Pause + Slider) */ -/* Optik wie die Status-Pill darunter (hell/cremefarben, Blur, Border), direkt darüber gesetzt. */ +/* Optik + Maße wie die Status-Pill darunter: gleiche linke Kante (var(--space-3)); die Breite wird + per JS an die Pill angeglichen (gleiche rechte Kante). Höhe wie die Pill. */ .map-radar-timeline { position: absolute; left: var(--space-3); - right: 88px; /* Platz für die Ecken-FABs (Speed-Dial / Zurück) rechts */ - bottom: calc(var(--space-3) + 40px); /* unmittelbar über der Status-Pill */ + width: min(320px, calc(100% - 100px)); /* Fallback; JS setzt = Pill-Breite */ + bottom: calc(var(--space-3) + 34px); /* unmittelbar über der Status-Pill */ z-index: 900; display: flex; align-items:center; - gap: 8px; - padding: 4px 12px 4px 5px; + gap: 7px; + padding: 3px 12px 3px 4px; border-radius: var(--radius-full); background: rgba(255, 255, 255, 0.88); backdrop-filter: blur(4px); @@ -3071,6 +3072,7 @@ html.modal-open { border: 1px solid var(--c-border-light); color: var(--c-text); pointer-events: auto; + box-sizing: border-box; } :root[data-theme="dark"] .map-radar-timeline { background: rgba(24, 20, 16, 0.92); @@ -3078,19 +3080,20 @@ html.modal-open { } .rdr-play { flex-shrink: 0; - width: 30px; height: 30px; + width: 24px; height: 24px; border: none; border-radius: 50%; background: var(--c-surface-2); color: var(--c-text); cursor: pointer; display: flex; align-items: center; justify-content: center; } +.rdr-play svg { width: 14px; height: 14px; } .rdr-play:active { background: var(--c-border); } .rdr-slider { flex: 1; min-width: 0; height: 4px; accent-color: var(--c-primary); cursor: pointer; } .rdr-time { flex-shrink: 0; font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; - min-width: 78px; text-align: right; color: var(--c-text-secondary); + min-width: 74px; text-align: right; color: var(--c-text-secondary); } .rdr-time.is-forecast { color: var(--c-primary); } /* Nowcast/Vorhersage-Frames hervorgehoben */ diff --git a/backend/static/index.html b/backend/static/index.html index 60bf077..1770205 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -86,14 +86,14 @@ Ban Yaro - + - - - - - + + + + + @@ -617,11 +617,11 @@ - - - - - + + + + + @@ -631,7 +631,7 @@ - + diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 1433eb5..6d91f3c 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '1217'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '1219'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator) window.APP_VERSION = APP_VERSION; diff --git a/backend/static/js/pages/map.js b/backend/static/js/pages/map.js index 29bff06..568f5d3 100644 --- a/backend/static/js/pages/map.js +++ b/backend/static/js/pages/map.js @@ -621,12 +621,16 @@ window.Page_map = (() => { document.getElementById('central-map')?.appendChild(el); el.querySelector('#rdr-play').addEventListener('click', _toggleRadarPlay); el.querySelector('#rdr-slider').addEventListener('input', e => { + const idx = parseInt(e.target.value, 10); // ZUERST lesen: _radarPause() setzt slider.value zurück _radarPause(); - _showRadarFrame(parseInt(e.target.value, 10)); + _showRadarFrame(idx); }); } else { el.querySelector('#rdr-slider').max = _radarFrames.length - 1; } + // Breite an die Status-Pill angleichen → gleiche linke + rechte Kante. + const pill = document.querySelector('.map-statusbar'); + if (pill && pill.offsetWidth > 60) el.style.width = pill.offsetWidth + 'px'; _updateRadarTimelineUI(); } diff --git a/backend/static/landing.html b/backend/static/landing.html index 0b01da6..9eef0c0 100644 --- a/backend/static/landing.html +++ b/backend/static/landing.html @@ -4,7 +4,7 @@ - + Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz diff --git a/backend/static/sw.js b/backend/static/sw.js index 1affc8c..b3e17b8 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -4,7 +4,7 @@ ============================================================ */ // ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab -const VER = '1217'; +const VER = '1219'; const CACHE_VERSION = `by-v${VER}`; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten From 72ee339860e76187c4e665dbf0f0529c6e29d932 Mon Sep 17 00:00:00 2001 From: rene Date: Fri, 5 Jun 2026 20:53:51 +0200 Subject: [PATCH 2/2] Docs: DWD-Regen-Vorhersage-Pipeline gescoppt (Datenformat verifiziert) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DWD RV (composite/rv, kostenlos, alle 5 Min, 25 Frames 0-120min). Format verifiziert: 194-Byte-ASCII-Header + 1200×1100 uint16 LE, Wert=&0x0FFF×0.01mm, &0x2000=kein-Daten (PoC: Decode trivial, kein wradlib nötig). Pipeline: fetch→decode→kolorieren→reprojizieren(DE1200→3857)→Kacheln→PMTiles/Cron 5min; Frontend hängt Forecast-Frames rechts von 'jetzt' in die Timeline. Knackpunkt: Georeferenzierung (PoC nötig). --- docs/DWD_RAIN_FORECAST_PLAN.md | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 docs/DWD_RAIN_FORECAST_PLAN.md diff --git a/docs/DWD_RAIN_FORECAST_PLAN.md b/docs/DWD_RAIN_FORECAST_PLAN.md new file mode 100644 index 0000000..4c84e5d --- /dev/null +++ b/docs/DWD_RAIN_FORECAST_PLAN.md @@ -0,0 +1,56 @@ +# DWD Regen-Vorhersage (Radar-Nowcast) — Scoping-Plan + +**Status:** gescoppt + Datenformat verifiziert (2026-06-05). Umsetzung offen. +**Ziel:** Verlässliche, längere Regen-**Vorhersage** als animiertes Karten-Overlay (bis +2 h) statt RainViewers +unzuverlässigem 30-Min-Nowcast (der oft leer ist). Self-hosted wie die Basemap — passt zur Tile-Server-Philosophie. + +## Quelle: DWD RV (Composite RV) — kostenlos, kein API-Key +- `https://opendata.dwd.de/weather/radar/composite/rv/DE1200_RV.tar.bz2` +- **Alle 5 Min** publiziert. Jedes Archiv = ein Vorhersage-Lauf mit **25 Frames** `_000`…`_120` + (**0 bis +120 Min**, 5-Min-Schritte), je ~2,5 MB unkomprimiert (~1 MB als .tar.bz2). +- **Format (verifiziert):** RADOLAN-Binär. 194-Byte-ASCII-Header bis `ETX (0x03)`, dann **1200×1100 uint16 + little-endian** (= 2.640.000 Byte). Header-Felder: `PR E-02` (0,01 mm), `INT 5` (5-Min-Summe), + `GP1200x1100`, `VV` (Lead-Time). **Wert = `raw & 0x0FFF` × 0,01 mm/5min; `raw & 0x2000` = kein Daten.** + → Decode trivial, **kein wradlib nötig** (PoC: 1,32 Mio Zellen geparst, Regen korrekt erkannt). +- **Gitter/Projektion:** DE1200 (1 km), polar-stereografisch, fest georeferenziert (Eckkoordinaten dokumentiert; + wradlib `get_radolan_grid` ODER GDAL mit dem bekannten RADOLAN-PROJ-String). +- **Abdeckung:** Deutschland + Randbereiche (reicht etwas nach AT/CH/Nachbarn, aber DE-zentriert). + Voll-AT/CH bräuchte ACG/MeteoSwiss → out of scope. + +## Pipeline (Server-seitig, Cron alle 5 Min — analog zum OSM-POI-Job) +1. **Fetch** neueste `DE1200_RV