Skip to content

Map: show the basemap's scale bar and compass, and carry them into exports - #612

Open
BhattaraiSijan wants to merge 5 commits into
developmentfrom
feat/scale-bar
Open

BhattaraiSijan wants to merge 5 commits into
developmentfrom
feat/scale-bar

Conversation

@BhattaraiSijan

@BhattaraiSijan BhattaraiSijan commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #570. Closes #576. Supersedes #574 and #578.

Summary

A mission's basemap can now show the map library's own scale bar and compass, and exports carry them.

  • One config key. msv.basemap.controls holds scaleBar { show, units, position } and compass { show, position }. show is the switch; a mission without the key shows nothing, so existing missions are unchanged.
  • On screen, deck.gl. With a MapLibre or Mapbox basemap, the adapter adds the library's ScaleControl (100 px, metric or imperial) and a compass-only NavigationControl that turns with the bearing, tips with the pitch and resets the view to north on click. Each side-by-side comparison pane gets its own. Controls live on the map object, so basemap style switches keep them. Standalone deck.gl (no basemap provider) draws none.
  • On screen, Leaflet. The same key adds L.control.scale. Leaflet cannot rotate, so no compass.
  • Exports. The deck.gl capture reads the library's bar as drawn, its label and its length rescaled to image pixels, and reports the camera bearing. The share export paints that bar at the map's bottom-left and a north arrow beside it, then appends the legend band as before. Screen and image always read the same distance, including on high-DPI displays. The bar is left out when the map is tilted past 10°, since a perspective view has no single scale; the arrow stays. Leaflet's capture rasterizes the map DOM, so its bar is in the image already. Exports with the legend switched off still carry both.
  • Configure. The User Interface tab's Basemap section gains Show Scale Bar, Scale Bar Position, Scale Bar Units, Show Compass and Compass Position.

Why not compute the scale ourselves

MapLibre's and Mapbox's scale controls already do the one thing a scale bar needs: unproject two points on the centre row and measure the distance between them. #574 reimplemented that through the engine interface to support a plugin placed in any float panel and the scale under the pointer. A scale bar is map chrome, so this takes the library's control instead, which removes the plugin, the map:getMetersPerPixel and map:mouseout bus additions, and the per-frame move emission. What stays from #574 is the canvas renderer for the exported bar and the tilt rule.

Not in this PR

  • Lifting the float panels clear of the map corners. A float-top-right panel can cover a top-right control; the position dropdowns are the workaround.
  • Hiding the on-screen bar past 10° of tilt, to match the export.
  • A scale bar on standalone deck.gl, which has no basemap to host one.
  • Exports while comparison mode is on, which are broken independently of this change.

Test plan

  • npx vitest run tests/unit: 161 files, 2916 tests pass
  • Air4US with both controls on: bar at bottom-left updating with zoom, compass at its corner turning with right-drag and resetting on click
  • Side-by-side comparison: each pane carries both
  • Switch basemap style: controls stay
  • Export PNG and PDF: bar reads the same distance as on screen, north arrow beside it; rotate the map and export again, the arrow follows
  • Tilt past 10° and export: arrow only
  • Legend toggle off: exports still carry bar and arrow
  • Configure: tick and untick the boxes, change corners and units, save, reload

🤖 Generated with Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant