GL-Karte: Ortsnamen-Labels (Glyphs self-hosted) + ScaleControl raus (lag unter der Status-Pill)

- main.py: /fonts-Mount (Glyph-PBFs aus data/tiles/fonts), Open Sans Regular self-hosted
- map-gl-style.js: glyphs-URL + Label-Layer (Ortsnamen/Straßen/Gewässer, name:de)
- map.js _initMapGL: ScaleControl entfernt (überdeckte die Zoom/Wetter/Zecken-Pill)
Ortsnamen für Orientierung (René), auch bei kleinem Zoom.
This commit is contained in:
rene 2026-06-05 11:09:08 +02:00
parent 4d0cd0f460
commit 9c959dd632
8 changed files with 54 additions and 17 deletions

View file

@ -1 +1 @@
1186 1187

View file

@ -381,6 +381,12 @@ app.mount("/img", StaticFiles(directory=f"{STATIC_DIR}/img"), name="img")
# (Range nativ, keine App-CPU) — siehe docs/TILE_SERVER_HANDOVER.md, Entscheidung #2. # (Range nativ, keine App-CPU) — siehe docs/TILE_SERVER_HANDOVER.md, Entscheidung #2.
_TILES_DIR = os.getenv("TILES_DIR", "/data/tiles") _TILES_DIR = os.getenv("TILES_DIR", "/data/tiles")
# Glyphs (Font-PBFs) für MapLibre-Labels — kleine Static-Files (kein Range nötig),
# liegen im data-Volume unter tiles/fonts/{fontstack}/{range}.pbf.
_FONTS_DIR = os.getenv("FONTS_DIR", os.path.join(_TILES_DIR, "fonts"))
if os.path.isdir(_FONTS_DIR):
app.mount("/fonts", StaticFiles(directory=_FONTS_DIR), name="fonts")
@app.api_route("/tiles/{filename}", methods=["GET", "HEAD"]) @app.api_route("/tiles/{filename}", methods=["GET", "HEAD"])
async def serve_tile(filename: str, request: Request): async def serve_tile(filename: str, request: Request):
# Kein Path-Traversal # Kein Path-Traversal

View file

@ -86,14 +86,14 @@
<title>Ban Yaro</title> <title>Ban Yaro</title>
<!-- Theme + theme-color Statusleiste vor CSS setzen --> <!-- Theme + theme-color Statusleiste vor CSS setzen -->
<script src="/js/boot-early.js?v=1186"></script> <script src="/js/boot-early.js?v=1187"></script>
<!-- CSS: Reihenfolge ist wichtig — ?v= zwingt Browser zur Neuladung --> <!-- CSS: Reihenfolge ist wichtig — ?v= zwingt Browser zur Neuladung -->
<link rel="stylesheet" href="/css/design-system.css?v=1186"> <link rel="stylesheet" href="/css/design-system.css?v=1187">
<link rel="stylesheet" href="/css/layout.css?v=1186"> <link rel="stylesheet" href="/css/layout.css?v=1187">
<link rel="stylesheet" href="/css/components.css?v=1186"> <link rel="stylesheet" href="/css/components.css?v=1187">
<link rel="stylesheet" href="/css/utilities.css?v=1186"> <link rel="stylesheet" href="/css/utilities.css?v=1187">
<link rel="stylesheet" href="/css/lists.css?v=1186"> <link rel="stylesheet" href="/css/lists.css?v=1187">
</head> </head>
<body> <body>
@ -617,11 +617,11 @@
<div id="modal-container"></div> <div id="modal-container"></div>
<!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features --> <!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features -->
<script src="/js/api.js?v=1186"></script> <script src="/js/api.js?v=1187"></script>
<script src="/js/ui.js?v=1186"></script> <script src="/js/ui.js?v=1187"></script>
<script src="/js/app.js?v=1186"></script> <script src="/js/app.js?v=1187"></script>
<script src="/js/worlds.js?v=1186"></script> <script src="/js/worlds.js?v=1187"></script>
<script src="/js/offline-indicator.js?v=1186"></script> <script src="/js/offline-indicator.js?v=1187"></script>
<!-- Feature-Seiten werden lazy geladen --> <!-- Feature-Seiten werden lazy geladen -->
@ -631,7 +631,7 @@
<!-- Boot: Offline-Banner + SW-Registration (extrahiert für CSP) --> <!-- Boot: Offline-Banner + SW-Registration (extrahiert für CSP) -->
<script src="/js/boot.js?v=1186"></script> <script src="/js/boot.js?v=1187"></script>
</body> </body>

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung. Router, State-Management, Navigation, Initialisierung.
============================================================ */ ============================================================ */
const APP_VER = '1186'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VER = '1187'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt 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_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator)
window.APP_VERSION = APP_VERSION; window.APP_VERSION = APP_VERSION;

View file

@ -13,20 +13,25 @@
bg: '#f4f1ec', land: '#dce8c8', park: '#c8e6b0', water: '#a0c8f0', bg: '#f4f1ec', land: '#dce8c8', park: '#c8e6b0', water: '#a0c8f0',
road: '#ffffff', roadCasing: '#d9cfc2', building: '#e6ddcf', road: '#ffffff', roadCasing: '#d9cfc2', building: '#e6ddcf',
buildingLine: '#d4cabb', boundary: '#b08ac0', buildingLine: '#d4cabb', boundary: '#b08ac0',
label: '#33312e', roadLabel: '#6b6357', waterLabel: '#4a78a8', labelHalo: 'rgba(255,255,255,0.9)',
}, },
dark: { dark: {
bg: '#1a1d21', land: '#222820', park: '#27331f', water: '#16242e', bg: '#1a1d21', land: '#222820', park: '#27331f', water: '#16242e',
road: '#3a4046', roadCasing: '#23282d', building: '#262b30', road: '#3a4046', roadCasing: '#23282d', building: '#262b30',
buildingLine: '#31373d', boundary: '#7d5a8c', buildingLine: '#31373d', boundary: '#7d5a8c',
label: '#d6d9dd', roadLabel: '#9aa0a6', waterLabel: '#6fa0cc', labelHalo: 'rgba(0,0,0,0.8)',
}, },
}; };
var FONT = ['Open Sans Regular'];
// Liefert ein MapLibre-Style-JSON (Version 8) ohne glyphs/sprite. // Liefert ein MapLibre-Style-JSON (Version 8) ohne glyphs/sprite.
function build(opts) { function build(opts) {
opts = opts || {}; opts = opts || {};
var t = THEMES[opts.dark ? 'dark' : 'light']; var t = THEMES[opts.dark ? 'dark' : 'light'];
return { return {
version: 8, version: 8,
glyphs: window.location.origin + '/fonts/{fontstack}/{range}.pbf',
sources: { sources: {
by: { type: 'vector', url: 'pmtiles://' + tilesUrl() }, by: { type: 'vector', url: 'pmtiles://' + tilesUrl() },
}, },
@ -52,6 +57,33 @@
paint: { 'fill-color': t.building, 'fill-outline-color': t.buildingLine } }, paint: { 'fill-color': t.building, 'fill-outline-color': t.buildingLine } },
{ id: 'boundary', type: 'line', source: 'by', 'source-layer': 'boundary', { id: 'boundary', type: 'line', source: 'by', 'source-layer': 'boundary',
paint: { 'line-color': t.boundary, 'line-dasharray': [2, 2], 'line-width': 1 } }, paint: { 'line-color': t.boundary, 'line-dasharray': [2, 2], 'line-width': 1 } },
// ---- Labels (brauchen glyphs) ----
{ id: 'water-labels', type: 'symbol', source: 'by', 'source-layer': 'water_name',
layout: {
'text-field': ['coalesce', ['get', 'name:de'], ['get', 'name']],
'text-font': FONT, 'text-size': 12, 'text-max-width': 6,
},
paint: { 'text-color': t.waterLabel, 'text-halo-color': t.labelHalo, 'text-halo-width': 1.2 } },
{ id: 'street-labels', type: 'symbol', source: 'by', 'source-layer': 'transportation_name',
minzoom: 14,
layout: {
'text-field': ['coalesce', ['get', 'name:de'], ['get', 'name']],
'text-font': FONT, 'symbol-placement': 'line', 'text-size': 11,
},
paint: { 'text-color': t.roadLabel, 'text-halo-color': t.labelHalo, 'text-halo-width': 1.2 } },
// Ortsnamen (Städte/Dörfer) — wichtig für Orientierung, auch bei kleinem Zoom.
{ id: 'place-labels', type: 'symbol', source: 'by', 'source-layer': 'place',
filter: ['in', ['get', 'class'], ['literal', ['city', 'town', 'village', 'suburb', 'hamlet', 'neighbourhood']]],
layout: {
'text-field': ['coalesce', ['get', 'name:de'], ['get', 'name']],
'text-font': FONT, 'text-max-width': 8, 'text-anchor': 'center',
'text-size': ['interpolate', ['linear'], ['zoom'],
4, 10, 8, 12, 12, 14, 16, 17],
},
paint: { 'text-color': t.label, 'text-halo-color': t.labelHalo, 'text-halo-width': 1.6 } },
], ],
}; };
} }

View file

@ -756,7 +756,6 @@ window.Page_map = (() => {
// Pinch bleibt in der Karte (verhindert iOS-Page-Zoom), ohne globales user-scalable=no. // Pinch bleibt in der Karte (verhindert iOS-Page-Zoom), ohne globales user-scalable=no.
el.style.touchAction = 'none'; el.style.touchAction = 'none';
_map.addControl(new maplibregl.NavigationControl({ showCompass: false }), 'top-left'); _map.addControl(new maplibregl.NavigationControl({ showCompass: false }), 'top-left');
_map.addControl(new maplibregl.ScaleControl());
_map.addControl(new maplibregl.AttributionControl({ _map.addControl(new maplibregl.AttributionControl({
compact: true, customAttribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', compact: true, customAttribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
})); }));

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark"> <meta name="color-scheme" content="light dark">
<script src="/js/landing-init.js?v=1186"></script> <script src="/js/landing-init.js?v=1187"></script>
<title>Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz</title> <title>Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz</title>
<meta name="description" content="Ban Yaro: Die kostenlose All-in-One Hunde-App für DACH. Tagebuch, Giftköder-Alarm, Training mit KI, Forum, Wurfbörse, Stammbaum, Inzucht-Check — DSGVO-konform, offline-fähig, ohne App Store."> <meta name="description" content="Ban Yaro: Die kostenlose All-in-One Hunde-App für DACH. Tagebuch, Giftköder-Alarm, Training mit KI, Forum, Wurfbörse, Stammbaum, Inzucht-Check — DSGVO-konform, offline-fähig, ohne App Store.">
<meta name="keywords" content="Hunde App, Hunde Community, Wurfbörse, Züchter, Welpen kaufen, Stammbaum Hund, Inzuchtkoeffizient, Hundezucht, Impfpass Hund, Giftköder Alarm, Gassi Community, Hundetraining App, Hunde Forum, Hunde KI, Hundefilm Datenbank, Welpen Marktplatz"> <meta name="keywords" content="Hunde App, Hunde Community, Wurfbörse, Züchter, Welpen kaufen, Stammbaum Hund, Inzuchtkoeffizient, Hundezucht, Impfpass Hund, Giftköder Alarm, Gassi Community, Hundetraining App, Hunde Forum, Hunde KI, Hundefilm Datenbank, Welpen Marktplatz">

View file

@ -4,7 +4,7 @@
============================================================ */ ============================================================ */
// ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab // ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab
const VER = '1186'; const VER = '1187';
const CACHE_VERSION = `by-v${VER}`; const CACHE_VERSION = `by-v${VER}`;
const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten