> **本文回答**：绘图捕捉 / 正交 / 对齐辅助线（guides），`snapOptions` 与 Alt / Ctrl / Backspace 快捷键。

## 一、开启捕捉

```js
const draw = new vjmap.Draw.Tool({
  snap: true,             // 对象捕捉
  guides: true,           // 对齐辅助线：经过附近已有顶点的水平 / 竖直参考线（不是网格）
  snapOptions: {
    snapPx: 15,            // 捕捉像素阈值（⚠️ CAD GeoProjection 下有效半径仅 ~5-10px，
                           //  且 zoom 无关——阈值换算用标准 mercator 米、距离量算走 CAD unproject，
                           //  两条缩放律不抵消；要更大半径需把 snapPx 调大约 2 倍）
    snapToMidPoints: false, // 是否捕捉中点
    snapVertexPriorityDistance: 1.25,  // 顶点优先距离
    snapGridPx: 2000       // 辅助线半长（像素），默认 2000
  }
});
```

在 action API 里通过 `api.getSnapFeatures`：

```js
await vjmap.Draw.actionDrawPoint(map, {
  api: { getSnapFeatures: snapObj }    // snapObj.features 是要捕捉的要素数组
});
```

## 二、快捷键（绘图时）

| 键 | 动作 |
|---|---|
| `Alt` | 按住期间禁用捕捉（移动返回原始鼠标位，不吸附） |
| `Ctrl` | 临时启用正交（当前点与前一顶点**像素** x\|y 取差小者对齐，非地理方向） |
| `Backspace` | 删除最后一个点（`map.setCustomKeyValue("_disable_drawkey_backspacekey", true)` 可禁用——**须严格布尔 `true`**，字符串 `"true"` 不生效） |
| `ESC` | 取消 |
| `Enter` | 结束（顶点不足时 resolve `{cancel:true}`） |

## 三、捕捉标记样式

捕捉指示不是 `meta` 属性——源码里 guide 要素带 `properties.isSnapGuide: "true"`（捕捉节点 id 为 `SNAPNODE_GUIDE`，对齐辅助线（guides）id 为 `VERTICAL_GUIDE`/`HORIZONTAL_GUIDE`）。内置样式对 `isSnapGuide=="true"` 的 LineString 画一条红色虚线（`guide` 图层）。

要自定义捕捉节点点样式，往 `opts.styles` 追加一个 filter 命中 `isSnapGuide` 的 Point 图层：

```js
const opts = vjmap.cloneDeep(vjmap.Draw.defaultOptions());   // defaultOptions 是浅拷贝，styles 全局共享，须深拷贝
opts.styles.push({
  id: "my-snap-point",
  type: "circle",
  filter: ["all", ["==", "$type", "Point"], ["==", "isSnapGuide", "true"]],
  paint: { "circle-radius": 6, "circle-color": "#ff0000" }
});
const draw = new vjmap.Draw.Tool(opts);
```

## 四、捕捉源

### 1. 捕捉 CAD 图上的点线（栅格模式）

```js
const snapObj = { features: [] };
const res = await svc.conditionQueryFeature({
  fields: "s3", condition: "s3 != ''", limit: 100000
});
for (const item of res.result) {
  const pts = item.s3.split(";").map(p => p.split(",").map(Number));
  const coords = pts.filter(p => p.length >= 2).map(([x, y]) => map.toLngLat([x, y]));
  if (coords.length === 1) {
    snapObj.features.push({ type: "Feature", geometry: { type: "Point", coordinates: coords[0] } });
  } else if (coords.length > 1) {
    snapObj.features.push({ type: "Feature", geometry: { type: "LineString", coordinates: coords } });
  }
}
```

### 2. 捕捉矢量样式内已渲染要素

```js
snapObj.features = map.queryRenderedFeatures({ layers: ["vector-layer-lines"] });
```

### 3. 捕捉 Draw 工具里自己绘制的要素

通过 `draw.getAll()` 取出给下一个绘制：

```js
const snapFeatures = draw.getAll().features;
await vjmap.Draw.actionDrawLineSting(map, { api: { getSnapFeatures: { features: snapFeatures } } });
```

## 五、禁用某实体捕捉

```js
draw.setFeatureProperty(featureId, "noSnap", true);
```

## 六、正交模式

按住 `Ctrl` 时，下一个点强制水平 / 垂直相对视口（不是地理方向）。程序内无直接 API，可通过样式或自己判断移动方向。

## 七、捕捉性能

- `getSnapFeatures` 数据量大（>1 万要素）时，绘制每帧都会全量遍历 → 可以只保留视口内 features。
- 仅在绘制开始前填 `snapObj.features`，绘制过程中避免频繁 push。

## 八、自定义捕捉回调

当前发布版**没有** `onSnap` 回调（运行时与 d.ts 均不存在）——`api.getSnapFeatures` 是唯一注入点；要"命中即知"可在 `updatecoordinate` 回调里自行对 `snapObj.features` 做最近点判定。

## 九、对齐辅助线（guides，不是网格捕捉）

`guides: true` 时，鼠标接近某个已有顶点的 x 或 y 时，画一条经过该顶点的竖直 / 水平参考线（内置按钮"捕捉网格"`snap_mode_grid` 开关的就是它）；**没有按像素间距的网格捕捉**。`snapGridPx` 只是参考线的半长（像素）：

```js
const draw = new vjmap.Draw.Tool({
  guides: true,
  snapOptions: { snapGridPx: 500 }   // 参考线向两侧各延伸 500px
});
```

## 十、常见坑

1. **绘制速度变慢** → 捕捉要素过多；按视口范围裁剪。
2. **CAD 文字位置捕不到**：因为 s3 字段未包含文字；测量工具可能需额外查询 Text 实体。
3. **不同图之间共享 snapObj** → 坐标系不同会偏移；每张图独立。
4. **Alt 释放后捕捉消失**：这是临时切换的预期行为。
