6.5 KiB
Project Hints - dees-catalog-geo
Overview
Geospatial web components library using MapLibre GL JS for map rendering and terra-draw for drawing capabilities.
Key Dependencies
- maplibre-gl (v5.x): WebGL-based vector map library
- terra-draw (v1.24.0): Modern drawing library with support for multiple map libraries
- terra-draw-maplibre-gl-adapter (v1.x): Adapter connecting terra-draw with MapLibre
Component: dees-geo-map
Properties
| Property | Type | Default | Description |
|---|---|---|---|
center |
[number, number] |
[0, 0] |
Map center as [lng, lat] |
zoom |
number |
2 |
Initial zoom level |
mapStyle |
string |
'osm' |
Map style ('osm' or custom URL) |
activeTool |
TDrawTool |
'static' |
Active drawing tool |
geoJson |
GeoJSON.FeatureCollection |
{...} |
Initial features |
showToolbar |
boolean |
true |
Show/hide drawing toolbar |
projection |
'mercator' | 'globe' |
'mercator' |
Map projection type |
showSearch |
boolean |
false |
Show address search input |
showNavigation |
boolean |
false |
Show A-to-B navigation panel |
navigationMode |
'driving' | 'walking' | 'cycling' |
'driving' |
Transport mode for routing |
Drawing Tools (TDrawTool)
point- Draw pointslinestring- Draw linespolygon- Draw polygonsrectangle- Draw rectanglescircle- Draw circlesfreehand- Freehand drawingselect- Select and edit featuresstatic- Pan/zoom only (no drawing)
Events
map-ready- Fired when map is initializedmap-move- Fired on pan/zoom with center and zoomdraw-change- Fired on any feature changedraw-finish- Fired when a shape is completedaddress-selected- Fired when a search result is selectedroute-calculated- Fired when a navigation route is calculated (includes route, startPoint, endPoint, mode)
Public Methods
getFeatures()- Get all drawn featuresgetGeoJson()- Get features as FeatureCollectionloadGeoJson(geojson)- Load features from GeoJSONclearAllFeatures()- Remove all featuressetTool(tool)- Set active drawing toolflyTo(center, zoom?)- Animate to locationfitToFeatures(padding?)- Fit view to all featuressetProjection(projection)- Set map projection ('mercator' or 'globe')getMap()- Get underlying MapLibre instancegetTerraDraw()- Get TerraDraw instancecalculateRoute()- Calculate route between start and end pointssetNavigationStart(coords, address?)- Set navigation start pointsetNavigationEnd(coords, address?)- Set navigation end pointclearNavigation()- Clear all navigation state
Context Menu
Right-click on the map to access a context menu with the following options:
- Drag to Draw - Toggle between drag mode (click-drag for circles/rectangles) and two-click mode
- Globe View - Toggle between globe (3D sphere) and Mercator (flat) projection
- Clear All Features - Remove all drawn features from the map
- Fit to Features - Zoom and pan to show all drawn features
Navigation Feature
The navigation panel (showNavigation={true}) provides A-to-B routing using OSRM (Open Source Routing Machine):
- Transport modes: Driving, Walking, Cycling
- Point selection: Type an address or click on the map
- Route display: Blue line overlay with turn-by-turn directions
- API: Uses free OSRM API (https://router.project-osrm.org) with fair-use rate limit
Development
pnpm install- Install dependenciespnpm watch- Start development server (port 3002)pnpm build- Build for production
File Structure
ts_web/
├── index.ts # Main exports
├── 00_commitinfo_data.ts # Auto-generated
└── elements/
├── index.ts # Elements barrel
├── 00colors.ts # Color definitions
├── 00componentstyles.ts # Shared styles
└── 00group-map/
├── index.ts
└── dees-geo-map/
├── index.ts # Exports main + modules
├── dees-geo-map.ts # Main component (~550 lines)
├── dees-geo-map.demo.ts # Demo function
├── geo-map.icons.ts # Icon SVG definitions (~60 lines)
├── geo-map.search.ts # SearchController class (~180 lines)
└── geo-map.navigation.ts # NavigationController class (~530 lines)
Modular Architecture
The component was refactored for better maintainability:
geo-map.icons.ts
Contains all SVG icon definitions as a GEO_MAP_ICONS record and a renderIcon(name) helper function.
geo-map.search.ts
SearchController class encapsulating Nominatim geocoding search:
- Reusable for standalone search or within navigation
- Debounced API calls
- Keyboard navigation support
- Customizable via
ISearchControllerConfig
geo-map.navigation.ts
NavigationController class for A-to-B routing:
- OSRM routing API integration
- Start/end point management with markers
- Map click mode for point selection
- Turn-by-turn directions rendering
- Route overlay on map
Usage of Controllers
// SearchController is reusable
const search = new SearchController(
{ placeholder: 'Search...' },
{
onResultSelected: (result, coords, zoom) => { /* handle */ },
onRequestUpdate: () => this.requestUpdate(),
}
);
// NavigationController manages all navigation state
const nav = new NavigationController({
onRouteCalculated: (event) => { /* dispatch */ },
onRequestUpdate: () => this.requestUpdate(),
getMap: () => this.map,
});
Notes
- MapLibre CSS is loaded dynamically from CDN
- Terra-draw requires the separate maplibre-gl-adapter package
- The component uses Shadow DOM for style encapsulation
Shadow DOM & Terra-Draw Drawing Fix
Terra-draw's event listeners normally intercept map events through MapLibre's canvas element. In Shadow DOM contexts, these events are scoped locally and don't propagate correctly, causing terra-draw handlers to fail while MapLibre's drag handlers continue working.
Solution: Manual drag coordination in setTool():
- When a drawing tool is active (
polygon,rectangle,point,linestring,circle,freehand), MapLibre'sdragPananddragRotateare disabled - When
staticorselectmode is active, dragging is re-enabled - The
TerraDrawMapLibreGLAdapterdoes NOT accept alibparameter - onlymapis required