Architecture
Architecture
Layers, components, data flow, and rendering — so you can build advanced features on solid ground.
System layers
vjmapext uses a classic stack: application, core, and foundation.
Design
MapCadLayer is the hub: it does not embed business rules. Subsystems communicate via EventBus; coordinates go through CoordMapper.
Component relationships
Data flow
From entity creation to pixels on the map:
Three-source bucketing
| Source | ID | Use | Update rate |
|---|---|---|---|
| Hot | mapcad-hot | Selected / highlighted + grips + preview | High (per frame while interacting) |
| Cold | mapcad-cold | Static entities | Low (on data change) |
| Dynamic | mapcad-dynamic | dynamic: true entities | Medium (animation frames) |
Performance
Static geometry stays in Cold so interaction does not reserialize everything. RenderCache caches GeoJSON per entity; style-only changes can patch properties in place.
Command execution
CommandContext
Each command receives a CommandContext with store, inputManager, eventBus, coordMapper, renderPipeline, previewManager, gripManager, drawingDefaults, undoManager, blocks, map, dimReactorManager, etc.
Events
| Category | Event | When |
|---|---|---|
| Entity | entity:added / deleted / modified | Store changes |
| Entity | entity:mouseenter / mouseleave / click / dblclick | Pointer |
| Selection | selection:changed | Selection set changes |
| Command | command:started / ended | Command lifecycle |
| Mode | mode:changed | Edit / browse |
| Render | render:requested | Render refresh |
| Store | store:changed | Store data |
| Input | input:started / ended | User input |
| Box select | boxselect:started / ended | Marquee |
mapcadLayer.eventBus.on('entity:added', (e) => {
console.log('Added:', e.entity.id, e.entity.type);
});
mapcadLayer.eventBus.on('selection:changed', (e) => {
console.log('Selection:', e.selectedIds);
});
mapcadLayer.eventBus.on('mode:changed', (e) => {
console.log('Mode:', e.mode);
});Render pipeline
Incremental vs full rebuild:
Full rebuild: first render, forceFullRender(), projection rebind, display-level filter changes in browse mode.
Incremental: add/delete/modify — style patch vs geometry replace; _entityIndex tracks bucket positions.
Warning
Normally render() follows dirty flags. Call renderPipeline.forceFullRender() only if geometry was mutated outside normal paths.
Coordinates
CoordMapper.bindMap() runs in onAdd(); entities use CAD space; GeoJSON gets lng/lat via projection.
Next steps
- Coordinates — projection details
- MapCadLayer — API reference
- Entity basics
- Commands & input