CadMapOverlay Map Overlay
About 3 min
CadMapOverlay Map Overlay
CadMapOverlay is used to overlay a WebCAD view on top of a vjmap / Mapbox GL map, enabling integrated display of CAD drawings and maps. It supports view synchronization, entity selection, coordinate conversion, and more.
Features
- View synchronization: WebCAD view automatically follows map zoom, pan, and rotation
- Smooth animation: uses CSS transforms for smooth transitions and avoids jitter
- Entity selection: supports click-to-select and Shift+click additive selection
- Coordinate conversion: automatic conversion between CAD coordinates and longitude/latitude
- Event listening: selection change callback and map extent update listening
- Transparent background: WebCAD background is transparent and blends seamlessly with the map
Basic Usage
Create Map Overlay
import { CadMapOverlay, Engine, LineEnt, CircleEnt } from 'vjcad';
// Map extent (CAD coordinates)
const mapExtent = [0, 0, 1000, 1000];
// Create overlay
const cadOverlay = new CadMapOverlay({
bounds: mapExtent,
serviceUrl: 'http://127.0.0.1:27660/api/v1',
accessToken: 'your-token',
themeMode: 0, // 0 = dark, 1 = light
enableSelection: true,
onSelectionChanged: (selection) => {
console.log('Selected entities:', selection);
}
});
// Add to vjmap map
await cadOverlay.addTo(map);
// Add entities
const line = new LineEnt([100, 100], [500, 500]);
line.setDefaults();
line.color = 1;
const circle = new CircleEnt([300, 300], 100);
circle.setDefaults();
circle.color = 3;
cadOverlay.addEntities([line, circle]);
cadOverlay.zoomToExtents();Configuration Options
CadMapOverlayOptions
| Option | Type | Default | Description |
|---|---|---|---|
bounds | number[] | GeoBounds | Required | CAD bounds [minX, minY, maxX, maxY] |
serviceUrl | string | Required | WebCAD service URL |
accessToken | string | Required | Access token |
themeMode | number | 0 | Theme mode (0 = dark, 1 = light) |
minZoom | number | 0 | Minimum visible zoom level |
maxZoom | number | 100 | Maximum visible zoom level |
enableSelection | boolean | true | Whether entity selection is enabled |
smoothAnimation | boolean | true | Whether to use smooth animation mode |
onSelectionChanged | Function | - | Selection change callback |
Animation Modes
// Smooth animation mode (default)
// Uses CSS transforms during animation and redraws when animation ends
// Pros: smooth, no jitter
const overlay1 = new CadMapOverlay({
bounds: mapExtent,
smoothAnimation: true, // Default
// ...
});
// Real-time redraw mode
// Redraws the view on each movement
// Pros: more immediate response; cons: may jitter at high zoom levels
const overlay2 = new CadMapOverlay({
bounds: mapExtent,
smoothAnimation: false,
// ...
});API Methods
Map Operations
// Add to map
await cadOverlay.addTo(map);
await cadOverlay.addTo(map, 'container-id'); // Specify parent container
// Remove from map
cadOverlay.remove();
// Show / hide
cadOverlay.setVisible(true);
cadOverlay.setVisible(false);
// Redraw
cadOverlay.redraw();View Operations
// Zoom extents
cadOverlay.zoomToExtents();
// Update CAD bounds
cadOverlay.updateBounds([0, 0, 2000, 2000]);
// Get current bounds
const bounds = cadOverlay.getCadBounds();Entity Operations
// Add entities
cadOverlay.addEntities([line, circle, text]);
// Get MainView instance (access lower-level APIs)
const cadView = cadOverlay.getCadView();Selection Operations
// Get current selection
const selection = cadOverlay.getSelection();
// Set selection
cadOverlay.setSelection([entity1, entity2]);
// Clear selection
cadOverlay.clearSelection();Coordinate Conversion
// CAD coordinate to longitude/latitude
const lngLat = cadOverlay.cadToLngLat(500, 500);
// { lng: 116.xxx, lat: 39.xxx }
// Longitude/latitude to CAD coordinate
const cadPt = cadOverlay.lngLatToCad({ lng: 116.xxx, lat: 39.xxx });
// { x: 500, y: 500 }Event Handling
Selection Change Callback
const cadOverlay = new CadMapOverlay({
// ...
onSelectionChanged: (selection) => {
if (selection.length === 0) {
console.log('Selection cleared');
} else {
console.log(`Selected ${selection.length} entities:`);
selection.forEach((ent, i) => {
console.log(` [${i + 1}] ${ent.type}, ID: ${ent.id}`);
});
}
}
});Listen for Map Extent Updates
When map.updateMapExtent() is called, the overlay automatically updates the CAD bounds:
// vjmap updates extent
map.updateMapExtent([0, 0, 2000, 2000]);
// CadMapOverlay automatically listens for 'updateMapExtent' and updates itselfInteraction Operations
| Action | Effect |
|---|---|
| Mouse wheel | Zoom map and CAD view |
| Left-button drag | Pan map and CAD view |
| Left click | Select CAD entity |
| Shift+click | Add / remove entity from selection |
ESC | Clear selection |
| Right-button drag | Rotate map (if supported by the map) |
Complete Example
Integrate with vjmap
// Dynamically load vjmap
async function loadVjmap() {
// Load CSS
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://vjmap.com/demo/js/vjmap/vjmap.min.css';
document.head.appendChild(link);
// Load JS
return new Promise((resolve) => {
const script = document.createElement('script');
script.src = 'https://vjmap.com/demo/js/vjmap/vjmap.min.js';
script.onload = resolve;
document.head.appendChild(script);
});
}
await loadVjmap();
// Create map
const mapExtent = [0, 0, 1000, 1000];
const prj = new vjmap.GeoProjection(vjmap.GeoBounds.fromArray(mapExtent));
const map = new vjmap.Map({
container: 'map',
style: vjmap.openMapDarkStyle(),
center: prj.toLngLat(vjmap.GeoBounds.fromArray(mapExtent).center()),
zoom: 2,
pitch: 0,
pitchWithRotate: false,
maxPitch: 0,
renderWorldCopies: false,
});
map.setMapProjection(prj);
map.addControl(new vjmap.NavigationControl());
await new Promise(resolve => map.on('load', resolve));
// Create WebCAD overlay
const { CadMapOverlay, LineEnt, CircleEnt, TextEnt, Engine } = vjcad;
const cadOverlay = new CadMapOverlay({
bounds: mapExtent,
serviceUrl: env.serviceUrl,
accessToken: env.accessToken,
themeMode: 0,
enableSelection: true,
smoothAnimation: true,
onSelectionChanged: (selection) => {
console.log(`Selected ${selection.length} entities`);
}
});
await cadOverlay.addTo(map);
// Create random entities
function addRandomEntities() {
const bounds = cadOverlay.getCadBounds();
const [minX, minY, maxX, maxY] = bounds;
const entities = [];
// Random lines
for (let i = 0; i < 10; i++) {
const x1 = minX + Math.random() * (maxX - minX);
const y1 = minY + Math.random() * (maxY - minY);
const x2 = minX + Math.random() * (maxX - minX);
const y2 = minY + Math.random() * (maxY - minY);
const line = new LineEnt([x1, y1], [x2, y2]);
line.setDefaults();
line.color = Math.floor(Math.random() * 7) + 1;
entities.push(line);
}
// Random circles
for (let i = 0; i < 5; i++) {
const cx = minX + Math.random() * (maxX - minX);
const cy = minY + Math.random() * (maxY - minY);
const radius = (maxX - minX) * 0.05 * (0.5 + Math.random());
const circle = new CircleEnt([cx, cy], radius);
circle.setDefaults();
circle.color = Math.floor(Math.random() * 7) + 1;
entities.push(circle);
}
// Random text
const texts = ['WebCAD', 'vjmap', 'Test', 'Example'];
for (let i = 0; i < 4; i++) {
const x = minX + Math.random() * (maxX - minX);
const y = minY + Math.random() * (maxY - minY);
const text = new TextEnt();
text.insertionPoint = [x, y];
text.text = texts[i];
text.height = (maxX - minX) * 0.03;
text.setDefaults();
text.color = Math.floor(Math.random() * 7) + 1;
entities.push(text);
}
cadOverlay.addEntities(entities);
}
addRandomEntities();
cadOverlay.zoomToExtents();Notes
- Coordinate system: CAD coordinates are converted to longitude/latitude through vjmap projection. Ensure
boundsandmap.setMapProjection()use the same extent - Transparent background: the WebCAD layer background is transparent, so the map tiles underneath remain visible
- Event passthrough: the WebCAD layer uses
pointer-events: none; mouse events are handled by the map and entity picking is computed from coordinates - Selection mode
- Click to select one entity
- Shift+click to add/remove selection
ESCclears selection
- Performance optimization
- Default
smoothAnimation: trueprovides smoother animation - Set to
falsefor more immediate response, but there may be slight jitter at high zoom levels
- Default
- No tilt support: map
pitchshould be set to0; 3D tilted view is not supported
Next Steps
- Viewer Mode - standalone CAD viewer
- Preview View Component - lightweight preview component
- Event System - more event types