Swap the pin marker for a rounded-square badge
The National Park Service frames its own map symbols (the icons already vendored in for POI categories) in a rounded square, not a pin — pairing a pin shape with NPS-style pictograms looked like two mismatched icon conventions. Switched the marker to a rounded square to match. This also simplifies the placement code: a pin has to anchor at its tip, so the category glyph on top needed an offset computed from the pin/glyph geometry to land in the pin's head. A square has no tip — both the badge and the glyph layer just center directly on the coordinate with no offset math at all.
This commit is contained in:
1 parent
2a83bb10ca
commit
7de8428b05
3 files changed
+50
-64
No files matched your search
+17
-33
@@ -6,7 +6,7 @@ import {
|
||||
WAYPOINT_ICON,
|
||||
TRACK_ICON,
|
||||
ROUTE_ICON,
|
||||
MAP_PIN_ICON,
|
||||
MAP_MARKER_ICON,
|
||||
POI_ICONS,
|
||||
} from "/js/icons.js";
|
||||
import { notifySidePanelOpen, onlyOneSidePanelOpen } from "/js/panels.js";
|
||||
@@ -19,24 +19,9 @@ const MOVE_URL = "/api/gpx/move";
|
||||
const TRACK_COLOR = "#e63946";
|
||||
const POI_ICON_KEYS = Object.keys(POI_ICONS);
|
||||
const POI_ICON_IMAGE_SIZE = 48; // rasterized once at this size, rendered much smaller by icon-size below
|
||||
const POI_ICON_SIZE = 0.3; // 48 * 0.3 = ~14px, matching the pin head's diameter below
|
||||
|
||||
// The pin glyph (icons.js's MAP_PIN_ICON) is a 24x24 viewBox with its head
|
||||
// circle centered at y=9, rasterized onto the same POI_ICON_IMAGE_SIZE
|
||||
// canvas as every other icon. icon-anchor: "bottom" anchors both this layer
|
||||
// and the category-glyph layer below to the *raster canvas's* bottom edge
|
||||
// (not the pin's visual tip, which sits a little above that edge) — so both
|
||||
// layers share one screen anchor point, and placing the glyph in the pin's
|
||||
// head is just "how far above that shared anchor is each icon's own visual
|
||||
// center, and what's the gap between them":
|
||||
const MAP_PIN_ID = "map-pin";
|
||||
const MAP_PIN_SIZE = 0.55;
|
||||
const MAP_PIN_HEAD_CENTER_SVG_Y = 9;
|
||||
const MAP_PIN_VIEWBOX = 24;
|
||||
const pinHeadCenterAboveAnchorPx =
|
||||
(MAP_PIN_VIEWBOX - MAP_PIN_HEAD_CENTER_SVG_Y) * (POI_ICON_IMAGE_SIZE / MAP_PIN_VIEWBOX) * MAP_PIN_SIZE;
|
||||
const glyphOwnCenterAboveAnchorPx = (POI_ICON_IMAGE_SIZE * POI_ICON_SIZE) / 2; // glyph content roughly fills its own canvas
|
||||
const POI_ICON_OFFSET_Y = -((pinHeadCenterAboveAnchorPx - glyphOwnCenterAboveAnchorPx) / POI_ICON_SIZE);
|
||||
const POI_ICON_SIZE = 0.3; // 48 * 0.3 = ~14px, sized to sit inside the marker badge below
|
||||
const MAP_MARKER_ID = "map-marker";
|
||||
const MAP_MARKER_SIZE = 0.55;
|
||||
|
||||
// Custom drag payload MIME type for moving an already-uploaded file between
|
||||
// folders, as opposed to an OS file drag (type "Files") for uploading a new
|
||||
@@ -71,7 +56,7 @@ export class GpxPanelControl {
|
||||
// color information worth preserving, and SDF lets the same sprite be
|
||||
// reused if a future category needs a different tint.
|
||||
async _registerPoiIcons() {
|
||||
const sources = { ...POI_ICONS, [MAP_PIN_ID]: MAP_PIN_ICON };
|
||||
const sources = { ...POI_ICONS, [MAP_MARKER_ID]: MAP_MARKER_ICON };
|
||||
await Promise.all(
|
||||
Object.keys(sources).map(async (key) => {
|
||||
if (this._map.hasImage(key)) return;
|
||||
@@ -424,20 +409,23 @@ export class GpxPanelControl {
|
||||
layout: { "text-field": ["get", "point_count_abbreviated"], "text-font": ["Noto Sans Regular"], "text-size": 11 },
|
||||
paint: { "text-color": "#fff" },
|
||||
});
|
||||
// A pin (icons.js's MAP_PIN_ICON), not a plain circle: a flat colored
|
||||
// dot looks too much like a base map style's own small circular POI
|
||||
// icons, so individual waypoints blended in and were hard to spot as
|
||||
// "your data" versus the map's own points. Anchored at its tip (the
|
||||
// standard map-pin convention), not centered on the coordinate.
|
||||
// A rounded-square badge (icons.js's MAP_MARKER_ICON), not a plain
|
||||
// circle: a flat colored dot looked too much like a base map style's
|
||||
// own small circular POI icons, so individual waypoints blended in
|
||||
// instead of standing out as "your data". A rounded square rather than
|
||||
// a pin/teardrop specifically to match how the NPS itself frames these
|
||||
// exact category symbols (POI_ICONS below) on its own maps. Centered on
|
||||
// the coordinate — a square has no natural "tip" the way a pin does, so
|
||||
// default center anchoring is simplest and also means the glyph layer
|
||||
// below needs no offset, just the same center anchor.
|
||||
this._map.addLayer({
|
||||
id: `${pointsId}-unclustered`,
|
||||
type: "symbol",
|
||||
source: pointsId,
|
||||
filter: ["!", ["has", "point_count"]],
|
||||
layout: {
|
||||
"icon-image": MAP_PIN_ID,
|
||||
"icon-size": MAP_PIN_SIZE,
|
||||
"icon-anchor": "bottom",
|
||||
"icon-image": MAP_MARKER_ID,
|
||||
"icon-size": MAP_MARKER_SIZE,
|
||||
"icon-allow-overlap": true,
|
||||
"icon-ignore-placement": true,
|
||||
},
|
||||
@@ -445,9 +433,7 @@ export class GpxPanelControl {
|
||||
});
|
||||
// Only for the curated POI_ICON_KEYS (see icons.js) — anything else
|
||||
// (a plain hand-placed waypoint, or a category p4n2gpx/OsmAnd hasn't
|
||||
// been taught here) just keeps the plain pin above with no glyph.
|
||||
// icon-offset moves it up from the anchor (the pin's tip) into the
|
||||
// pin's round head — see POI_ICON_OFFSET_Y's comment above.
|
||||
// been taught here) just keeps the plain badge above with no glyph.
|
||||
this._map.addLayer({
|
||||
id: `${pointsId}-unclustered-icon`,
|
||||
type: "symbol",
|
||||
@@ -456,8 +442,6 @@ export class GpxPanelControl {
|
||||
layout: {
|
||||
"icon-image": ["get", "icon"],
|
||||
"icon-size": POI_ICON_SIZE,
|
||||
"icon-anchor": "bottom",
|
||||
"icon-offset": [0, POI_ICON_OFFSET_Y],
|
||||
"icon-allow-overlap": true,
|
||||
"icon-ignore-placement": true,
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user