> **本文回答**：已有 Leaflet 项目里叠加 vjmap CAD 图。

## 一、Leaflet 上叠 CAD WMS

```js
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 地图上叠不齐：

```js
// 自定义 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 底图
```

再叠互联网瓦片：

```js
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：

```js
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](../internet-map/baidu.md) 类似：求 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 无关）。
