> **本文回答**：`createMapDataHider` / `MapEntityHider` —— 把 DWG 原图里的实体"用样式隐藏"，避免 SDK 接管后双重显示；栅格 / 矢量底图双模式。

## 一、为什么需要

查出实体 → 加动画 → 但原图还在 → 画面上有两份 → 需要隐藏原图那份。

但**不是 "删除"**，是"样式级隐藏"，可逆，也不影响底图其它内容。

## 二、创建

```js
const hider = mapcadLayer.createMapDataHider();
// 等价 new vjmapext.MapEntityHider(map)
```

它会自动识别当前底图模式：

| 底图 | 机制 |
|---|---|
| 栅格（`svc.rasterStyle()`） | `map.updateStyle(svc, { expression: "if(gInObjectId in 'id1||id2'){...}" })`，后端表达式排除后瓦片重拉 |
| 矢量（`svc.vectorStyle()`） | `map.setFilterEx(layers, ['!', ['match', ['id'], ids, true, false]])`，前端过滤 |

## 三、核心 API

```ts
type HideItem =
  | string                                    // 栅格 objectid
  | number                                    // 矢量 feature.id
  | { id?, objectid? }
  | GeoJSON.Feature;                          // 推荐，两种 id 自动抽取

hider.hide(items): Promise<void>
hider.show(items): Promise<void>
hider.clear(): Promise<void>
hider.getHiddenIds(): string[]                // 栅格 objectid
hider.getHiddenFeatureIds(): number[]         // 矢量 feature.id
hider.isHidden(id): boolean
hider.refresh(): Promise<void>
hider.mode: 'raster' | 'vector'
```

## 四、基本使用

```js
// 1. 查
const fc = await mapcadLayer.queryMapEntities({ entTypes: ['AcDbText'] });

// 2. 隐藏（直接传 Feature，兼容两种底图）
const hider = mapcadLayer.createMapDataHider();
await hider.hide(fc.features);

// 3. 用 SDK 实体重绘
mapcadLayer.featuresToEntities(fc).forEach(e => mapcadLayer.addEntity(e));

// 4. 恢复原图
await hider.clear();
```

## 五、栅格 vs 矢量的关键差异

| 模式 | 过滤字段 | 类型 | 来源 |
|---|---|---|---|
| 栅格 | `gInObjectId` | 字符串 `'9BE_2'` | `feature.properties.objectid` |
| 矢量 | `['id']` | 数字 `1234` | `feature.id`（DB 主键） |

**警告**：只传 `objectid` 数组给 `hide()`：

- 栅格下生效
- **矢量下命中不到**（`['match', ['id'], ['9BE_2'], ...]` 永远 false）→ 看起来"没效果"

**解决**：**传 Feature 对象**，两种 id 都带着。

## 六、多个 hider 独立管理

```js
const textHider = mapcadLayer.createMapDataHider();
const roadHider = mapcadLayer.createMapDataHider();

await textHider.hide(textFeatures);
await roadHider.hide(roadFeatures);

// 导出时分别传：
await mapcadLayer.exportDwg({ hider: textHider });   // 只删文字
await mapcadLayer.exportDwg({ hider: roadHider });   // 只删道路
```

**注意：多 hider 是"后写覆盖"不是合并**。栅格模式下所有 hider 默认写同一个 `styleName`（`myCustomStyle_temp`）的样式，矢量模式下 `setFilterEx` 也是整体替换——**最后一次 `refresh()` 生效，之前 hider 的隐藏会被顶掉**。要并存请给每个 hider 传不同 `styleName`（栅格）或干脆**只用一个 hider** 管理所有隐藏 id。

## 七、配合 exportDwg（导出时删除）

```js
await mapcadLayer.exportDwg({ hider });              // 自动删除源图中被 hider 隐藏的实体
await mapcadLayer.exportDwg({ hider, deleteFromSource: false }); // 仅导出，不删源
```

见 [backend/export-dwg](../../../vjmap/references/backend/export-dwg.md) 的 `deleteObjectIds` / `onBeforeUpdate` 钩子。

## 八、栅格底图耗时

栅格模式下 `hide` 会触发后端瓦片重拉（瓦片里少了被隐藏的实体），通常 300 ~ 800 ms；期间画面会有一次闪。

想避免闪烁：

```js
const canvas = map.getCanvas();
canvas.style.opacity = 0.3;
await hider.hide(fc.features);
canvas.style.opacity = 1;
```

## 九、矢量底图瞬时

矢量模式是前端 filter 表达式，1 万 id 内基本瞬时；更大量级（10+ 万 id）时 filter 本身可能慢。

超大量级时可考虑：

- 分组 hide：一次 1 万
- 改用 CSS opacity 方案
- 用 feature-state + 样式表达式把实体变透明：

```js
fc.features.forEach(f => map.setFeatureState({ source: 'vec', id: f.id }, { hidden: true }));
// layer 样式里：
// lineOpacity: ['case', ['boolean', ['feature-state', 'hidden'], false], 0, 1]
```

## 十、常见坑

1. **只传 objectid → 矢量不生效**：务必传 Feature 对象。
2. **栅格模式 hide 后画面闪一下**：瓦片重拉；上面 opacity 技巧或用矢量底图。
3. **连续 hide 多次**：每次都会触发样式刷新；收集好 features 再一次 hide。
4. **hider 丢失引用**：GC 后无法 clear；用全局 Map 持有。
5. **导出时忘了 hider**：导出的 DWG 里既有原实体又有 SDK 实体 → 双份。

## 相关

- 查询 → [mapdata-query](mapdata-query.md)
- 转实体 → [features-to-entities](features-to-entities.md)
- 导出 → [backend/export-dwg](../../../vjmap/references/backend/export-dwg.md)
