> **本文回答**：vjmap + Deck.GL 集成方式 —— 加脚本、创建 DeckLayer、数据坐标。

## 一、加载 deck.gl

Deck.GL 通过动态脚本加载：

```js
if (typeof deck !== "object") {
  await vjmap.addScript({ src: "js/deck.gl.min.js" });
}
```

或 npm：

```bash
npm i deck.gl @deck.gl/layers
```

```js
import { ArcLayer, ScatterplotLayer } from "@deck.gl/layers";
```

> vjmap 提供 `vjmap.DeckLayer` 适配器，把 Deck.GL 图层包装成 vjmap 可识别的自定义图层，推荐直接用它（见下节）。

## 二、通过 `vjmap.DeckLayer` 集成

```js
const deckLayer = new vjmap.DeckLayer({
  id: "deck",
  type: deck.ArcLayer,
  data: [
    { from: { coord: [116.3, 39.9] }, to: { coord: [117.3, 40.9] } }
  ],
  getWidth: 12,
  getSourcePosition: d => d.from.coord,
  getTargetPosition: d => d.to.coord,
  getSourceColor: [255, 0, 0],
  getTargetColor: [0, 255, 0],
  pickable: true,
  autoHighlight: true,
  onClick: ({ object }) => alert("第 " + object.id)
});
map.addLayer(deckLayer);
```

> **坑位（deck 命名空间来源）**：构造函数实际读 `window.deck ?? props.deck`——**不是 `props.deckNs`**（d.ts 的 `deckNs` 字段名有误导性，传入无效）。用 script 标签加载 deck.gl UMD 时 `window.deck` 自动就位；npm `import deck` 的用户必须显式传 `deck` 属性：
>
> ```js
> import * as deck from "deck.gl"; // 传 deck.gl 元包的完整命名空间；只引入 @deck.gl/core、@deck.gl/layers 等子包不够
> new vjmap.DeckLayer({ id: "d", deck, type: deck.ArcLayer, /* ... */ });
> ```
>
> 两者都没有时构造即抛 `Cannot read properties of undefined`。

## 三、完整示例（弧线图）

```js
const svc = new vjmap.Service(URL, TOKEN);
const res = await svc.openMap({ mapid: "sys_zp", mapopenway: vjmap.MapOpenWay.GeomRender, style: vjmap.openMapDarkStyle() });
const prj = new vjmap.GeoProjection(vjmap.GeoBounds.fromString(res.bounds));

const map = new vjmap.Map({
  container: "map",
  style: svc.rasterStyle(),
  center: prj.toLngLat(prj.getMapExtent().center()),
  zoom: 2, pitch: 60,
  renderWorldCopies: false
});
map.attach(svc, prj);
await map.onLoad();

if (typeof deck !== "object") await vjmap.addScript({ src: "js/deck.gl.min.js" });

// 10 条随机弧线（坐标转到渲染经纬度）
const bounds = map.getGeoBounds(0.6);
const data = [];
for (let i = 0; i < 10; i++) {
  data.push({
    id: i + 1,
    from: {
      coordinates: map.toLngLat(bounds.randomPoint()),
      color: [vjmap.randInt(0,255), vjmap.randInt(0,255), vjmap.randInt(0,255)]
    },
    to: {
      coordinates: map.toLngLat(bounds.randomPoint()),
      color: [vjmap.randInt(0,255), vjmap.randInt(0,255), vjmap.randInt(0,255)]
    }
  });
}

const deckLayer = new vjmap.DeckLayer({
  id: "deck",
  type: deck.ArcLayer,
  data,
  getWidth: 12,
  getSourcePosition: d => d.from.coordinates,
  getTargetPosition: d => d.to.coordinates,
  getSourceColor: d => d.from.color,
  getTargetColor: d => d.to.color,
  pickable: true,
  autoHighlight: true
});
map.addLayer(deckLayer);
```

## 四、常见 Deck 图层

| 图层 | 用途 |
|---|---|
| `ScatterplotLayer` | 散点（可交互） |
| `ArcLayer` | 弧线 |
| `LineLayer` | 直线 |
| `PolygonLayer` | 多边形 |
| `HexagonLayer` | 蜂窝聚合 |
| `HeatmapLayer` | 热力图 |
| `TripsLayer` | 时序轨迹动画 |
| `ColumnLayer` | 3D 柱状 |
| `PathLayer` | 路径 |

## 五、数据坐标

Deck.GL 默认使用 **经纬度 [lng, lat]**。所以 CAD 坐标要：

```js
const deckPoints = cadPoints.map(p => map.toLngLat(p));
```

## 六、3D / 俯仰角

Deck.GL 支持 `pitch`，但必须 `map.getPitch() > 0`。

```js
const map = new vjmap.Map({ ..., pitch: 60 });
```

## 七、与 vjmap 样式协同

- Deck 图层默认在 vjmap 所有层之上。
- 通过 `map.addLayer(deckLayer, beforeId)` 插入到指定位置。

## 八、性能

- 大数据量（>10 万点）用 `HexagonLayer` / `HeatmapLayer` 聚合。
- 开 `pickable: false` 不交互时快很多。
- 关闭 `autoHighlight`。

## 九、常见坑

1. **坐标传 CAD 原值**（上百万）→ Deck 直接画在"错误的地理位置"（地球外）。必须 `map.toLngLat`。
2. **没 `await map.onLoad`**：直接 addLayer 会失败。
3. **Deck script 未加载完就 new**：通过 `typeof deck !== "object"` 守卫。
4. **Deck 图层遮挡交互**：`pickable: true` 时会拦截 mousemove，导致 vjmap 自己的 hover 不触发。
