Internet basemaps
About 2 min
Internet basemaps
vjmapext works on CAD drawings and on internet raster basemaps (Tianditu, Amap, etc.). Recommended patterns below.
Core idea
- Internal coordinates use Web Mercator meters (EPSG:3857).
- Projection:
vjmap.GeoProjectionwith global Mercator bounds[-EQ, -EQ, EQ, EQ],EQ = vjmap.Projection.EQUATORIAL_SEMIPERIMETER. - Convert lng/lat to Mercator meters before passing coordinates to
MapCadLayer.
const EQ = vjmap.Projection.EQUATORIAL_SEMIPERIMETER;
const prj = new vjmap.GeoProjection(vjmap.GeoBounds.fromArray([-EQ, -EQ, EQ, EQ]));
const xy = vjmap.Projection.lngLat2Mercator([lng, lat]);Tianditu
const { MapCadLayer, CircleEnt, TextEnt } = vjmapext;
const svc = new vjmap.Service(env.serviceUrl, env.accessToken);
const EQ = vjmap.Projection.EQUATORIAL_SEMIPERIMETER;
const prj = new vjmap.GeoProjection(vjmap.GeoBounds.fromArray([-EQ, -EQ, EQ, EQ]));
const map = new vjmap.Map({
container: 'map',
style: {
version: svc.styleVersion(),
glyphs: svc.glyphsUrl(),
sources: {
tdtVec: {
type: 'raster',
tiles: ['https://t3.tianditu.gov.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk=<YOUR_TOKEN>']
},
tdtCva: {
type: 'raster',
tiles: ['https://t3.tianditu.gov.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}&tk=<YOUR_TOKEN>']
}
},
layers: [
{ id: 'tdtVec', type: 'raster', source: 'tdtVec' },
{ id: 'tdtCva', type: 'raster', source: 'tdtCva' }
]
},
center: [116.3912, 39.9073],
zoom: 13,
renderWorldCopies: false
});
map.attach(svc, prj);
await map.onLoad();
const mapcadLayer = new MapCadLayer({
defaultColor: 0x1f4e79,
drawingDefaults: {
color: 0x1f4e79,
fillColor: 0x1f4e79,
fillOpacity: 0.15
}
});
map.addControl(mapcadLayer);
mapcadLayer.createUI({ theme: 'light' });
const p = vjmap.Projection.lngLat2Mercator([116.3912, 39.9073]);
const c = new CircleEnt([p[0], p[1]], 120);
c.color = 0xc0392b;
c.fillColor = 0xc0392b;
c.fillOpacity = 0.35;
mapcadLayer.addEntity(c);Tile types
vec_w— vector roadimg_w— imagerycva_w— Chinese labels (often stacked withvec_w/img_w)
Amap (GCJ02)
Amap tiles use GCJ02. WGS84 GPS coordinates must be converted before Mercator:
function wgsToXY(lng, lat) {
const gcj = vjmap.transform.convert(
[lng, lat],
vjmap.transform.CRSTypes.WGS84,
vjmap.transform.CRSTypes.GCJ02
);
return vjmap.Projection.lngLat2Mercator(gcj);
}const svc = new vjmap.Service(env.serviceUrl, env.accessToken);
const EQ = vjmap.Projection.EQUATORIAL_SEMIPERIMETER;
const prj = new vjmap.GeoProjection(vjmap.GeoBounds.fromArray([-EQ, -EQ, EQ, EQ]));
const centerGcj = vjmap.transform.convert(
[116.3912, 39.9073],
vjmap.transform.CRSTypes.WGS84,
vjmap.transform.CRSTypes.GCJ02
);
const map = new vjmap.Map({
container: 'map',
style: {
version: svc.styleVersion(),
glyphs: svc.glyphsUrl(),
sources: {
gaode: {
type: 'raster',
tiles: ['https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}']
}
},
layers: [{ id: 'gaode', type: 'raster', source: 'gaode' }]
},
center: centerGcj,
zoom: 13,
renderWorldCopies: false
});
map.attach(svc, prj);
await map.onLoad();
const mapcadLayer = new MapCadLayer({
defaultColor: 0x1f4e79,
drawingDefaults: { color: 0x1f4e79, fillColor: 0x1f4e79, fillOpacity: 0.15 }
});
map.addControl(mapcadLayer);
mapcadLayer.createUI({ theme: 'light' });
const xy = wgsToXY(116.3912, 39.9073);Warning
centermust use the same CRS as the basemap (GCJ02 here).- Skipping correction offsets entities by tens to hundreds of meters.
Light basemap styling
UI theme
light:mapcadLayer.createUI({ theme: 'light' });Dark default stroke/fill for previews and new entities:
new MapCadLayer({ defaultColor: 0x1f4e79, drawingDefaults: { color: 0x1f4e79, fillColor: 0x1f4e79, fillOpacity: 0.15 } });Match
bodybackground to a light gray if your shell used a dark demo background:document.body.style.background = '#f5f7fa';
Demo sources
| Demo | Description |
|---|---|
| web/01webTianditu.js | Tianditu + CAD overlay |
| web/02webGaode.js | Amap, WGS84 → GCJ02 |
| basic/04locale.js | Locale + light/dark theme |