唯杰地图 logo唯杰地图
VJMAP
EN

leaflet

vjmap/references/overlay/leaflet.md 3.9 KB89 行
原文

本文回答:已有 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 同步视图。

六、常见坑

  1. tileSize:vjmap CAD 栅格瓦片(rasterStyle / rasterTileUrl)本就是 256,与 Leaflet 默认一致,无需改 tileSize;WMS 瓦片尺寸由 L.tileLayer.wms 按请求生成。
  2. Leaflet 没有 renderWorldCopies: false → 无限水平 pan;对 CAD 图来说不合理。Leaflet 的 maxBounds 限制范围。
  3. zoom 固定差 1:vjmap 引擎按 512 像素世界计 zoom、取 256 瓦片时瓦片级 = zoom + 1,所以同一画面 Leaflet zoom = vjmap zoom + 1(与 retina 无关)。