> **本文回答**：图例 / 指北针 / 比例尺 / 鹰眼图 等常用控件叠加。

## 一、vjmap 内置控件

| 控件 | 说明 |
|---|---|
| `vjmap.NavigationControl` | 缩放 + 旋转 |
| `vjmap.ScaleControl` | 比例尺 |
| `vjmap.FullscreenControl` | 全屏 |
| `vjmap.AttributionControl` | 版权信息 |
| `vjmap.MousePositionControl` | 鼠标坐标 + zoom 显示（vjmap 扩展） |
| `vjmap.MiniMapControl` | 鹰眼小地图（vjmap 扩展） |
| `vjmap.ButtonGroupControl` | 按钮组控件（vjmap 扩展） |
| `vjmap.GeolocateControl` | GPS 定位 |

## 二、使用

```js
map.addControl(new vjmap.NavigationControl(), "top-right");
map.addControl(new vjmap.ScaleControl({ maxWidth: 100, unit: "metric" }));
map.addControl(new vjmap.MousePositionControl({ showZoom: true, showLatLng: true }), "bottom-left");
map.addControl(new vjmap.FullscreenControl());
```

## 三、图例（Legend）

vjmap 没有内置图例控件，通常自建 div：

```html
<div id="legend" style="position: absolute; bottom: 20px; right: 20px; background: #fff; padding: 8px; border-radius: 4px;">
  <div><span style="display:inline-block;width:12px;height:12px;background:#f00"></span> 一级管线</div>
  <div><span style="display:inline-block;width:12px;height:12px;background:#0f0"></span> 二级管线</div>
</div>
```

## 四、指北针

vjmap 未单独提供指北针控件，但 `NavigationControl` 自带旋转按钮（随 bearing 转动）。

独立指北针：

```html
<div id="compass" style="position: absolute; top: 20px; left: 20px; width: 48px; height: 48px; background: url('compass.svg') no-repeat center / contain"></div>
```

```js
map.on("rotate", () => {
  document.getElementById("compass").style.transform = `rotate(${-map.getBearing()}deg)`;
});
```

## 五、比例尺

vjmap 内置：

```js
map.addControl(new vjmap.ScaleControl({
  maxWidth: 100,
  unit: "metric"          // "imperial" / "nautical" 等
}));
```

对 **CAD 地图**，比例尺单位需按 CAD 图的单位（米 / 毫米）。可用自定义：

```js
class CadScaleControl {
  onAdd(map) {
    this.map = map;
    this.container = document.createElement("div");
    this.container.className = "vjmapgis-ctrl vjmapgis-ctrl-scale";  // vjmap 控件类前缀是 vjmapgis-ctrl-*
    map.on("move", this.update.bind(this));
    this.update();
    return this.container;
  }
  update() {
    const width = 100;
    const p0 = this.map.unproject([0, 0]);
    const p1 = this.map.unproject([width, 0]);
    const prj = this.map.getMapProjection();
    const cadDist = prj.fromLngLat(p1).sub(prj.fromLngLat(p0)).mag();  // GeoPoint: sub/mag（无 length()）
    this.container.innerText = `${cadDist.toFixed(2)} 单位 / 100px`;
  }
  onRemove() {
    this.container.parentNode.removeChild(this.container);
  }
}
map.addControl(new CadScaleControl(), "bottom-left");
```

> **说明**：上面 `className` 是 CSS 类名；vjmap 底层也会给内置控件打 `vjmapgis-ctrl` / `vjmapgis-ctrl-group` 等类名，DevTools 里都能看到，自定义控件建议沿用同样的类名以复用样式。

## 六、鹰眼（小地图）

内置 `vjmap.MiniMapControl`（见 [interaction/controls](../interaction/controls.md) 第六节，`containerStyle` 可配缩放/位置）：

```js
map.addControl(new vjmap.MiniMapControl({
  containerStyle: { transform: "scale(0.6)", transformOrigin: "100% 0%" }
}), "top-right");
```

## 七、常见坑

1. **控件重叠**：多个控件都放 `top-left`。选不同位置或自定义 DOM。
2. **控件 CSS 没加载**：vjmap 的样式文件 `vjmap.min.css` 必须引入，否则缩放按钮不显示。
3. **CSS 样式被覆盖**：项目里写了 `.vjmapgis-ctrl button { ... }` 的全局样式可能影响；用 `:scope` 或更具体的选择器。
4. **Ant Design 等 UI 库**：控件可能被遮挡；z-index 设 > ant 组件。
