Turn POI markers into pins and use a real icon set
CI / check (push) Successful in 42s
CI / deploy (push) Successful in 16s

Colored circles for waypoints looked too similar to a base map style's own
small circular POI icons, so uploaded POI data blended into the map instead
of standing out. Switched the marker shape to a pin/teardrop (reusing the
existing WAYPOINT_ICON path, filled instead of stroked) — no base map style
uses that shape for its own points, so it reads immediately as "your data".
Anchored at its tip, the standard map-pin convention, rather than centered
on the coordinate.

Also swapped the hand-drawn category glyphs for the National Park Service's
own map symbols (github.com/nationalparkservice/symbol-library, BSD
licensed, forked from Mapbox's Maki) for the six categories it covers —
professional, purpose-built pictograms beat ad-hoc "fuel pump"/"picnic
table" line art. `forest` has no NPS equivalent and stays hand-drawn.

The glyph now sits in the pin's head rather than centered on a flat dot,
which needed real geometry (both layers anchor to the same point, so the
offset is the gap between where the pin's head-center ends up and where the
glyph's own visual center already sits) rather than the old anchor="center"
zero-offset placement.
This commit is contained in:
randy committed 2026-09-07 16:37:31 +02:00
1 parent 0b18dc018a
commit 2a83bb10ca
3 files changed
+143 -50

No files matched your search

+34 -15
View File
@@ -218,21 +218,40 @@ into `category`/`color` properties (an OsmAnd export can carry a
the same local element name "icon" once REXML drops namespace
prefixes, so this specifically matches on namespace *URI*
(`https://osmand.net`), not local name, to avoid picking whichever
happens to come last in the file). The unclustered-points map layer
colors each dot via `["coalesce", ["get", "color"], TRACK_COLOR]`
(falling back to the plain track color for a waypoint with no
category, e.g. a hand-placed GNSS pin), and a small curated icon set
(`public/js/icons.js`'s `POI_ICONS`, ~7 hand-drawn glyphs covering the
categories p4n2gpx actually uses, not an exhaustive OsmAnd icon set) is
rasterized once per style load (`_registerPoiIcons`, an SVG →
`<img>` → `<canvas>` → `ImageData` round trip, since these need to be
real raster images for `map.addImage`) and registered as SDF images —
a single alpha shape MapLibre tints at render time via `icon-color`
rather than a fixed-color image — so a symbol layer can draw a white
glyph on top of each dot for any waypoint whose `icon` matches a known
key (filtered out entirely for anything else, so an unrecognized icon
key just falls back to a plain colored dot rather than a broken/missing
image warning). The points source itself is created with
happens to come last in the file). Individual waypoints render as a
pin (`public/js/icons.js`'s `MAP_PIN_ICON`, the same path as the
existing `WAYPOINT_ICON` outline, filled instead of stroked) rather
than a plain circle — a flat colored dot turned out to look too much
like a base map style's own small circular POI icons, blending in
instead of reading as "your data"; a pin is a shape convention no base
map uses for its own points. It's colored via
`["coalesce", ["get", "color"], TRACK_COLOR]` (falling back to the
plain track color for a waypoint with no category, e.g. a hand-placed
GNSS pin) and anchored at its tip (`icon-anchor: "bottom"`, the
standard map-pin convention — the tip, not the shape's center, lands on
the actual coordinate). A small curated icon set
(`public/js/icons.js`'s `POI_ICONS`, covering the categories p4n2gpx
actually uses, not an exhaustive OsmAnd icon set) draws a white glyph
on top of the pin's head, in a symbol layer offset up from the shared
tip anchor by a size computed from the pin and glyph geometry
(`POI_ICON_OFFSET_Y` — both layers anchor to the same raster canvas
edge, so the offset is "how far above that shared anchor is the pin's
head-center, minus how far above it the glyph's own visual center
already sits at its own icon-size"), filtered to just the known keys
(anything else keeps the plain pin with no glyph, rather than a
broken/missing image warning). Six of the seven glyphs are the
National Park Service's own map symbols
(`github.com/nationalparkservice/symbol-library`, BSD-licensed,
originally forked from Mapbox's Maki project) — a professional,
purpose-built icon set beats hand-drawing "fuel pump"/"picnic table"
glyphs from scratch; `forest` has no NPS equivalent (that set covers
facilities, not land cover) and stays hand-drawn. Both the pin and the
category glyphs are rasterized once per style load (`_registerPoiIcons`,
an SVG → `<img>` → `<canvas>` → `ImageData` round trip, since these
need to be real raster images for `map.addImage`) and registered as SDF
images — a single alpha shape MapLibre tints at render time via
`icon-color` rather than a fixed-color image. The points source itself
is created with
`cluster: true`; nearby points collapse into a stepped-radius,
sequential-blue circle sized by `point_count` below `clusterMaxZoom`,
clicking one zooms to its `getClusterExpansionZoom()`, and this is