Map Overlays
Load GeoJSON, GPX, and georeferenced images as interactive map layers.
7 min readOverlays extend the map with external spatial data — mission area boundaries from a planning tool, route files from a GPS device, aerial imagery captured by a drone, or any other georeferenced content. Each overlay is an independent layer with its own style settings, and all overlay state is synchronized across connected clients in real time.
Vector Overlays
Any GeoJSON or GPX file that has been uploaded to the File Sharing system can be activated as a vector map overlay. The overlay records a reference to the source file rather than copying the geometry — updating the file and refreshing the overlay will reflect the new content.
{ "file_id": "uuid", "name": "Mission Boundary", "overlay_type": "vector" }
GPX Conversion
GPX files are converted to GeoJSON server-side when the overlay is activated. Track
segments become LineString features, waypoints become Point
features, and routes become LineString features. The converted GeoJSON is
what the client receives — the original GPX is retained in file storage as the source
of truth.
Rendering
Vector overlays are rendered using a MapLibre GeoJSON source. The server parses the geometry and computes a bounding box stored in the overlay record. On the client, each vector overlay gets up to five rendering layers depending on the geometry types present in the data:
- Fill layer — for
PolygonandMultiPolygonfeatures - Fill-outline layer — strokes the polygon boundary at a fixed 1px width
- Line layer — for
LineStringandMultiLineStringfeatures - Circle layer — for
PointandMultiPointfeatures - Label layer — text symbol from the feature's
nameproperty if present
Image Overlays
Raster images — photographs, drone captures, scanned maps — can be placed directly on the map as georeferenced image overlays. The image is stretched to fit four corner coordinates that the operator specifies during placement.
overlay_type to "image" and supply the four corner coordinates.{ "file_id": "uuid", "name": "Drone Survey", "overlay_type": "image", "corners": [[minLon,maxLat],[maxLon,maxLat],[maxLon,minLat],[minLon,minLat]] }
Click-to-Place Workflow
The placement UI walks the operator through a two-step click workflow on the map:
- Click the first corner. The cursor becomes a crosshair. Click the map at the top-left corner of the image's intended position.
- Click the opposite corner. Click at the bottom-right corner. The server computes the other two corners from these two points and creates a rectangular placement that can be adjusted afterward.
A preview of the placed image appears immediately using the provisional coordinates before the final request is submitted.
Manual Coordinate Entry
For precise placement, the panel offers a manual coordinate entry form where all four corner coordinates can be entered as decimal degrees. This is suitable when the exact bounds of the coverage area are known from metadata — for example, from a drone flight plan export or GeoTIFF world file.
MapLibre Rendering
Image overlays are rendered using MapLibre's native image source type.
The image binary is fetched from the file download endpoint using an authenticated
request, converted to a blob URL, and passed to the source. This ensures the image
data never leaves the local network unprotected even when fetched by the browser.
The layer type is raster, which supports hardware-accelerated rendering
and opacity control.
3D terrain and hillshade are automatically disabled when one or more image overlays
are active. MapLibre does not support mixing raster layers with the
terrain elevation model. Terrain resumes automatically when all image overlays are
hidden or removed.
Style Controls
Each overlay has independent style properties that persist in the database and are shared with all clients. Changes take effect immediately on all connected clients without a page reload.
name, color, opacity, line_width, corners (image overlays)
| Property | Type | Applies To | Default |
|---|---|---|---|
color |
CSS hex string | Vector overlays | #3B82F6 |
opacity |
0.0 – 1.0 | Both types | 0.7 |
line_width |
Pixels (integer) | Vector overlays | 2 |
Style updates are persisted to the overlays table and broadcast via the
overlay:updated Socket.IO event. Clients reapply the updated paint
properties to the relevant MapLibre layers without re-fetching the geometry.
Interaction
Feature Info Popups
Clicking on any visible vector overlay feature opens a popup anchored to the click
location. The popup displays all GeoJSON properties attached to the clicked feature
in a key-value table. Properties with null values or internal
MapLibre layer identifiers are excluded from the display.
Zoom to Extent
Each overlay entry in the management panel has a zoom-to-extent button. Clicking it
calls MapLibre's fitBounds using the overlay's stored bbox
with a small padding applied. This is useful for immediately locating an overlay
that falls outside the current map view.
Local Visibility Toggle
Each overlay can be toggled visible or hidden using the eye icon in the panel. This
is a client-side preference stored in component state — it does not modify the overlay
record on the server and does not affect other users. Toggling visibility calls
MapLibre's setLayoutProperty with visibility: 'visible'
or 'none' rather than adding or removing the layer, which is
instantaneous.
Local visibility is reset on page reload. To permanently remove an overlay from
everyone's map, delete it via DELETE /api/overlays/:id. The underlying
file in file storage is not deleted — only the overlay record and its layers.
Real-Time Sync
All overlay CRUD operations emit Socket.IO events to every connected client. This ensures that when one operator creates or modifies an overlay, all other clients immediately add or update the corresponding map layers.
| Event | Direction | Payload |
|---|---|---|
overlay:created |
Server → all clients | Full overlay record including bbox, overlay_type, and style properties |
overlay:updated |
Server → all clients | Full updated overlay record |
overlay:removed |
Server → all clients | { id } — the removed overlay's identifier |
Receiving clients respond to overlay:created by fetching the geometry
from the file content endpoint and adding the new source and layers to the map.
overlay:updated triggers a paint property update. overlay:removed
removes all associated layers and the source from the map.