---
name: vjmap
description: Use when building web map or CAD applications with vjmap (唯杰地图 map2d) — opening DWG drawings, initializing the map, coordinate transforms (CAD / WGS84 / GCJ02 / BD09 / Mercator), overlaying internet basemaps (Tianditu, Gaode, Baidu, OSM), drawing Markers / Popups / Symbols / polygons / polylines, bulk GeoJSON features, right-click context menu, measurement, layer style expressions, map & EventBus events, render performance, backend service calls (SQL / expression / fulltext query, uploadMap, DWG export), or troubleshooting vjmap integration. Keywords 唯杰地图 vjmap map2d 打开图 DWG 坐标转换 Marker Popup Symbol 图层样式 表达式 右键菜单 测量 互联网底图叠加 批量 性能 报错. Excludes vjmapext CAD entities/commands (use vjmapext skill), vjmap3d (use vjmap3d skill), vjcad (use vjcad skill).
metadata:
  product: map2d
  package: vjmap
  packageVersion: "1.0.161"
  docsMcp: https://vjmap.com/server/aimcp/mcp?products=map2d
---

# vjmap（唯杰地图 2D）二次开发技能

> 面向 **vjmap (map2d)** Web 地图底座的二次开发。CAD 绘图扩展（`MapCadLayer`）见 **vjmapext** skill；三维见 **vjmap3d** skill；纯 CAD 编辑器见 **vjcad** skill。

## 〇、文档与示例来源（路径约定）

本 skill 的 `references/` 是自带离线参考，已按 **vjmap@1.0.161** 的 `dist/vjmap.d.ts` 与官方示例核对。仍需更深细节时按下列来源查证，**冲突时以 npm 包 .d.ts 与 playground 示例为准**：

| 来源 | 用法 |
|---|---|
| 官方文档/示例 MCP | `https://vjmap.com/server/aimcp/mcp?products=map2d`（工具：`list_docs` / `search_docs` / `get_doc_content`）。路径前缀：`map2d/doc/...`（官方文档）、`map2d/vjmap-playground/src/...`（在线示例源码）、`map2d/vjmap-vue3/...`、`map2d/vjmap-common/...` |
| npm 包类型定义 | `npm i vjmap` 后看 `node_modules/vjmap/dist/vjmap.d.ts` |
| 服务 REST 接口 | `references/backend/rest-interface.md`，服务能力见 **vjmap-service** skill |

示例代码中的 `env.serviceUrl` / `env.accessToken` / `env.exampleMapId` 是 playground 注入的环境变量；自己项目里替换为**你的服务地址与 token**（公有云 `https://vjmap.com/server/api/v1`，私有化 `http://<ip>:27660/api/v1`）。**不要把 token 写进提交的代码**。

## 一、适用范围

| 包 | 角色 | 包含 | 不包含 |
|---|---|---|---|
| `vjmap` | Web 地图底座（支持 DWG / 矢量瓦片 / 栅格瓦片 / 互联网地图的 WebGL 渲染框架） | Service / Map / GeoProjection / Marker / Popup / Symbol / Polyline / Polygon / FillExtrusion / 图层与样式 / 事件 / 坐标转换 / 互联网地图叠加 / 交互控件 / 后台服务 | — |
| `vjmapext` | CAD 绘图扩展（`MapCadLayer` 挂在 `vjmap.Map` 上） | — | **不在范围**，见 vjmapext skill |
| `vjmap3d` | 三维地图 | — | **不在范围**，见 vjmap3d skill |
| `vjcad` | 纯 CAD 编辑器 | — | **不在范围**，见 vjcad skill |

## 二、安装与引入

**npm**（推荐用于工程化项目）：

```bash
npm i vjmap          # vjmapext 需另装：npm i vjmap vjmapext
```

```ts
import vjmap from "vjmap";
import "vjmap/dist/vjmap.min.css";
```

**CDN / 全局对象**（单 HTML 直跑；unpkg / jsdelivr 均可，版本号按需替换）：

```html
<link rel="stylesheet" href="https://unpkg.com/vjmap@1.0.161/dist/vjmap.min.css">
<script src="https://unpkg.com/vjmap@1.0.161/dist/vjmap.min.js"></script>
<!-- 全局对象 vjmap；官方 demo CDN 亦可用：https://vjmap.com/demo/js/vjmap/vjmap.min.js -->
```

**起步模板**（复制即用）：`templates/vite-app/`（npm + Vite，[README](templates/vite-app/README.md)）与 `templates/cdn/`（单 HTML），均含完整 openMap→attach→onLoad 初始化代码，只需替换 `serviceUrl / accessToken / mapid`。

## 三、心智模型

```
       [DWG / 互联网底图]
              |
              v
+-----------+       +-----------------+
|  Service  |---->  |  GeoProjection  |          创建顺序：
| (后台API) |       | (图范围/经纬度) |          1. new vjmap.Service(url, token)
+-----------+       +-----------------+          2. await svc.openMap({mapid, fileid, mapopenway, style})
        \              /                          3. new vjmap.GeoProjection(GeoBounds.fromString(res.bounds))
         v            v                           4. new vjmap.Map({container, style, center, zoom})
         +----------------+                       5. map.attach(svc, prj)
         |  vjmap.Map      | (WebGL 渲染)         6. await map.onLoad()
         |  - sources       |                      7. (可选) vjmapext MapCadLayer → 见 vjmapext skill
         |  - layers        |
         |  - Marker/Popup  |
         |  - events        |
         +-----------------+
```

**关键认知**：
1. `vjmap.Map` 遵循主流 WebGL 地图框架的 `source/layer/event` API 风格，另外扩展了 `attach/toLngLat/fromLngLat/onLoad/getGeoBounds/enableVectorLayerHoverHighlight/...` 等 vjmap 专有接口。
2. 渲染用的**经纬度**只有在以互联网地图为底图时才有真实地理意义；以 CAD 图为底图时，它只是把 CAD 原始坐标映射到 `(-180,180) × (-85.0511,85.0511)` 的渲染区间。
3. 几何计算用 **CAD 几何坐标**，绘制用 **经纬度坐标**；坐标往返永远通过 `map.toLngLat / map.fromLngLat`（或 `prj.toLngLat / prj.fromLngLat`）。
4. 需要保存坐标到后台时，**一律保存 CAD 坐标**；加载时再 `toLngLat` 转为渲染经纬度。

## 四、最小可运行模板（MRT）

**CDN 版（HTML 直接粘贴运行）**：

```html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://vjmap.com/demo/js/vjmap/vjmap.min.css">
  <script src="https://vjmap.com/demo/js/vjmap/vjmap.min.js"></script>
</head>
<body style="margin:0">
<div id="map" style="position:absolute;left:0;top:0;right:0;bottom:0"></div>
<script>
window.onload = async () => {
  const svc = new vjmap.Service(
    "https://vjmap.com/server/api/v1",   // 换成你的服务地址
    "YOUR_TOKEN"                          // 换成你的 token
  );
  const res = await svc.openMap({
    mapid: "sys_zp",
    mapopenway: vjmap.MapOpenWay.GeomRender,
    style: vjmap.openMapDarkStyle()
  });
  if (res.error) { console.error(res.error); return; }

  const prj = new vjmap.GeoProjection(res.bounds);
  const map = new vjmap.Map({
    container: "map",
    style: svc.vectorStyle(),
    center: prj.toLngLat(prj.getMapExtent().center()),
    zoom: 2,
    renderWorldCopies: false
  });
  map.attach(svc, prj);
  await map.onLoad();

  const center = prj.toLngLat(prj.getMapExtent().center());
  new vjmap.Marker()
    .setLngLat(center)
    .setPopup(new vjmap.Popup().setHTML("<b>hello vjmap</b>"))
    .addTo(map);
};
</script>
</body>
</html>
```

**npm 版**：`npm i vjmap` + `import vjmap from "vjmap"; import "vjmap/dist/vjmap.min.css";`，其余代码一致。Vue3 工程集成见 [setup/integrations](references/setup/integrations.md) 与 `map2d/vjmap-vue3/` 示例。

**vjmapext 版**（CAD 实体 / 绘图命令 / 编辑交互）：见 **vjmapext** skill 的 MRT。

## 五、按用户场景速查

标 【vjmapext】 的条目属于 CAD 绘图扩展，对应文件在 `../vjmapext/references/`（两个 skill 并列安装时链接可直接跳转）。

| 用户问题 | 去读 |
|---|---|
| 怎么打开一张 DWG 图？ | [open-map/open-dwg](references/open-map/open-dwg.md) |
| 三种打开方式有什么区别（内存/几何栅格/几何矢量）？ | [open-map/map-open-way](references/open-map/map-open-way.md) |
| 打开一张空白图？ | [open-map/blank-map](references/open-map/blank-map.md) |
| 切换当前图？ | [open-map/switching](references/open-map/switching.md) |
| `toLngLat` 和 `fromLngLat` 的关系？ | [coord/concepts](references/coord/concepts.md) + [coord/projection-api](references/coord/projection-api.md) |
| WGS84 / GCJ02 / BD09 互转？ | [coord/gis-transforms](references/coord/gis-transforms.md) |
| 高德/天地图底图上 CAD 偏移怎么办？ | [coord/internet-basemap-align](references/coord/internet-basemap-align.md) + [internet-map/gaode](references/internet-map/gaode.md) |
| UCS <-> WCS 转换？ | [coord/concepts](references/coord/concepts.md) |
| Marker / Symbol / CircleFill 等覆盖物该传 CAD 坐标还是渲染经纬度？ | [coord/overlay-coords](references/coord/overlay-coords.md) |
| 查询结果 `.geom`/`.geojson`/`points`/`envelop` 各在什么空间、怎么叠到图上？ | [coord/query-coords](references/coord/query-coords.md) |
| 如何叠加天地图？ | [internet-map/tianditu](references/internet-map/tianditu.md) |
| 如何叠加高德矢量图？ | [internet-map/gaode](references/internet-map/gaode.md) |
| 叠加百度地图？ | [internet-map/baidu](references/internet-map/baidu.md) |
| 叠加 XYZ 瓦片 / OSM？ | [internet-map/raster-tile](references/internet-map/raster-tile.md) + [internet-map/osm-overseas](references/internet-map/osm-overseas.md) |
| 左右两张图联动对比？ | [overlay/multi-map](references/overlay/multi-map.md) + [overlay/sync-view](references/overlay/sync-view.md) |
| Cesium 3D + CAD 2D 叠加？ | [overlay/cesium](references/overlay/cesium.md) |
| 地图批注 / 图例 / 指北针 / 比例尺？ | [overlay/annotation](references/overlay/annotation.md) + [overlay/legend-north-scale](references/overlay/legend-north-scale.md) |
| **怎么加右键菜单？** | [interaction/context-menu](references/interaction/context-menu.md) |
| 测量长度 / 面积？ | [interaction/measure](references/interaction/measure.md) |
| vjmap 自带绘图工具（点/线/面/矩形）？ | [interaction/draw-tools](references/interaction/draw-tools.md) + [interaction/draw-action](references/interaction/draw-action.md) |
| 框选 + 点选 + 过滤图层？ | [interaction/select-feature](references/interaction/select-feature.md) |
| 加导航/比例尺/全屏控件？ | [interaction/controls](references/interaction/controls.md) |
| 捕捉 / 正交 / 快捷键（Draw.Tool）？ | [interaction/snap-ortho](references/interaction/snap-ortho.md) |
| 禁用拖拽 / 旋转 / 缩放？ | [interaction/drag-rotate-zoom](references/interaction/drag-rotate-zoom.md) |
| 鼠标键盘事件？ | [interaction/mouse-keyboard](references/interaction/mouse-keyboard.md) |
| 如何创建一个 Marker？ | [marker/create](references/marker/create.md) |
| Marker 完整参数？ | [marker/options](references/marker/options.md) |
| 内置图标 / SVG 自定义 Marker？ | [marker/builtin-icons](references/marker/builtin-icons.md) |
| 自定义 DOM 的 Marker？ | [marker/custom-dom](references/marker/custom-dom.md) |
| Marker 缩放时位置飘移？ | [marker/anchor-offset](references/marker/anchor-offset.md) |
| Marker 随缩放显隐 / 限定级别？ | [marker/zoom-behavior](references/marker/zoom-behavior.md) |
| Marker 动画（呼吸/光圈/旋转）？ | [marker/animation](references/marker/animation.md) |
| Marker 拖动？ | [marker/drag](references/marker/drag.md) |
| Marker 点击/悬停事件？ | [marker/events](references/marker/events.md) |
| 万级 Marker 聚合？ | [marker/cluster](references/marker/cluster.md) |
| Marker 绑定 Popup？ | [marker/with-popup](references/marker/with-popup.md) |
| Marker 太多太卡（10 万个）？ | [marker/performance-tips](references/marker/performance-tips.md) + [symbol/marker-vs-symbol](references/symbol/marker-vs-symbol.md) + [perf/large-markers](references/perf/large-markers.md) |
| 创建 Popup？ | [popup/create](references/popup/create.md) |
| Popup 选项（关闭按钮/锚点/偏移/追踪鼠标）？ | [popup/options](references/popup/options.md) + [popup/track-pointer](references/popup/track-pointer.md) |
| Popup 里放 Vue/React 组件？ | [popup/dynamic-content](references/popup/dynamic-content.md) |
| 点符号（圆 / 图标 / 文字）？ | [symbol/circle-symbol](references/symbol/circle-symbol.md) + [symbol/icon-symbol](references/symbol/icon-symbol.md) + [symbol/text-symbol](references/symbol/text-symbol.md) |
| 用 DOM Marker 还是 Symbol 图层？ | [symbol/marker-vs-symbol](references/symbol/marker-vs-symbol.md) |
| 画线（粗细/虚线/渐变）？ | [primitive/line](references/primitive/line.md) + [primitive/polyline-api](references/primitive/polyline-api.md) |
| 画多边形 + 轮廓？ | [primitive/polygon-fill](references/primitive/polygon-fill.md) |
| 画圆/弧/椭圆？ | [primitive/circle-arc](references/primitive/circle-arc.md) |
| 用 GeoJSON 源批量画？ | [primitive/geojson-source](references/primitive/geojson-source.md) + [batch/geojson-bulk](references/batch/geojson-bulk.md) |
| 图层样式表达式怎么写？ | [map-style/expressions](references/map-style/expressions.md) + [symbol/expression](references/symbol/expression.md) |
| 数据驱动染色（match/case/interpolate）？ | [map-style/data-driven](references/map-style/data-driven.md) |
| 拉伸成 3D？ | [map-style/extrusion-3d](references/map-style/extrusion-3d.md) |
| 雾 / 天空 / 大气 / 主题切换？ | [map-style/fog-sky-atmosphere](references/map-style/fog-sky-atmosphere.md) + [map-style/theme-switch](references/map-style/theme-switch.md) |
| 查询图上所有文字 / 某图层所有实体？ | [backend/query-features](references/backend/query-features.md) + [backend/query-expression](references/backend/query-expression.md) |
| SQL 条件查询？ | [backend/query-sql](references/backend/query-sql.md) |
| 全文搜索？ | [backend/query-fulltext](references/backend/query-fulltext.md) |
| 服务端条件高亮（不用查询）？ | [backend/svr-style-var](references/backend/svr-style-var.md) |
| 自动分割子图 / 自动标注 / 提取表格 / 提取中心线？ | [backend/query-cases](references/backend/query-cases.md) |
| 上传 DWG 创建新图？ | [backend/upload-create-map](references/backend/upload-create-map.md) |
| 实体智能识别？ | [backend/recognizer](references/backend/recognizer.md) |
| AI 对话 / AI 绘 CAD / 地图 MCP 协议？ | [backend/ai-features](references/backend/ai-features.md) |
| 导出 DWG / PNG / PDF？ | [backend/export-dwg](references/backend/export-dwg.md) + [backend/export-formats](references/backend/export-formats.md) |
| 【vjmapext】创建 CAD 实体（LineEnt / CircleEnt / TextEnt）？ | `../vjmapext/references/entity/overview.md` + 对应叶子 |
| 【vjmapext】批量导入 mapdata 到实体层？ | `../vjmapext/references/batch/mapdata-query.md` + `features-to-entities.md` |
| 【vjmapext】执行 LINE / CIRCLE / MOVE 命令？ | `../vjmapext/references/drawing/execute-command.md` + `builtin-draw.md` |
| 【vjmapext】监听命令结束 / 实体增删改？ | `../vjmapext/references/event/bus-command-mode.md` + `bus-entity.md` |
| 【vjmapext】自定义命令 / 捕捉 / 夹点 / undo？ | `../vjmapext/references/drawing/custom-command.md` 等 |
| 【vjmapext】大量实体卡顿 / 告警光圈？ | `../vjmapext/references/perf/` 全目录 |
| 点击地图上哪个图层？ | [event/layer-events](references/event/layer-events.md) |
| 地图 load / move / zoom 事件？ | [event/map-lifecycle](references/event/map-lifecycle.md) + [event/map-view](references/event/map-view.md) |
| 事件监听怎么清理（map.on / eventBus.on）？ | [event/cleanup](references/event/cleanup.md) |
| Vue3 卸载组件后 Marker 残留？ | [setup/dispose](references/setup/dispose.md) + [trouble/vue-react-dispose](references/trouble/vue-react-dispose.md) |
| 首屏黑屏 / 容器塌陷？ | [trouble/container-collapse](references/trouble/container-collapse.md) |
| token 失效（HTTP 403）/ CORS？ | [trouble/token-cors](references/trouble/token-cors.md) |

## 六、完整文件地图

**环境初始化 (setup/)**  
[overview](references/setup/overview.md) · [install](references/setup/install.md) · [container](references/setup/container.md) · [integrations](references/setup/integrations.md) · [dispose](references/setup/dispose.md)

**打开图 (open-map/)**  
[overview](references/open-map/overview.md) · [open-dwg](references/open-map/open-dwg.md) · [map-open-way](references/open-map/map-open-way.md) · [blank-map](references/open-map/blank-map.md) · [bounds-and-projection](references/open-map/bounds-and-projection.md) · [switching](references/open-map/switching.md)

**坐标转换 (coord/)**  
[overview](references/coord/overview.md) · [concepts](references/coord/concepts.md) · [projection-api](references/coord/projection-api.md) · [gis-transforms](references/coord/gis-transforms.md) · [internet-basemap-align](references/coord/internet-basemap-align.md) · [cad-epsg](references/coord/cad-epsg.md) · [overlay-coords](references/coord/overlay-coords.md) · [query-coords](references/coord/query-coords.md)

**后台服务 (backend/)**  
[overview](references/backend/overview.md) · [service-basics](references/backend/service-basics.md) · [rest-interface](references/backend/rest-interface.md) · [common-map-methods](references/backend/common-map-methods.md) · [query-sql](references/backend/query-sql.md) · [query-expression](references/backend/query-expression.md) · [query-features](references/backend/query-features.md) · [query-fulltext](references/backend/query-fulltext.md) · [query-cases](references/backend/query-cases.md) · [svr-style-var](references/backend/svr-style-var.md) · [map-management](references/backend/map-management.md) · [upload-create-map](references/backend/upload-create-map.md) · [map-sources](references/backend/map-sources.md) · [map-power](references/backend/map-power.md) · [export-dwg](references/backend/export-dwg.md) · [export-formats](references/backend/export-formats.md) · [recognizer](references/backend/recognizer.md) · [ai-features](references/backend/ai-features.md)

**Marker (marker/)**  
[overview](references/marker/overview.md) · [create](references/marker/create.md) · [options](references/marker/options.md) · [builtin-icons](references/marker/builtin-icons.md) · [custom-dom](references/marker/custom-dom.md) · [anchor-offset](references/marker/anchor-offset.md) · [zoom-behavior](references/marker/zoom-behavior.md) · [animation](references/marker/animation.md) · [drag](references/marker/drag.md) · [events](references/marker/events.md) · [cluster](references/marker/cluster.md) · [with-popup](references/marker/with-popup.md) · [performance-tips](references/marker/performance-tips.md)

**Popup (popup/)**  
[overview](references/popup/overview.md) · [create](references/popup/create.md) · [options](references/popup/options.md) · [track-pointer](references/popup/track-pointer.md) · [marker-binding](references/popup/marker-binding.md) · [styling](references/popup/styling.md) · [dynamic-content](references/popup/dynamic-content.md)

**Symbol (symbol/)**  
[overview](references/symbol/overview.md) · [layer-types](references/symbol/layer-types.md) · [circle-symbol](references/symbol/circle-symbol.md) · [icon-symbol](references/symbol/icon-symbol.md) · [text-symbol](references/symbol/text-symbol.md) · [expression](references/symbol/expression.md) · [marker-vs-symbol](references/symbol/marker-vs-symbol.md)

**Primitive (primitive/)**  
[overview](references/primitive/overview.md) · [line](references/primitive/line.md) · [polygon-fill](references/primitive/polygon-fill.md) · [polyline-api](references/primitive/polyline-api.md) · [circle-arc](references/primitive/circle-arc.md) · [geojson-source](references/primitive/geojson-source.md) · [editing](references/primitive/editing.md) · [svg-div-overlay](references/primitive/svg-div-overlay.md)

**批量 (batch/)**  
[geojson-bulk](references/batch/geojson-bulk.md)（实体级批量在 vjmapext skill）

**互联网地图 (internet-map/)**  
[overview](references/internet-map/overview.md) · [tianditu](references/internet-map/tianditu.md) · [gaode](references/internet-map/gaode.md) · [baidu](references/internet-map/baidu.md) · [tencent](references/internet-map/tencent.md) · [osm-overseas](references/internet-map/osm-overseas.md) · [raster-tile](references/internet-map/raster-tile.md) · [vector-tile](references/internet-map/vector-tile.md) · [label-overlay](references/internet-map/label-overlay.md) · [zoom-level-map](references/internet-map/zoom-level-map.md)

**叠加 (overlay/)**  
[overview](references/overlay/overview.md) · [multi-map](references/overlay/multi-map.md) · [deckgl](references/overlay/deckgl.md) · [leaflet](references/overlay/leaflet.md) · [openlayers](references/overlay/openlayers.md) · [cesium](references/overlay/cesium.md) · [annotation](references/overlay/annotation.md) · [legend-north-scale](references/overlay/legend-north-scale.md) · [sync-view](references/overlay/sync-view.md)

**交互工具 (interaction/)**  
[overview](references/interaction/overview.md) · [context-menu](references/interaction/context-menu.md) · [measure](references/interaction/measure.md) · [draw-tools](references/interaction/draw-tools.md) · [draw-action](references/interaction/draw-action.md) · [select-feature](references/interaction/select-feature.md) · [controls](references/interaction/controls.md) · [mouse-keyboard](references/interaction/mouse-keyboard.md) · [drag-rotate-zoom](references/interaction/drag-rotate-zoom.md) · [snap-ortho](references/interaction/snap-ortho.md)

**地图样式 (map-style/)**  
[overview](references/map-style/overview.md) · [style-spec](references/map-style/style-spec.md) · [layer-styles](references/map-style/layer-styles.md) · [expressions](references/map-style/expressions.md) · [data-driven](references/map-style/data-driven.md) · [extrusion-3d](references/map-style/extrusion-3d.md) · [fog-sky-atmosphere](references/map-style/fog-sky-atmosphere.md) · [sprite-glyphs](references/map-style/sprite-glyphs.md) · [theme-switch](references/map-style/theme-switch.md)

**事件 (event/)**  
[overview](references/event/overview.md) · [map-interaction](references/event/map-interaction.md) · [map-lifecycle](references/event/map-lifecycle.md) · [map-view](references/event/map-view.md) · [layer-events](references/event/layer-events.md) · [cleanup](references/event/cleanup.md)（EventBus `entity:*/command:*` 事件在 vjmapext skill）

**性能 (perf/)**  
[overview](references/perf/overview.md) · [large-markers](references/perf/large-markers.md) · [event-throttling](references/perf/event-throttling.md) · [memory-leaks](references/perf/memory-leaks.md) · [profiling](references/perf/profiling.md)（实体渲染桶 / FX 特效性能在 vjmapext skill）

**常见坑 (trouble/)**  
[overview](references/trouble/overview.md) · [container-collapse](references/trouble/container-collapse.md) · [cdn-order](references/trouble/cdn-order.md) · [token-cors](references/trouble/token-cors.md) · [bounds-parse](references/trouble/bounds-parse.md) · [coord-offset-gaode](references/trouble/coord-offset-gaode.md) · [marker-duplicate](references/trouble/marker-duplicate.md) · [listener-leak](references/trouble/listener-leak.md) · [vue-react-dispose](references/trouble/vue-react-dispose.md)

## 七、约定、命名与红旗

### 命名

- `svc` = `vjmap.Service` 实例；`map` = `vjmap.Map` 实例；`prj` = `vjmap.GeoProjection` 实例；`mapcadLayer` = `vjmapext.MapCadLayer` 实例（见 vjmapext skill）。
- `res = await svc.openMap(...)` 要包 `try/catch`（HTTP 非 2xx——403 token 失效、404 图不存在——直接 reject，不进 `res.error`），成功返回后再立刻检查 `res.error`（带内错误，如密码图）。

### 异步初始化顺序

1. `new vjmap.Service(url, token)`
2. `await svc.openMap({mapid, fileid, mapopenway, style})` → 得 `res.bounds`
3. `new vjmap.GeoProjection(res.bounds)`（或 `vjmap.LnglatProjection` 用于互联网底图）
4. `new vjmap.Map({container, style, center, zoom, ...})`
5. `map.attach(svc, prj)`
6. `await map.onLoad()` — **之后才能** 加 source/layer/Marker/Control
7. （可选）`new vjmapext.MapCadLayer(...)` → `map.addControl(cad)` — 详见 vjmapext skill

### Top 10 红旗

1. 容器 `<div>` 没有宽高或 `position` 未设 `relative/absolute` → 首屏黑屏。
2. `<script>` 里把 `vjmapext` 写在 `vjmap` 之前 → 依赖未就绪。
3. `openMap` 没 `try/catch`、之后也没检查 `res.error` 就继续。
4. 互联网底图上画 CAD 数据不做 GCJ02/BD09 纠偏 → 整体偏移。
5. 批量 `addEntity` 在循环里每次都 `setDirty()` / 单独 commit → 卡顿（vjmapext）。
6. Vue/React 组件卸载时没 `map.remove()` + 清监听 → Marker 重影、内存泄漏。
7. `map.on('click', handler)` 没对应 `map.off` → 长期运行内存膨胀。
8. 10 万点标注用 DOM `Marker` 而不是 `Symbol` 图层 → 帧率崩。
9. `setData` 每帧都重建 FeatureCollection → 重复创建 GeoJSON worker。
10. 动画层和实体层混用（应放到 `fx` GPU 图层，vjmapext）→ 重绘抖动。

### 保存 / 加载坐标的规矩

- **保存至后台**：使用 `map.fromLngLat(lngLatObj)` 转为 CAD 几何坐标后保存。
- **从后台加载**：使用 `map.toLngLat(cadObj)` 转为渲染经纬度后绘制。
- 几何计算（相交、插值、偏移…）：用 CAD 坐标算，只在最后绘制时转经纬度。
