leaflet
本文回答:已有 Leaflet 项目里叠加 vjmap CAD 图。
一、Leaflet 上叠 CAD WMS
const svc = new vjmap.Service(URL, TOKEN);
await svc.openMap({ mapid: "sys_cad2000", mapopenway: vjmap.MapOpenWay.GeomRender });
const wmsUrl = svc.wmsTileUrl({
mapid: "sys_cad2000",
layers: "默认图层名",
bbox: "", // ⚠️ 必传空串:默认 "{bbox-epsg-3857}" 只有 vjmap 引擎会填,Leaflet 不认
srs: "EPSG:3857",
crs: "EPSG:4548" // sys_cad2000 是 CGCS2000 3° 带 117°E(无带号)
});
// 用 L.tileLayer.wms(由它追加 bbox);普通 L.tileLayer 遇到 {bbox-epsg-3857} 模板会直接抛错
const cadLayer = L.tileLayer.wms(wmsUrl, { zIndex: 10 });
cadLayer.addTo(leafletMap);
二、以 CAD 为底图(Leaflet 加载互联网瓦片作 overlay)
此模式用 vjmap 做底图更方便;但如果必须用 Leaflet:webMapUrl 返回的瓦片是按 vjmap 的 CAD 瓦片网格切的,Leaflet 地图必须用与之匹配的自定义 CRS(以 CAD 范围为基准的 L.CRS.Simple 变体,见官方示例 12leafletwebCad.js),CAD 本身用 svc.rasterTileUrl() 作底图;默认 EPSG:3857 的 Leaflet 地图上叠不齐:
// 自定义 CRS:zoom 0 = 一张 256 瓦片覆盖整个 CAD 范围
const mapBounds = vjmap.GeoBounds.fromString(res.bounds);
const CadCRS = L.Class.extend({
includes: L.CRS.Simple,
initialize: function (llb) { // llb: L.LatLngBounds
this.bounds = llb;
this.projection = L.Projection.LonLat;
const r = 256 / Math.abs(llb.getEast() - llb.getWest());
this.transformation = new L.Transformation(r, -r * llb.getWest(), -r, r * llb.getNorth());
}
});
const llBounds = L.latLngBounds([[mapBounds.min.y, mapBounds.min.x], [mapBounds.max.y, mapBounds.max.x]]);
const leafletMap = L.map("map", { crs: new CadCRS(llBounds) })
.setView([mapBounds.center().y, mapBounds.center().x], 2);
L.tileLayer(svc.rasterTileUrl(), { bounds: llBounds }).addTo(leafletMap); // CAD 底图
再叠互联网瓦片:
const tileUrl = svc.webMapUrl({
tileCrs: "gcj02",
tileUrl: [
"https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
],
tileSize: 256,
tileShards: "1,2,3,4",
mapbounds: res.bounds,
srs: "EPSG:4527",
fourParameterBefore: "39000000,0,1,0"
});
const gaodeLayer = L.tileLayer(tileUrl, { zIndex: 0 });
gaodeLayer.addTo(leafletMap);
三、坐标互转
Leaflet 里取鼠标点击时的 LatLng,要转 CAD:
leafletMap.on("click", async (e) => {
const latlng = e.latlng;
// 目标 EPSG 必须与 WMS 的 crs 一致(sys_cad2000 → EPSG:4548;EPSG:4544 是 105°E 带,不是同一投影)
const res = await svc.cmdTransform("EPSG:4326", "EPSG:4548", vjmap.geoPoint([latlng.lng, latlng.lat])); // points 必须 geoPoint 包装,裸数组会序列化成 undefined,undefined
console.log("CAD:", res[0]);
});
四、四参数(无坐标系 CAD)
和 baidu 类似:求 4 个公共点 → coordTransfromGetFourParamter → 传入 fourParameter 参数。
五、混合方案
很多项目只用 Leaflet 显示经纬度底图 + 业务 markers / polyline,CAD 用 iframe 套 vjmap;需要时通过 postMessage 同步视图。
六、常见坑
- tileSize:vjmap CAD 栅格瓦片(
rasterStyle/rasterTileUrl)本就是 256,与 Leaflet 默认一致,无需改 tileSize;WMS 瓦片尺寸由L.tileLayer.wms按请求生成。 - Leaflet 没有
renderWorldCopies: false→ 无限水平 pan;对 CAD 图来说不合理。Leaflet 的maxBounds限制范围。 - zoom 固定差 1:vjmap 引擎按 512 像素世界计 zoom、取 256 瓦片时瓦片级 = zoom + 1,所以同一画面 Leaflet zoom = vjmap zoom + 1(与 retina 无关)。