From af496380bf7034510845fe6df0b357c63ab47f23 Mon Sep 17 00:00:00 2001 From: Stream Date: Sun, 3 May 2026 13:50:01 +0300 Subject: [PATCH] auto-sync: 2026-05-03 13:50:01 --- tasks/enduro-trails/prototype/app.py | 2 +- tasks/enduro-trails/prototype/static/app.css | 67 +++++++++++++++++++ tasks/enduro-trails/prototype/static/app.js | 59 ++++++++++++++++ .../enduro-trails/prototype/static/index.html | 5 ++ 4 files changed, 132 insertions(+), 1 deletion(-) diff --git a/tasks/enduro-trails/prototype/app.py b/tasks/enduro-trails/prototype/app.py index 4a97680..4c4ebf9 100644 --- a/tasks/enduro-trails/prototype/app.py +++ b/tasks/enduro-trails/prototype/app.py @@ -332,4 +332,4 @@ if os.path.exists(STATIC_DIR): if __name__ == "__main__": print(f"==> Enduro Trails API DB={DATA_PATH} Port={PORT}") - uvicorn.run(app, host="0.0.0.0", port=PORT) + uvicorn.run("app:app", host="0.0.0.0", port=PORT, workers=4) diff --git a/tasks/enduro-trails/prototype/static/app.css b/tasks/enduro-trails/prototype/static/app.css index 10dcaa4..09d5c08 100644 --- a/tasks/enduro-trails/prototype/static/app.css +++ b/tasks/enduro-trails/prototype/static/app.css @@ -211,3 +211,70 @@ body { font-family: monospace; color: #333; } + +/* ─── Кастомные кнопки управления ────────────────────────────────────────── */ +.custom-map-ctrl { + position: absolute; + right: 10px; + display: flex; + flex-direction: column; + gap: 6px; + z-index: 5; +} + +#map-controls-br { + bottom: 40px; +} + +.map-ctrl-btn { + width: 36px; + height: 36px; + background: #fff; + border: 1px solid #ccc; + border-radius: 4px; + cursor: pointer; + font-size: 18px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 1px 4px rgba(0,0,0,0.15); + transition: background 0.15s; + user-select: none; +} + +.map-ctrl-btn:hover { background: #f5f5f5; } +.map-ctrl-btn.active { background: #ff6600; border-color: #ff6600; } + +/* ─── Маркер текущего местоположения ─────────────────────────────────────── */ +.my-location-marker { + position: relative; + width: 20px; + height: 20px; +} + +.my-location-dot { + position: absolute; + top: 50%; left: 50%; + transform: translate(-50%, -50%); + width: 14px; height: 14px; + background: #ff6600; + border: 2px solid #fff; + border-radius: 50%; + box-shadow: 0 0 4px rgba(0,0,0,0.3); + z-index: 2; +} + +.my-location-pulse { + position: absolute; + top: 50%; left: 50%; + transform: translate(-50%, -50%); + width: 30px; height: 30px; + background: rgba(255, 102, 0, 0.25); + border-radius: 50%; + animation: location-pulse 1.5s ease-out infinite; +} + +@keyframes location-pulse { + 0% { transform: translate(-50%, -50%) scale(0.5); opacity: 1; } + 100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; } +} diff --git a/tasks/enduro-trails/prototype/static/app.js b/tasks/enduro-trails/prototype/static/app.js index 55a0490..24db73e 100644 --- a/tasks/enduro-trails/prototype/static/app.js +++ b/tasks/enduro-trails/prototype/static/app.js @@ -1,3 +1,62 @@ +// ─── Компас ─────────────────────────────────────────────────────────────────── +let compassLocked = false; + +function toggleCompass() { + const map = window._map; + if (!map) return; + const btn = document.getElementById('btn-compass'); + compassLocked = !compassLocked; + if (compassLocked) { + map.rotateTo(0, { duration: 300 }); + map.dragRotate.disable(); + map.touchZoomRotate.disableRotation(); + btn.textContent = '⬆️'; + btn.title = 'Север вверху (нажми для свободного вращения)'; + btn.classList.add('active'); + } else { + map.dragRotate.enable(); + map.touchZoomRotate.enableRotation(); + btn.textContent = '🧭'; + btn.title = 'Свободное вращение'; + btn.classList.remove('active'); + } +} + +// ─── Геолокация ─────────────────────────────────────────────────────────────── +let locationMarker = null; + +function locateMe() { + if (!navigator.geolocation) { + alert('Геолокация недоступна в этом браузере'); + return; + } + const btn = document.getElementById('btn-locate'); + btn.textContent = '⏳'; + navigator.geolocation.getCurrentPosition( + (pos) => { + const { longitude, latitude } = pos.coords; + const map = window._map; + btn.textContent = '📍'; + map.flyTo({ center: [longitude, latitude], zoom: 13, duration: 800 }); + if (locationMarker) { + locationMarker.setLngLat([longitude, latitude]); + } else { + const el = document.createElement('div'); + el.className = 'my-location-marker'; + el.innerHTML = '
'; + locationMarker = new maplibregl.Marker({ element: el, anchor: 'center' }) + .setLngLat([longitude, latitude]) + .addTo(map); + } + }, + (err) => { + btn.textContent = '📍'; + alert('Не удалось определить местоположение: ' + err.message); + }, + { enableHighAccuracy: true, timeout: 10000 } + ); +} + // ─── Layer visibility state ─────────────────────────────────────────────────── const layerState = { tracks: true, diff --git a/tasks/enduro-trails/prototype/static/index.html b/tasks/enduro-trails/prototype/static/index.html index 70f0031..cf4a840 100644 --- a/tasks/enduro-trails/prototype/static/index.html +++ b/tasks/enduro-trails/prototype/static/index.html @@ -93,6 +93,11 @@
Zoom: 7 | Координаты:
+ +
+ + +