explore: default heatmap/by-type; month All button; bbox filtering on map move

This commit is contained in:
Davide Scaini
2026-05-14 14:45:54 +02:00
parent 537d1bb712
commit 6d13993f98
+38 -6
View File
@@ -22,10 +22,11 @@
let dateFrom = ''; let dateFrom = '';
let dateTo = ''; let dateTo = '';
let selectedYear: string | null = null; let selectedYear: string | null = null;
let selectedMonth: number | null = null;
// View // View
let viewMode: 'lines' | 'heatmap' = 'lines'; let viewMode: 'lines' | 'heatmap' = 'heatmap';
let heatmapMode: 'global' | 'bytype' = 'global'; let heatmapMode: 'global' | 'bytype' = 'bytype';
// Tile layers — same as planner // Tile layers — same as planner
const TILES: Record<string, { tiles: string[]; attribution: string; label: string }> = { const TILES: Record<string, { tiles: string[]; attribution: string; label: string }> = {
@@ -83,26 +84,49 @@
function clearAllTypes() { selectedTypes = new Set(); } function clearAllTypes() { selectedTypes = new Set(); }
function setYear(y: string) { function setYear(y: string) {
if (selectedYear === y) { selectedYear = null; dateFrom = ''; dateTo = ''; return; } if (selectedYear === y) { selectedYear = null; selectedMonth = null; dateFrom = ''; dateTo = ''; return; }
selectedYear = y; selectedYear = y;
selectedMonth = null;
dateFrom = `${y}-01-01`; dateFrom = `${y}-01-01`;
dateTo = `${y}-12-31`; dateTo = `${y}-12-31`;
} }
function setMonth(m: number) { // m: 1-12 function setMonth(m: number) { // m: 1-12
if (!selectedYear) return; if (!selectedYear) return;
selectedMonth = m;
const mm = String(m).padStart(2, '0'); const mm = String(m).padStart(2, '0');
const last = new Date(+selectedYear, m, 0).getDate(); const last = new Date(+selectedYear, m, 0).getDate();
dateFrom = `${selectedYear}-${mm}-01`; dateFrom = `${selectedYear}-${mm}-01`;
dateTo = `${selectedYear}-${mm}-${String(last).padStart(2,'0')}`; dateTo = `${selectedYear}-${mm}-${String(last).padStart(2,'0')}`;
} }
function clearDates() { dateFrom = ''; dateTo = ''; selectedYear = null; } function clearMonth() {
if (!selectedYear) return;
selectedMonth = null;
dateFrom = `${selectedYear}-01-01`;
dateTo = `${selectedYear}-12-31`;
}
function clearDates() { dateFrom = ''; dateTo = ''; selectedYear = null; selectedMonth = null; }
// ── Map ──────────────────────────────────────────────────────────────────── // ── Map ────────────────────────────────────────────────────────────────────
let _bbox: { w: number; e: number; s: number; n: number } | null = null;
function _getBbox() {
if (!map) return null;
const b = map.getBounds();
return { w: b.getWest(), e: b.getEast(), s: b.getSouth(), n: b.getNorth() };
}
function _inBbox(lng: number, lat: number): boolean {
if (!_bbox) return true;
return lng >= _bbox.w && lng <= _bbox.e && lat >= _bbox.s && lat <= _bbox.n;
}
function _linesGeoJSON(ts: Track[]) { function _linesGeoJSON(ts: Track[]) {
return { type: 'FeatureCollection', features: ts.map(t => ({ const visible = _bbox ? ts.filter(t => t.coords.some(([lng, lat]) => _inBbox(lng, lat))) : ts;
return { type: 'FeatureCollection', features: visible.map(t => ({
type: 'Feature', type: 'Feature',
geometry: { type: 'LineString', coordinates: t.coords }, geometry: { type: 'LineString', coordinates: t.coords },
properties: { type: t.type }, properties: { type: t.type },
@@ -113,6 +137,7 @@
const features: any[] = []; const features: any[] = [];
for (const t of ts) for (const t of ts)
for (const [lng, lat] of t.coords) for (const [lng, lat] of t.coords)
if (_inBbox(lng, lat))
features.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [lng, lat] }, properties: { type: t.type } }); features.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [lng, lat] }, properties: { type: t.type } });
return { type: 'FeatureCollection', features }; return { type: 'FeatureCollection', features };
} }
@@ -203,9 +228,15 @@
} }
mapReady = true; mapReady = true;
_bbox = _getBbox();
_updateMap(tracks, viewMode, heatmapMode); _updateMap(tracks, viewMode, heatmapMode);
_fitBounds(tracks); _fitBounds(tracks);
}); });
map.on('moveend', () => {
_bbox = _getBbox();
if (mapReady) _updateMap(filteredTracks, viewMode, heatmapMode);
});
}); });
onDestroy(() => { if (map) map.remove(); }); onDestroy(() => { if (map) map.remove(); });
@@ -261,9 +292,10 @@
</div> </div>
{#if selectedYear} {#if selectedYear}
<div class="pills month-pills"> <div class="pills month-pills">
<button class="pill small" class:active={selectedMonth === null} onclick={clearMonth}>All</button>
{#each MONTHS as m, i} {#each MONTHS as m, i}
<button class="pill small" <button class="pill small"
class:active={dateFrom === `${selectedYear}-${String(i+1).padStart(2,'0')}-01`} class:active={selectedMonth === i + 1}
onclick={() => setMonth(i + 1)}>{m}</button> onclick={() => setMonth(i + 1)}>{m}</button>
{/each} {/each}
</div> </div>