Color-code, cluster and add icons to POI waypoints
CI / check (push) Successful in 47s
CI / deploy (push) Successful in 16s

A park4night/OsmAnd POI export (e.g. a p4n2gpx area export) tags every
waypoint with a category and a per-category color/icon in its <extensions>
block, all of which was previously thrown away — every waypoint rendered as
the same plain red dot, unreadable once a file has a few thousand of them.

Maptool::Gpx now captures category/color/icon (waypoint_style), matched by
namespace URI rather than local element name: a p4n2gpx file carries both
<osmand:icon> and <locus:icon> side by side, and REXML strips prefixes from
Element#name, so both report as just "icon" — matching on that alone was
silently picking the (useless) Locus drawable path instead of the OsmAnd
category key. Regression test added for this.

On the map: waypoints are colored by category (falling back to the plain
track color for anything uncategorized), a small hand-drawn icon set
(public/js/icons.js's POI_ICONS, rasterized to SDF sprites at runtime) draws
a glyph on top for the categories it covers, the points source is clustered
so a dense export collapses into count bubbles instead of a solid blob, and
a legend in the side panel lists whichever categories are currently visible.

Splitting each file's GeoJSON into a lines source and a points source
(rather than one mixed source with a geometry-type filter per layer) was
needed for clustering, since MapLibre's cluster support only understands a
source made entirely of points.
This commit is contained in:
randy committed 2026-09-07 16:18:06 +02:00
1 parent 708c08259b
commit 0b18dc018a
8 files changed
+434 -35

No files matched your search

+33
View File
@@ -398,6 +398,32 @@ html, body {
outline-offset: -2px;
}
.gpx-legend {
flex-shrink: 0;
max-height: 140px;
overflow-y: auto;
padding: 8px 12px;
border-top: 1px solid #eee;
}
.gpx-legend[hidden] {
display: none;
}
.gpx-legend__item {
display: flex;
align-items: center;
gap: 6px;
padding: 2px 0;
}
.gpx-legend__swatch {
width: 10px;
height: 10px;
border-radius: 50%;
flex-shrink: 0;
}
#map.gpx-drop-hover::after {
content: "";
position: absolute;
@@ -417,6 +443,13 @@ html, body {
font-size: 12px;
}
.gpx-popup__category {
color: #888;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.02em;
}
.gnss-control__status {
color: #888;
white-space: nowrap;